iOS架構模式初探

一個項目的架構模式選擇有多種,Apple推薦的MVC模式是被大多數開發者所選用的,後來又慢慢瞭解到MVP,MVVM,以及VIPER。
下面是我對這些模式特性以及適用情景的理解,歡迎各位大神一起探討。

一個好的架構應該具備的特點:

  1. 任務均衡分攤給具有清晰角色的實體
  2. 可測試性通常都來自與上一條(對於一個合適的架構是非常容易)
  3. 易用性和低成本維護

MVC。MVP。MVVM都把應用中的實體分爲以下三類:

  • Models–負責主要的數據或者操作數據的數據訪問層,可以想象 Person 和 PersonDataProvider 類。
  • Views–負責展示層(GUI),對於iOS環境可以聯想一下以 UI 開頭的所有類。
  • Controller/Presenter/ViewModel–負責協調 Model 和
    View,通常根據用戶在View上的動作在Model上作出對應的更改,同時將更改的信息返回到View上。

將實體劃分可以更好的理解它們之間的關係,進行復用(尤其是對於View和Model),進行獨立的測試。

1.最通用的MVC
最傳統的MVC下的View沒有任何界限,只是簡單的在Controller中呈現model的變化。傳統的MVC之間相互都有通信,耦合度很高,複用性較低。
蘋果官方推薦的MVC希望Controller是一個介於View 和 Model之間的協調器,所以View和Model之間沒有任何直接的聯繫。Controller是一個最小可重用單元,三者之間關係如下:
MVC

而事實上,如果嚴格按照採用這種格式,將業務邏輯和數據轉換到Model,View的最大的任務就是向Controller傳遞用戶動作事件。ViewController最終會承擔一切代理和數據源的職責,還負責一些分發和取消網絡請求以及一些其他的任務。
事實上我們很多次會把給視圖控件賦值的邏輯寫在View裏,由View直接來調用Model,比如
cell.productModel = tadArray[indexPath.row];
如果嚴格遵守MVC的話,就會把對cell的設置放在 Controller 中,不向View傳遞一個Model對象,這樣就會大大增加Controller的體積,使Controller變得更加臃腫。而Controller和View的高度耦合,也使單元測試變得更加艱難,需要有足夠的創造性來模擬View和它 們的生命週期。

2.實現了Cocoa願景的MVP
MVP是第一個如何協調整合三個實際上分離的層次的架構模式。
這裏寫圖片描述
看起來跟MVC沒什麼區別,但在MVP裏,Presenter完全把Model和View進行了分離,主要的程序邏輯在Presenter裏實現。而且,Presenter與具體的View是沒有直接關聯的,而是通過定義好的接口進行交互,從而使得在變更View時候可以保持Presenter的不變,即重用! 不僅如此,我們還可以編寫測試用的View,模擬用戶的各種操作,從而實現對Presenter的測試–而不需要使用自動化的測試工具。 我們甚至可以在Model和View都沒有完成時候,就可以通過編寫Mock Object(即實現了Model和View的接口,但沒有具體的內容的)來測試Presenter的邏輯。 在MVP裏,應用程序的邏輯主要在Presenter來實現,其中的View是很薄的一層。因此就有人提出了Presenter First的設計模式,就是根據User Story來首先設計和開發Presenter。在這個過程中,View是很簡單的,能夠把信息顯示清楚就可以了。在後面,根據需要再隨便更改View,而對Presenter沒有任何的影響了。 如果要實現的UI比較複雜,而且相關的顯示邏輯還跟Model有關係,就可以在View和Presenter之間放置一個Adapter。由這個 Adapter來訪問Model和View,避免兩者之間的關聯。而同時,因爲Adapter實現了View的接口,從而可以保證與Presenter之間接口的不變。這樣就可以保證View和Presenter之間接口的簡潔,又不失去UI的靈活性。 在MVP模式裏,View只應該有簡單的Set/Get的方法,用戶輸入和設置界面顯示的內容,除此就不應該有更多的內容,絕不容許直接訪問Model–這就是與MVC很大的不同之處。
就MVP而言,UIViewController的子類實際上就是Views並不是Presenters。這區別使這種模式的可測試性變強,但代碼量更大,降低了開發速度,因爲必須要做一些手動的數據和事件綁定。
MVP的特性:

  • 任務均攤–我們將最主要的任務劃分到Presenter和Model,而View的功能較少(雖然上述例子中Model的任務也並不多)。
  • 可測試性–非常好,由於一個功能簡單的View層,所以測試大多數業務邏輯也變得簡單。
  • 易用性–在我們上邊不切實際的簡單的例子中,代碼量是MVC模式的2倍,但同時MVP的概念卻非常清晰。

    3.最新的MVVM

    除了固有的 Model和View外,VM即是ViewModel。
    這裏寫圖片描述
    如上圖所示,它和MVP模式非常像,都將ViewController視爲View,只是將原controller裏的邏輯處理移到了ViewModel裏, 所謂”邏輯部分”可以是各種delegate,網絡請求,緩存,數據庫,coredata等等。View 和Model之間沒有緊密的聯繫,也有像監管版本的MVP那樣的綁定功能,但這個綁定不是在View和Model之間而是在View和ViewModel之間。
    所謂綁定除了自己實現還有兩種選擇:

  • 基於KVO的綁定庫如 RZDataBinding 和 SwiftBond
  • 完全的函數響應式編程,比如像ReactiveCocoa、RxSwift或者 PromiseKit
    提到MVVM就會聯想到最近大熱的ReactiveCocoa,主要是因爲ReactiveCocoa能更好的發揮MVVM的特點。詳細請戳:iOS開發之ReactiveCocoa下的MVVM

