iOS開發--MVVM-R架構之美

MVVM-R
開發軟體就像搭建房子,一個好的架構設計,決定著房子搭建的速度、質量和高度。對於移動端開發來說,有常見的 MVC
、 MVP
、 MVVM
和 VIPER
等架構模式,這些架構有各自的優缺點,如何尋找合適的架構,這得結合當前的專案情況和期望。筆者這邊在綜合考慮各種因素之後,決定使用 MVVM-R
作為專案的開發架構。下面做下思考的過程。
一個好的架構應該具有的特徵:
- 職責單一
- 可測性
- 易用性
Apple 的 MVC
理想狀態

MVC.png
- Models(模型) - 資料層,提供對應的資料結構。比如 Person 類。
- Views(檢視) - 展示層(GUI)。對於 iOS 來說所有以 UI 開頭的類基本都屬於這層。
- Controller 控制器 - 它是 Model 和 View 之間的膠水或者說是中間人。一般來說,當用戶對 View 有操作時它負責去修改相應 Model ;當 Model 的值發生變化時它負責去更新對應 View 。
現實情況
Apple 的 MVC看上去挺美好的,View 和 Model 之間相互獨立的,只是通過 Controller 來相互聯絡。但是在實際的開發中,往往為了方便,views中還是會引入models進行賦值操作,而且Controller中會寫網路資料操作、業務邏輯操作和互動等等程式碼,顯得特別冗腫,不易擴充套件和後期維護。
對應說需要整合 單元測試 的來說,因為每個模組耦合太嚴重基本無法進行。
總結:
- 職責劃分:理想狀態下,View 和 Model 確實是實現了分離,但是 View 和 Controller 耦合的太厲害
- 可測性:因為劃分的不夠清楚,所以能測的基本就只有 Model 而已
- 易用:相較於其他模式,它的程式碼量最少。而且基本上每個人都很熟悉它,即便是沒太多經驗的開發者也能維護。
如果是對於小專案,只追求開發速度,則MVC可能是較佳的選擇。
MVP - 保證了職責劃分的(promises delivered) Cocoa MVC

MVP.png
- Models(模型) - 資料層,負責處理資料的資料介面層,包括網路請求和資料處理等。
- View/Controller - 展示層和互動層。MVP裡面的 View 和 Controller 是耦合緊密的,給Presenter提供檢視設定和互動的方法,沒有直接拿model進行賦值好操作,保持了很好的獨立性。
- Presenter - 它完全不關注 ViewController 的生命週期,裡面基本沒什麼佈局相關的程式碼,它的職責只是通過資料和狀態來呼叫View層提供的方法來更新UI。
MVP 架構擁有三個真正獨立的分層,V層通過提供方法,讓P層呼叫和賦值,M層只負責資料提供,具有很好的可測試性,但相對於MVC來說意味著巨大的程式碼量。
總結:
- 劃分: 我們把大部分的職責都分配到了 Presenter 和 Model 裡面,而 View 基本上不需要做什麼。
- 可測性:簡直棒,我們可以通過 View 來測試大部分的業務邏輯。
- 易用: MVP擁有清晰架構思路,但在程式碼量上會相對做出犧牲。
MVP 架構在 iOS 中意味著極好的可測性和巨大的程式碼量。
VIPER - 把搭建樂高積木的經驗應用到 iOS 應用的設計上

VIPER.png
VIPER的五層職責劃分:
- Entity(實體) :類似於MVC的Model,是一個純粹的資料結構物件。
- Interactor(互動器) :專門用來負責網路請求和資料處理。
- View/Controller(檢視) :負責UI的佈局和提供互動相關的方法,供Presenter呼叫。
- Presenter(展示器) :負責處理包括呼叫Interactor進行網路請求,根據狀態重新整理UI介面,根據使用者互動處理相關的業務邏輯等。
- Router(路由) : 主要負責 VIPER 模組之間的轉場和銜接。
總結:
- 劃分:毫無疑問的,VIPER 在職責劃分方面是做的最好的。
- 可測性:理所當然的,職責劃分的越好,測試起來就越容易。
- 易用:不難想象,上面兩點好處都是用維護性的代價換來的。一個小小的任務,可能就需要你為各種類寫大量的介面。
如果你的專案較大或未來會很大,VIPER可能是更好的選擇。
MVVM - 是 MV(X) 系列架構裡面最新興的,也是最出色的

