MVC與MVVM之間在IOS中的區別


作為一個iOS開發者,我不止一次聽到我的一些開發者朋友跟我說我寫的iOS代碼看起來好舒服,很整潔,為什么咱們iOS開發的相當一大部分應用軟件都給人以美的享受,究竟是什么使得iOS上的應用可以如此漂亮?因為他們使用了將代碼和界面分開的開發結構框架MVC。

 

MVC的低耦合性、高重用性、可維護性等優點顯而易見,使得原本復雜的代碼與界面的交互變得簡單、清晰、明了,開發者可以把更多的精力放在前端界面的設計上,而不用絞盡腦汁去思考究竟應該如何使界面得到同步,這樣減輕了設計壓力,也從另一方面使用戶得到更多更好的享受體驗。縱觀iOS經典Native App的所有應用軟件,幾乎都具有一個很大特點,那就是“炫”。清新的畫面配以簡單的手勢操作,顛覆着用戶的思維方式,小巧精悍。

 

MVC是構建iOS app的標准模式。但是,各位朋友們,如果你已經使用過MVC一段時間,我覺得越來越厭倦MVC的一些缺點。在本文,我將重溫一下MVC是什么,詳述它的缺點,並且告訴你一個新的方式來架構你的app:Model-View-ViewModel。 

MVC即是Model-VIew-Controller三個英文單詞的縮寫,中文翻譯為模型-視圖-控制器。MVC並非只有ios應用軟件獨有的應用開發模式,它被廣泛應用在許多軟件(尤其是中大型軟件)的開發上。MVC把軟件系統分為三個部分:Model,View,Controller。Model相當於應用的底層,應用在功能上的實現完全依賴於Model,打個比方,如果是一台電腦的話,Model就是你機箱里的所有東西:cpu,內存,硬盤,顯卡等的一個集合,你不必看到它們,但它們必不可少;Controller就是控制器,它控制Model與View的交互,它將M和V捆綁在一起,將你的操作傳達給Model,再控制View將其表現出來。View相當於電腦的圖形界面,將Model的運行結果可視化地呈現給用戶,你在屏幕上看到的一切都可以歸類於View。

 

在cocoa中,你的程序中的每一個object(對象)都將明顯地僅屬於這三部分中的一個,而完全不屬於另外兩個。因此,用MVC開發的應用軟件更易於進行維護和修改,不用因為底層的Model出了問題而去影響表層的View。MVC雖然把三部分獨立了出來,但三部分之間仍然存在聯系,但就如下圖所示,Model與View之間是完全獨立的,兩者各自運行,以Controller為橋梁進行交互,並不發生直接關聯。

 

在這種架構下,View 是無狀態的,在 Model 變化的時候它只是簡單的被 Controller 重繪;就像網頁一樣,點擊了一個新的鏈接,整個網頁就重新加載。盡管這種架構可以在 iOS 應用里面實現,但是由於 MVC 的三種實體被緊密耦合着,每一種實體都和其他兩種有着聯系,所以即便是實現了也沒有什么意義。這種緊耦合還戲劇性的減少了它們被重用的可能,這恐怕不是你想要在自己的應用里面看到的。綜上,傳統 MVC 的例子我覺得也沒有必要去寫了。

 

傳統的 MVC 已經不適合當下的 iOS 開發了。

 

View 和 Model 之間是相互獨立的,它們只通過 Controller 來相互聯系。有點惱人的是 Controller 是重用性最差的,因為我們一般不會把冗雜的業務邏輯放在 Model 里面,那就只能放在 Controller 里了。

 

理論上看這么做貌似挺簡單的,但是你有沒有覺得有點不對勁?你甚至聽過有人把 MVC 叫做重控制器模式。另外 關於 ViewController 瘦身 已經成為iOS 開發者們熱議的話題了。為什么 Apple 要沿用只是做了一點點改進的傳統 MVC 架構呢?

 

Cocoa MVC 鼓勵你去寫重控制器是因為 View 的整個生命周期都需要它去管理,Controller 和 View 很難做到相互獨立。雖然你可以把控制器里的一些業務邏輯和數據轉換的工作交給 Model,但是你再想把負擔往 View 里面分攤的時候就沒辦法了;因為 View 的主要職責就只是講用戶的操作行為交給Controller 去處理而已。於是 ViewController 最終就變成了所有東西的代理和數據源,甚至還負責網絡請求的發起和取消。

 