(我們很容易想到把 UITableViewDataSource和UITableViewDelegate 的代碼提取出來放到一個單獨的類.
這裏有個demo把cell的生成, cell行高, 點擊等等抽象出來了 .還可以用block的形式使得函數能夠回調,感興趣可下載看看)
在MVVM下的三個特性評估:
- 任務均攤 –
在例子中並不是很清晰,但是事實上,MVVM的View要比MVP中的View承擔的責任多。因爲前者通過ViewModel的設置綁定來更新狀態,而後者只監聽Presenter的事件但並不會對自己有什麼更新。
- 可測試性 –
ViewModel不知道關於View的任何事情,這允許我們可以輕易的測試ViewModel。同時View也可以被測試,但是由於屬於UIKit的範疇,對他們的測試通常會被忽略。
- 易用性 –
在我們例子中的代碼量和MVP的差不多,但是在實際開發中,我們必須把View中的事件指向Presenter並且手動的來更新View,如果使用綁定的話,MVVM代碼量將會小的多。

MVVM集合了上述方法的優點,由於在View層的綁定它不需要其他附加代碼來更新View,且測試性依然很強。

4.VIPER–把LEGO建築經驗遷移到iOS app的設計
VIPER是iOS應用乾淨的架構的應用程序。VIPER對於圖層,交互,實體和路由來說是一個backronym。乾淨的架構將一個應用程序的邏輯結構劃分爲不同的層的責任,提供明確的應用程序邏輯和有關導航代碼的位置。這使得它更容易隔離依賴項(如數據庫)和測試之間的邊界的交互層。
VIPER在責任劃分層面進行了迭代,VIPER分爲五個層次:
這裏寫圖片描述

  • 交互器 – 包括關於數據和網絡請求的業務邏輯,例如創建一個實體(數據),或者從服務器中獲取一些數據。爲了實現這些功能,需要使用服務、管理器,但是他們並不被認爲是VIPER架構內的模塊,而是外部依賴。
  • 展示器 – 包含UI層面的業務邏輯以及在交互器層面的方法調用。
  • 實體 – 普通的數據對象,不屬於數據訪問層次,因爲數據訪問屬於交互器的職責。
  • 路由器 – 用來連接VIPER的各個模塊。
    與MV(X)系列相比,VIPER在任務均攤方面有一些不同:

  • Model 邏輯通過把實體作爲最小的數據結構轉換到交互器中。

  • Controller/Presenter/ViewModel的UI展示方面的職責移到了Presenter中,但是並沒有數據轉換相關的操作。
  • VIPER是第一個通過路由器實現明確的地址導航模式。

    VIPER模塊可以是一個屏幕或者用戶使用應用的整個過程–想想認證過程,可以由一屏完成或者需要幾步才能完成,取決於模塊大小。
    由上可見,VIPER的任務均攤特性很突出,而很好地分佈性就有更好的可測試性,但是易用性表現就弱了,維護成本較高,必須爲很小功能的類寫出大量的接口。所以現在應用VIPER架構還爲時過早大材小用,現在維護起來確實是有些不合理,考慮一些更爲簡單的模式可能會更好。

通過以上的對比分析,想必你跟我一樣對應用的架構有了一定的認知和了解,不再因爲MVC所以MVC了,其實選擇架構是一個根據實際情況具體分析利弊的過程,當然,在同一個應用中也可以根據頁面需要選擇多種不同的架構,但並沒有必要對那些在MVC模式下運轉良好的頁面進行重構,因爲二者是可以並存的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章