
原創(chuàng)作者:Piyush Sharma
原文鏈接:https://medium.com/@piyush.dez/ios-architectures-5a19cd56edc2
一個好架構(gòu)的特質(zhì):
- 每個對象應該有清晰的角色
- 能夠輕松地跟蹤數(shù)據(jù)流
- 不應該依賴于特定的框架
- 靈活,因為它簡單,而不是因為我們使用了太多的抽象
- 關注分離
- 可測試的
- 明確界限,一個對象應該只對一件事負責
為什么我們需要一個好架構(gòu)?
如果你正在debug一個有不同實現(xiàn)的巨大的類,你將會發(fā)現(xiàn)你自己很難在這個類找到導致bug的原因,并且修復它。你會遇到的大部分常見的問題:
- 你的數(shù)據(jù)直接在
UIViewController中存儲 - 你的
UIViews做了太多的事情 -
Model是個簡單的啞模型 - 你的單元測試其實沒有覆蓋到什么
所以應對這種復雜情況最簡單的方法就是按照 單一功能原則 在多個實體之間劃分責任。
受歡迎的架構(gòu)模式:MVC,MVP,MVVM,VIPER,VIP
首先,我們把整個項目劃分為3個實體:
- Model —— Model 就是用來數(shù)據(jù)存儲。持久化代碼,模型對象,解析器,幫助程序、擴展、常量和網(wǎng)絡代碼都在其中。
網(wǎng)絡代碼(Network code):你可能會使用一個單例類用于整個app的網(wǎng)絡通信,包括網(wǎng)絡請求,響應,還有錯誤處理。
持久化代碼(Persistence code):你使用這個部分代碼當需要持久化數(shù)據(jù)到數(shù)據(jù)庫,Core Data,或者保存數(shù)據(jù)到設備。
解析代碼(Parsing code):你應該會在Model層中包含解析網(wǎng)絡響應的對象。例如,在Swift model對象中,你能用 JSON encoding/decoding 來進行解析處理。這樣的話,一切都是自我包含,解析的時候,網(wǎng)絡層不必知道所有的Model細節(jié)。業(yè)務邏輯和解析邏輯都包含在Model里面。
管理者和抽象類(Managers and abstraction classes):每個人都使用它們,需要它們,但沒人知道它們叫什么或者它們屬于哪里。它通常有典型的 “manager” 對象,用于連接其他的類。
Views —— view 層是我們app的表層。它的類如果沒有包含任何特定領域邏輯的話通常都是可以復用的。比如,
UILabel是一個可以在屏幕上展示文本的view,并且它是可復用和擴展的。Controller/Presenter/ViewModel —— 把 controller 層當作app的大腦,或者引擎;它決定了下一步會發(fā)生什么。controller通過委托模式在視圖和模型之間進行調(diào)解。controller實體是不知道正在處理的view的具體實現(xiàn)。相反,它將通過協(xié)議和抽象層進行通信。一個經(jīng)典的例子就是
UITableView和它的數(shù)據(jù)源是通過UITableViewDataSource協(xié)議進行通信的。
MVC

Controller是View和Model之間的調(diào)度者,所以View和Model并不知道對方的存在。

Cocoa MVC 鼓勵我們寫“復雜”的 View Controller,因為它們與View的生命周期息息相關,很難說它們是分離的。

View Controller 最終成為一個委托和所有東西的數(shù)據(jù)源,通常負責調(diào)度和取消網(wǎng)絡請求。
MVVM
View 和 ViewController 進行互動,ViewController 又和 ViewModel 互動,然后 ViewModel 會和其他的 helpers,managers 存在關聯(lián)。

VIPER
這個架構(gòu)強制以結(jié)構(gòu)式的方式編寫代碼,并將ViewController 的職責劃分到更小的對象上。