MVVM.png
- Models(模型) - 資料模型,用來儲存資料。
- View/Controller(檢視) - 檢視介面,用來展示UI介面和響應使用者互動。
- ViewModel - 連結View和Model的橋樑,處理業務邏輯,更新Model的同時重新整理View。

ViewModel可以看做是MVC中對C層的一種優化和升級,把Controller的資料和邏輯處理部分從中抽離出來,用一個專門的物件去管理,這個物件就是ViewModel,是Model和Controller之間的一座橋樑。當MVVM結合繫結模式之後( 使用全量級的函式式響應程式設計框架,比如 ReactiveCocoa/ReactiveCocoa&usg=AFQjCNHM-pOkluiSuPsaVwVujCDTknVFUA&sig2=54zu-ATo8vDMvtXbxZYTvQ" target="_blank" rel="nofollow,noindex">ReactiveCocoa 、 Swift/" target="_blank" rel="nofollow,noindex">RxSwift 等 ),它變得越來越受開發者的喜愛,不單單解耦了每個模組,而且還精簡了程式碼,給後期的維護和寫單元測試提供了方便。
總結:
- 劃分: MVVM 框架裡面的 View 比 MVP 裡面負責的事情要更多一些。因為前者是通過 ViewModel 的資料繫結來更新自身狀態的,而後者只是把所有的事件統統交給 Presenter 去處理就完了,自己本身並不負責更新。
- 可測性:因為 ViewModel 對 View 是一無所知的,這樣我們對它的測試就變得很簡單。View 應該也是能夠被測試的,但是可能因為它對 UIKit 的依賴,你會直接略過它。
- 易用:MVVM的程式碼量基本跟 MVP 持平,但是在實際的應用當中 MVVM 會更簡潔一些。因為在 MVP 下你必須要把 View 的所有事件都交給 Presenter 去處理,而且需要手動的去更新 View 的狀態;而在 MVVM 下,你只需要用繫結就可以解決。
MVVM在結合函式式響應程式設計之後,會變得更加有魅力,但是也會相應的給開發者提出更多的挑戰,例如:函式式響應程式設計在除錯方明的問題和對TableView中檢視和模型之間如何優雅的繫結問題等等,不過相信這些都不是問題。
MVVM-R架構之美
在瞭解完 MVC
、 MVP
、 MVVM
和 VIPER
架構之後,這裡結合專案的需要,覺得 MVVM
會更適合現有的專案。所以在此基礎上對 MVVM
進行了一些小擴充套件,使各個模組更加的獨立可測試,也就是我們一開始看到的這張架構圖。

MVVM-R
MVVM-R思想:
-
V
:負責檢視佈局和提供自身需要的資料模型(通過protocol實現),View自身的互動事件,通過delegate代理出去; -
C
:管理生命週期和事件互動; -
M
:只提供資料結構,遵守了View提供的協議; -
VM
:網路請求和業務邏輯處理,介面的顯示完全由VM
配置資料來源決定; -
R
:處理模組間的跳轉。
好處:
- View層完全的獨立出來,不需要關心誰給它傳遞資料,誰來處理互動事件;
- View和Model層實現了完全的解耦;
- ViewModel通過配置資料模型,決定檢視的展示。
結合繫結:
- 選一個基於 KVO 的繫結庫,比如 RZDataBinding 或者 SwiftBond 。
- 使用全量級的 函式式響應程式設計 框架,比如 ReactiveCocoa 、 RxSwift 或者 PromiseKit" target="_blank" rel="nofollow,noindex">PromiseKit 。
這裡寫了一份MVVM-R架構的Demo,僅供交流學習:
MVVM-R架構之美