漫談app架構設計(上篇)
為什麼要糾結選擇什麼架構?
假如有一天,你在除錯一個實現了幾十種功能的龐大的類時,你會發現自己很難找到並修復你的類中的任何錯誤。並且,很難把這個類作為一個整體來考慮,因此,你總會忽略一些重要的細節。如果你的應用程式中已經出現了這種情況,那麼很有可能:
1.這類是控制器類
2.控制器直接儲存和處理你的資料
3.你的Views幾乎沒有做任何事情
4.Model僅僅是一個數據結構
5.單元測試覆蓋不了任何內容
說到設計模式,我們先來看看app架構的設計原則
單一職責原則
永遠不應該有多於一個原因來改變某個類。對於一個類而言,應該僅有一個引起它變化的原因。說白了就是,不同的類具備不同的職責,各施其責。這就好比一個團隊,大家分工協作,互不影響,各做各的事情。開放封閉原則
軟體實體,如:類、模組與函式,對於擴充套件應該是開放的,但對於修改應該是封閉的。介面只增不輕易刪改。當需求有改動,要修改程式碼了,此時您要做的是,儘量用繼承或組合的方式來擴充套件類的功能,而不是直接修改類的程式碼。當然,如果能夠確保對整體架構不會產生任何影響,那麼也沒必要搞得那麼複雜了,直接改這個類吧。
里氏替換原則
使用基類的指標或引用的函式,必須是在不知情的情況下,能夠使用派生類的物件。父類能夠替換子類,但子類不一定能替換父類。也就是說,在程式碼中可以將父類全部替換為子類,程式不會報錯,也不會在執行時出現任何異常,但反過來卻不一定成立。在繼承類時,務必重寫(Override)父類中所有的方法,尤其需要注意父類的 protected 方法(它們往往是讓您重寫的),子類儘量不要暴露自己的 public 方法供外界呼叫。
最少知識原則
儘量減少物件之間的互動,從而減小類之間的耦合。簡言之,一定要做到:低耦合,高內聚。在做系統設計時,不要讓一個類依賴於太多的其他類,需儘量減小依賴關係。
依賴倒置原則
高層模組不應該依賴於低層模組,它們應該依賴於抽象。抽象不應該依賴於細節,細節應該依賴於抽象。應該面向介面程式設計,不應該面向實現類程式設計。面向實現類程式設計,相當於就是論事,那是正向依賴(正常人思維);面向介面程式設計,相當於通過事物表象來看本質,那是反向依賴,即依賴倒置(程式設計師思維)
(其他設計原則 )
不要重複你自己
不要讓重複的程式碼到處都是,要讓它們足夠的重用,所以要儘可能地封裝。
保持它簡單與傻瓜
不要讓重複的程式碼到處都是,要讓它們足夠的重用,所以要儘可能地封裝。
高內聚與低耦合
模組內部需要做到內聚度高,模組之間需要做到耦合度低.
慣例優於配置
儘量讓慣例來減少配置,這樣才能提高開發效率,儘量做到“零配置”。很多開發框架都是這樣做的。
命令查詢分離
在定義介面時,要做到哪些是命令,哪些是查詢,要將它們分離,而不要揉到一起。
關注點分離
將一個複雜的問題分離為多個簡單的問題,然後逐個解決這些簡單的問題,那麼這個複雜的問題就解決了。難就難在如何進行分離。
契約式設計
模組或系統之間的互動,都是基於契約(介面或抽象)的,而不要依賴於具體實現。該原則建議我們要面向契約程式設計。
常用設計模式
MVC Model - View - Controller
MVVM Model-View-ViewModel
MVP Model - View - Presenter