Interactor —— 包含與數(shù)據(jù)(實體)或網(wǎng)絡相關的業(yè)務邏輯,如創(chuàng)建實體的新實例或從服務器獲取實體。出于這些目的,你將使用一些服務和管理器,它們不是VIPER模塊的一部分,而是外部依賴項。交互器中完成的工作應該獨立于任何UI。
Presenter —— Presenter主要由驅(qū)動UI的邏輯組成。它知道何時呈現(xiàn)用戶界面。它從用戶交互中收集輸入,以便更新UI并向 Interactor 發(fā)送請求。演示者還從 Interactor 接收結(jié)果,并將結(jié)果轉(zhuǎn)換為有效地顯示在視圖中的形式。它將處理數(shù)據(jù)并決定向用戶顯示什么。
View —— 它等待Presenter給它內(nèi)容顯示; 它從不要求 Presenter 提供數(shù)據(jù)。Presenter 不知道UILabel, UIButton等的存在,它只知道它所維護的內(nèi)容以及它應該在什么時候顯示。由 View 決定如何顯示內(nèi)容。
Entities —— Entities 是由 Interactor 操作的模型對象。Interactor 從不將Entities傳遞給顯示層(如Presenter)。
Router —— 負責VIPER模塊之間的segue。View Controller不應該知道下一個View Controller是什么,以及如何設置它。由于Presenter包含對用戶輸入作出響應的邏輯,所以是Presenter知道何時導航到另一個屏幕,以及導航到哪個屏幕。它們共同描述了從一個屏幕到下一個屏幕的路線。
由 Interactor 進行網(wǎng)絡操作,但它不會直接處理網(wǎng)絡代碼。它會詢問一個依賴類,比如network manager 或者 API client。Interactor 可能必須合并來自多個源的數(shù)據(jù),以提供滿足用例所需的信息。然后由Presenter 獲取 Interactor 返回的數(shù)據(jù)并將其格式化以供演示。
數(shù)據(jù)存儲負責向 Interactor 提供實體。當 Interactor 應用其業(yè)務邏輯時,它將需要從數(shù)據(jù)存儲中檢索實體,操作實體,然后將更新后的實體放回數(shù)據(jù)存儲中。數(shù)據(jù)存儲管理實體的持久性。Entities 不知道數(shù)據(jù)存儲,因此Entities不知道如何持久化它們自己。Interactor 也不應該知道如何持久化實體。
有時,Interactor 可能希望使用一種稱為數(shù)據(jù)管理器(data manager)的對象類型來促進其與數(shù)據(jù)存儲的交互。數(shù)據(jù)管理器處理更多特定于存儲的操作類型,如創(chuàng)建獲取請求、構(gòu)建查詢等。這使得 Interactor 可以更多地關注應用程序邏輯,而不必了解如何收集或持久化實體。
簡潔的Swift架構(gòu)(VIP)
view controller, interactor 和 presenter 是 VIP 架構(gòu)中三個主要的部分。

一個典型的場景是,如果用戶點擊應用程序用戶界面中的一個按鈕。view controller構(gòu)造一個請求對象并將其發(fā)送給interactor。interactor接受請求對象并執(zhí)行一些工作。然后將結(jié)果放入響應對象中,并將其發(fā)送給presenter。presenter獲取響應對象并格式化結(jié)果。然后將格式化的結(jié)果放入View Model對象中,并將其發(fā)送回view controller。最后,view controller將結(jié)果顯示給用戶。

VIP 很好地劃分了組件的職責。view controller 通過發(fā)送請求直接與 interactor 交互。interactor調(diào)用worker的方法,worker執(zhí)行一些工作,并通過向presenter發(fā)送帶有數(shù)據(jù)模型的響應來返回interactor響應的這些請求。presenter格式化要顯示的數(shù)據(jù),創(chuàng)建一個View Model,并通知view controller它應該基于View Model更新它的視圖。view controller通過調(diào)用Router上的方法來決定何時導航到不同的場景。Router執(zhí)行下一個視圖控制器的設置,并處理連接、傳遞數(shù)據(jù)和委托設置。