MVC以下幾點是真的讓人很頭疼!!

 

厚重的View Controller

 

由於大量的代碼被放進view controller,導致他們變的相當臃腫。在iOS中有的view controller里綿延成千上萬行代碼的事並不是前所未見的。這些超重app的突出情況包括:厚重的View Controller很難維護(由於其龐大的規模);包含幾十個屬性,使他們的狀態難以管理;遵循許多協議(protocol),導致協議的響應代碼和controller的邏輯代碼混淆在一起。

 

厚重的view controller很難測試,不管是手動測試或是使用單元測試,因為有太多可能的狀態。將代碼分解成更小的多個模塊通常是件好事。

 

遺失的網絡邏輯

 

蘋果使用的MVC的定義是這么說的:所有的對象都可以被歸類為一個model,一個view,或是一個controller。就這些。那么把網絡代碼放哪里?和一個API通信的代碼應該放在哪兒?

 

你可能試着把它放在model對象里,但是也會很棘手,因為網絡調用應該使用異步,這樣如果一個網絡請求比持有它的model生命周期更長,事情將變的復雜。顯然也不應該把網絡代碼放在view里,因此只剩下controller了。這同樣是個壞主意,因為這加劇了厚重View Controller的問題。

 

那么應該放在那里呢?顯然MVC的3大組件根本沒有適合放這些代碼的地方。

 

較差的可測試性

 

MVC的另一個大問題是,它不鼓勵開發人員編寫單元測試。由於view controller混合了視圖處理邏輯和業務邏輯,分離這些成分的單元測試成了一個艱巨的任務。大多數人選擇忽略這個任務,那就是不做任何測試。

 

定義模糊的“Manage”

 

之前我提到了view controller可以管理試圖的層次結構;view controller有一個“view”屬性,並且可以通過IBOutlet訪問視圖的任何子視圖。當有很多outlet時這樣做不易於擴展,在某種意義上,最好不要使用子視圖控制器(child view controller)來幫助管理子視圖(subview)。

 

要點在哪?驗證用戶輸入的業務邏輯應歸入controller還是model呢?

 

在這里有多個模糊的標准,似乎沒有人能完全達成一致。貌似無論如何,view和對應的controller都緊緊的耦合在一起,總之,還是會把它們當成一個組件來對待。

 

Hey!現在有個點子...

 

Model-View-ViewModel

 

在理想的世界里,MVC也許工作的很好。然而,我們生活在真實的世界。既然我們已經詳細說明了MVC在典型場景中的問題,那讓我們看一看一個可供替換的選擇:Model-View-ViewModel。

 

MVVM來自微軟,不過不要堅持反對它。MVVM和MVC很像。它正式規范了視圖和控制器緊耦合的性質,並引入新的組件。

在MVVM里,view和view controller正式聯系在一起,我們把它們視為一個組件。視圖view仍然不能直接引用模型model,當然controller也不能。相反,他們引用視圖模型view model。

 

view model是一個放置用戶輸入驗證邏輯,視圖顯示邏輯,發起網絡請求和其他各種各樣的代碼的極好的地方。有一件事情不應歸入view model,那就是任何視圖本身的引用。view model的概念同時適用於於iOS和OS X。(換句話說,不要在view model中使用 #import UIKit.h)

 

由於展示邏輯(presentation logic)放在了view model中(比如model的值映射到一個格式化的字符串),視圖控制器本身就會不再臃腫。當你開始使用MVVM的最好方式是,可以先將一小部分邏輯放入視圖模型,然后當你逐漸習慣於使用這個范式的時候再遷移更多的邏輯到視圖模型中。

 

使用MVVM的iOS app是高度可測試的;因為view model包含了所有的展示邏輯並且不會引用view,所以它可以通過編程方式充分測試。雖然有眾多的hack技術參與到測試Core Data模型,但使用MVVM寫的app可以進行充分的單元測試。

 

以我的經驗,使用MVVM會輕微的增加代碼量,但總體上減少了代碼的復雜性。這是一個划算的交易。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM