本文檔收集了這些年來我們使用Katana定義的最佳實(shí)踐和準(zhǔn)則。
項(xiàng)目中定義和共享準(zhǔn)則和最佳實(shí)踐的優(yōu)點(diǎn):
1. 當(dāng)做一件事有多種相同的方法時(shí)塔嬉,選擇一種方法并保持一致可以讓每個(gè)人立即了解事情是如何工作的,以及如何向應(yīng)用程序或庫(kù)引入更改,即使他們并不熟悉代碼庫(kù)。
2.?通過遵循共享的模式,我們可以在假設(shè)某些事情是以特定的方式完成的情況下實(shí)現(xiàn)工具恭取。
3.?在審查Pull請(qǐng)求時(shí),可以利用指導(dǎo)方針來提供有效的反饋熄守。
4.指南所保留的統(tǒng)一的書面知識(shí)蜈垮,新手們可以領(lǐng)先一步。
Guidelines
使用管理器來封裝邏輯
為了實(shí)現(xiàn)代碼的盡可能高的模塊化和可重用性裕照,我們定義了對(duì)象攒发,我們稱之為Manager。Manager負(fù)責(zé)處理業(yè)務(wù)邏輯的特定部分晋南。例如惠猿,健身應(yīng)用可能需要一個(gè)登錄管理器、一個(gè)計(jì)劃生成器负间,甚至需要更通用的邏輯來執(zhí)行API調(diào)用或跟蹤用戶指標(biāo)偶妖。
依賴容器負(fù)責(zé)啟動(dòng)這些管理器,并將它們暴露給Katana的Side Effects政溃。以下是創(chuàng)建管理器時(shí)需要遵循的一些指導(dǎo)方針:?
1.管理者是“被動(dòng)的”趾访,他們被Katana的?Side Effects所調(diào)用,他們不應(yīng)該以任何方式與武士刀交互(也就是說董虱,他們不能分派)
2.管理器既不能訪問存儲(chǔ)getState扼鞋,也不能訪問分派
3.管理器不應(yīng)該包含狀態(tài)。函數(shù)執(zhí)行計(jì)算所需的所有信息都作為參數(shù)傳遞愤诱。
4.管理者可能需要使用其他管理者來實(shí)現(xiàn)他們的部分邏輯藏鹊。我們稱這些下屬管理者為依賴關(guān)系。在初始化管理器時(shí)转锈,依賴項(xiàng)應(yīng)該作為參數(shù)傳遞。
在命名約定方面楚殿,作為管理器的類應(yīng)該使用Manager后綴命名撮慨。舉個(gè)具體的例子竿痰,Login不是一個(gè)有效的管理器名,而LoginManager是砌溺。
Event Observers
Katana?提供了一個(gè)攔截器影涉,可以用來觀察以下事件:
1.狀態(tài)變化,
2.一個(gè)狀態(tài)更新器或一個(gè)副作用已經(jīng)被發(fā)送规伐,
3.通知是否已經(jīng)被發(fā)布
有時(shí)這是不夠的蟹倾,我們需要觀察外部世界,并把我們從這個(gè)觀察中得到的信息帶回Katana的世界猖闪。正如指南(1)中所討論的鲜棠,管理器是應(yīng)用程序的被動(dòng)成員,因此它們不能分派培慌。為了解決這個(gè)特定的用例豁陆,我們引入了event observers。這些類是由依賴容器創(chuàng)建和擁有的吵护,它們唯一且唯一的職責(zé)是監(jiān)聽來自外部世界(例如盒音,F(xiàn)irebase、Websockets等等)的事件馅而,并在這個(gè)事件之后在Katana世界中分派一些東西祥诽。
雖然分開管理者(Manager)和Observers?可能看起來很奇怪,但這實(shí)際上有助于保持每個(gè)部分的簡(jiǎn)單和一致瓮恭。對(duì)于簡(jiǎn)單的情況使用管理器雄坪,對(duì)于更復(fù)雜的情況使用event observer。
在命名約定方面偎血,作為eventtobservers的類應(yīng)該使用Observer后綴命名诸衔。舉個(gè)具體的例子,HealthKit不是一個(gè)有效的觀察者名颇玷,而HealthKitObserver是笨农。
Avoid complex Side Effects(避免復(fù)雜的Side Effects)
在編寫應(yīng)用程序的邏輯時(shí),可能會(huì)創(chuàng)建一些高度靈活的Side Effects帖渠,這些Side Effects需要多個(gè)輸入(即谒亦,實(shí)現(xiàn)Side Effects的結(jié)構(gòu)有幾個(gè)參數(shù)),并根據(jù)這些輸入實(shí)現(xiàn)不同的東西空郊。
邏輯被封裝在分組的份招、可重用的函數(shù)中。這意味著您應(yīng)該盡量使Side Effects簡(jiǎn)單狞甚,并盡可能接近管理器功能和分派的簡(jiǎn)單鏈接锁摔。
關(guān)于在另一個(gè)Side Effects中發(fā)送一個(gè)Side Effects,應(yīng)該盡可能避免哼审,因?yàn)檫@會(huì)使整個(gè)邏輯更加難以遵循谐腰。如果您最終處于這種情況孕豹,請(qǐng)嘗試查看您的代碼,并考慮更多地利用管理員十气。
Leverage encapsulation, modularisation and visibility modifiers(利用封裝励背、模塊化和可見性修飾符)
應(yīng)用程序是由相互協(xié)作的獨(dú)立邏輯部分組成的。在編寫應(yīng)用程序邏輯時(shí)砸西,應(yīng)該創(chuàng)建名稱空間(模塊)叶眉,反映這些名稱空間中的劃分和組狀態(tài)更新器以及Side Effects。
Documentation
文檔是應(yīng)用程序中非常重要的部分芹枷。擁有出色的文檔衅疙,其他開發(fā)人員可以輕松進(jìn)入您的代碼庫(kù),并更快地提高生產(chǎn)力杖狼。
上面一條準(zhǔn)則定義了邏輯模塊的公共接口的概念炼蛤。在將該準(zhǔn)則應(yīng)用于代碼時(shí),還應(yīng)確保正確記錄了“公共接口”蝶涩。好的文檔應(yīng)包括:
1.功能/副作用/狀態(tài)更新程序的功能說明
2.參數(shù)說明
3.前提條件(如果有)
4.在編寫代碼時(shí)所做的假設(shè)
5.代碼無法輕易推斷出的任何其他信息理朋,這些信息在使用代碼或需要更改代碼時(shí)都非常有用
Project files structure (項(xiàng)目文件結(jié)構(gòu))
ProjectName
? ? |-- Logic
? ? ? ? ? |-- AppDependenciesContainer.swift
? ? ? ? ? |-- Home
? ? ? ? ? ? ? ? |-- HomeDispatchable.swift? // side effects and state updaters? ? ? ?
? ? ? ? ? |-- Login
? ? ? ? ? ? ? ? |-- LoginDispatchable.swift // side effects and state updaters
? ? ? ? ? ? ? ? |-- LoginManager.swift
? ? ? ? ? |-- PlanGenerator
? ? ? ? ? ? ? ? |-- PlanGeneratorDispatchable.swift // side effects and state updaters
? ? ? ? ? ? ? ? |-- PlanGeneratorModels.swift
? ? ? ? ? ? ? ? |-- PlanGeneratorManager.swift
? ? |-- UI
? ? ? ? ? |-- Login
? ? ? ? ? ? ? ? |-- LoginVC.swift
? ? ? ? ? ? ? ? |-- LoginView.swift?
? ? ? ? ? |-- Home
? ? ? ? ? ? ? ? |-- HomeVC.swift
? ? ? ? ? ? ? ? |-- HomeView.swift? ?
? ? ? ? ? ? ? ? |-- HomeVM.swift
? ? |-- State
? ? ? ? ? |-- AppState.swift? ?
如您所見,主文件夾包含3個(gè)主文件夾:邏輯绿聘,UI和狀態(tài)嗽上。
邏輯文件夾包含應(yīng)用程序的所有邏輯(狀態(tài)更新程序,副作用和管理器)以及依賴項(xiàng)容器熄攘。
即使所有邏輯都在一個(gè)文件中(例如Home.swift兽愤,它具有與Home視圖控制器嚴(yán)格相關(guān)的副作用),也應(yīng)該將該文件包含在文件夾中以方便搜索挪圾,而不必猜測(cè)它是文件夾還是文件夾浅萧。一份文件≌芩迹總體邏輯應(yīng)包含副作用洼畅,狀態(tài)更新程序,管理器和與邏輯相關(guān)的模型棚赔。
State文件夾包含該狀態(tài)一部分的所有結(jié)構(gòu)帝簇。請(qǐng)注意,遵循?準(zhǔn)則(4)靠益,您可能希望將狀態(tài)與邏輯共同定位丧肴,以對(duì)代碼實(shí)施某種信息隱藏技術(shù)(即,將某些變量設(shè)為私有或文件私有)胧后。這是唯一允許的例外芋浮。