引用的網路圖片
1)Model 和 View 永遠不能相互通訊,只能通過 Controller 傳遞。
2)Controller 可以直接與 Model 對話(讀寫呼叫 Model),Model 通過 Notification 和 KVO 機制與 Controller 間接通訊。
3)Controller 可以直接與 View 對話,通過 outlet,直接操作 View,outlet 直接對應到 View 中的控制元件,View 通過 action 向 Controller 報告事件的發生(如使用者 Touch 我了)。Controller 是 View 的直接資料源(資料很可能是 Controller 從 Model 中取得並經過加工了)。Controller 是 View 的代理(delegate),以同步 View 與 Controller。
MVC自身不足
MVC 在現實應用中的不足在 MVC 模式中 view 將使用者互動通知給控制器。view 的控制器通過更新 Model 來反應狀態的改變。Model(通常使用 Key-Value-Observation)通知控制器來更新他們負責的 view。
愈發笨重的Controller在傳統的 app 中模型資料一般都很簡單,不涉及到複雜的業務資料邏輯處理,客戶端開發受限於它自身執行的的平臺終端,這一點註定使移動端不像 PC 前端那樣能夠處理大量的複雜的業務場景。然而隨著移動平臺的各種深入,我們不得不考慮這個問題。傳統的 Model 資料大多來源於網路資料,拿到網路資料後客戶端要做的事情就是將資料直接按照順序畫在介面上。隨著業務的越來越來的深入,我們依賴的 service 服務可能在大多時間無法第一時間滿足客戶端需要的資料需求,移動端愈發的要自行處理一部分邏輯計算操作。這個時間一慣的做法是在控制器中處理,最終導致了控制器成了垃圾箱,越來越不可維護。
太過於輕量級的 Model:早期的 Model 層,其實就是如果資料有幾個屬性,就定義幾個屬性,ARC 普及以後我們在 Model 層的實現檔案中基本上看不到程式碼(無需再手動管理釋放變數,Model 既沒有複雜的業務處理,也沒有物件的構造,基本上 .m 檔案中的程式碼普遍是空的);同時與控制器的程式碼越來厚重形成強烈的反差,這一度讓人不禁對現有的開發設計構思有所懷疑
遺失的網路邏輯:蘋果使用的 MVC 的定義是這麼說的:所有的物件都可以被歸類為一個 Model,一個 view,或是一個控制器。就這些,那麼把網路程式碼放哪裡?和一個 API 通訊的程式碼應該放在哪兒?所以我們的MVVM設計模式也就應運而生了。
MVVM設計模式

引用的網路圖片
M:對應於MVC的M
V:對應於MVC的V
VM:viewModel,是把MVC裡的controller的資料的載入、加工功能分離出來
MVVM 是 Web 前端一種非常流行的開發模式,利用 MVVM 可以使我們的程式碼更專注於處理業務邏輯而不是去關心 DOM 操作。目前著名的 MVVM 框架有 vue, avalon, angular 等,這些框架各有千秋,但是實現的思想大致上是相同的:資料繫結 和 檢視重新整理。跟MVC一樣,主要目的是分離檢視(View)和模型(Model)。View可以獨立於Model變化和修改,一個ViewModel可以繫結到不同的"View"上,當View變化的時候Model可以不變,當Model變化的時候View也可以不變。
在MVVM中,資料是核心,由於VIewModel與View之間的雙向繫結,操作了ViewModel中的資料,就會同步到DOM,我們透過DOM事件監控使用者對DOM的改動,也會同步到ViewModel。
MVVM的缺點
資料繫結使得 Bug 很難被除錯。你看到介面異常了,有可能是你 View 的程式碼有 Bug,也可能是 Model 的程式碼有問題。資料繫結使得一個位置的 Bug 被快速傳遞到別的位置,要定位原始出問題的地方就變得不那麼容易了。
一個大的模組中model也會很大,雖然使用方便了也很容易保證了資料的一致性,當時長期持有,不釋放記憶體就造成了花費更多的記憶體。
資料雙向繫結不利於程式碼重用。客戶端開發最常用的重用是View,但是資料雙向繫結技術,讓你在一個View都綁定了一個model,不同模組的model都不同。那就不能簡單重用View了。
MVP設計模式

引用的網路圖片
1、MVP模式是MVC的一個演化版本,全稱是Model view Presenter。
2、MVP能夠有效的降低View的複雜性,避免業務邏輯被塞進View中,使得View變成一個混亂的“大泥坑”。
3、MVP模式會解除View與Model的耦合,同時又帶來了良好的可擴充套件性,可測試性,保證了系統的整潔性。
優點:降低耦合度,模組職責劃分明顯,利於多人開發,利於測試驅動開放,程式碼服用,隱藏資料。缺點:由於對檢視的渲染放在了Presenter中,所以檢視和Presenter的互動會過於頻繁。如果Presenter過多地渲染了檢視,往往會使得它與特定的檢視的聯絡過於緊密。一旦檢視需要變更,那麼Presenter也需要變更了。