iOS - 架構的認識過程,回頭是岸。

16年的時候寫過一篇代碼講解的,依舊是這三種架構,如今20年將近了,看到好的文章,是否增長新的認識。html

16年連接 前端

iOS - 架構模式 - 解密 MVC、MVP、MVVM、VIPER架構

新項目選擇架構程序員

MVC 數據庫

MVP 編程

MVVM數組

VIPER緩存

mvc不說你們經常使用的方式,VC解決一切。mvp來自於微軟的面像協議編程,mvvm想必用過阿里前端庫VUE的都瞭解。viper美團設計一種的架構模式網絡

可是時間緊,公司貌似不重視此方面的技術。認爲一切均可以在一倆個月內解決全部問題,出一個完整的項目,對此我也是很無語。數據結構

在此也就是重溫一下經常使用架構模式。最終我選擇自定義框架。大量的引用組件和第三方資源庫來解決燃眉之急。以後準備回頭是岸了。架構

 

iOS架構的認識過程 經典就是經典,沒有之一。iOS中MVC架構,看懂斯坦福大學⽩鬍子老頭這張圖基本上就能夠了

簡單理解,就是Controller對象擁有View和Model對象,二者經過Controller進行溝通。對於單個⻚頁面,三個類就搞定了,感受很簡單。

MVC


網絡鏈接應該放在哪裏?Model中嗎?感受頗有道理?實際上,不少的網絡鏈接的發起和接收後 的處理都放在了Controller中,由於方便嘛。Model通常只有屬性定義,沒有實現。

View應該是獨⽴一塊了了吧?實際上呢,View大多都放在了Controller中,有個loadView函數,很⽅便啊。有幾我的會單獨寫個類來做爲view?

原本,xib和Storyboard是很好的分離view的⽅方式。可是,因爲「不合適多⼈合做,版本管理」,⾮要代碼寫界面,還振振有詞:「性能⾼,對培養新人有好處」。「謊話說100次都能成真話」,況且這些理由聽上去還那麼有理。

像「檢查⽤戶名是否合法,檢查密碼對不對」應該放在哪裏呢?有幾我的會像斯坦福大學白鬍子老頭那樣新起一個類來寫?基本上都是Controller中搞定。

BaseController,BaseView,BaseModel必定⻅過不很多吧?有的還有好幾層呢 公共View,各類名字帶common或者相似的類常見吧?裏面⽹絡鏈接,數據庫,邏輯等每每比

View自己不少,儼然一個⼩小模塊了了,功能比Controller都強大了。這仍是view嗎? 原本MVC理論上是最簡單的架構,可是實際結果呢,變成了最難懂的架構。Controller成了上帝

類,什麼都幹。「只知道那一坨東⻄有用,但看不出那是簡單的MVC」。

MVC也被稱之爲 Massive View Controller(重量級視圖控制器器)。其實這不是MVC的錯,只是沒 有程序員認可本身懶惰,編程習慣很差罷了了。若是可以像斯坦福⼤學⽩胡⼦老爺爺那樣好的編程習 慣,那麼大部分的iOS程序都能有清晰的MVC架構。

MVVM

MVVM來⾃自MVC,⼀一張經典的圖就是下⾯面這張,在好多文章中看到過。

 

 
 

「稍微考慮一下,雖然 View 和 View Controller 是技術上不一樣的組件,但它們幾乎老是手牽手在一 起,成對的。你何時看到一個 View 可以與不一樣 View Controller 配對?或者反過來?因此,爲何不正規化它們的鏈接呢?」 ------ 這段話當時給個人印象很深入,這個觀點到如今我都承認。

Controller表明了一個場景(Scene)的⽣生命週期,是一個調度者。什麼都是,由於什麼都離不開 它。又好像什麼都不是,由於它表明不了任何具體的東⻄西。讓它和View合在一塊兒,做爲廣義的view 就有了了具體的意義,並限制了它無所不能的印象。這點值得確定。

「顯示邏輯(presentation logic)」能夠從Controller中移到ViewModel中,從而給Controller減負。 這個觀點我也是支持的。而且我以此認爲ViewModel就是用來作「顯示邏輯」的,一個頁面一個,隨⻚面而變化。在Swift中,我用結構體來作ViewModel。

關於綁定機制,文章中推薦ReactiveCocoa。我去⼤致看了一下,主要是將KVO,Block,notification,delegate等各類通信機制統一爲RACSignal,將界面和數據進行雙向綁定,功能確實強大。可是這個風格和普通iOS的開發習慣差距⽐較大,一會兒很難變過來。文章中也說只是推薦,不 強求,因此我也就一直沒有采用。被誤解的MVC和被神化的MVVM

至於綁定機制,在Swift中可使用屬性觀察者。ViewModel通常做爲Controller的⼀個屬性,對它 進行觀察,一旦變化,就⽤用ViewModel新的值設置界面元素,感受挺好用的。還有一些相隔很遠或 者一對多的變化,通常能夠採用NSNotification來達到目的。

從網絡取數據,業務邏輯(相對於顯示邏輯),應該放在那裏呢?文章中沒有說,看意思是保留 在Controller中。還有的觀點認爲應該放在ViewModel中,這固然有道理,並且這是主流的理解。但 是這樣會讓ViewModel變成另一個上帝類。

我理解的MVVM

這是本⼈的理解,僅僅一家之言。主流的觀點沒有Logic那個類,從圖中刪除基本上就是了。 ViewModel將是替代Controller的⼀個上帝類。

Controller主要做爲調度者,居於中心位置。客串串部分View相關功能:好比動畫⾥面關於view的位 置改變,這些代碼是要放在Controller裏面的。這也符合Controller+View實現view功能的概念。

ViewModel專⻔門作「顯示邏輯」,而且用屬性觀察者作綁定,必要的時候用Notification。正向的綁定 好比「action-target」響應就保留留在Controller中,具體事情交個其餘類作就能夠了。

在Swift中,ViewModel和Model推薦用Struct;Logic傾向於用class。從一個簡單直觀的概念來 說,ViewModel須要保持輕量級,跟隨⻚面走,隨時準備修改。Model也是輕量量級,跟隨後臺API定 義走,只是個數據結構,隨時準備修改。⽽而Logic就顯得比較大,考慮穩定,考慮複用。

增長Logic類,負責業務邏輯,好比從⽹絡取數據,修改數據庫,檢查⽤戶名合法性,具體的響應 邏輯,監聽後的具體處理等

 

重點是Controller減負,儘可能起調度者職能,具體工做都放到Logic中處理理。

Logic考慮複用,能夠對應單個⻚面,也能夠多個⻚面共用。按照業務邏輯的思路路去劃分模塊。劃 分標準能夠和⻚面分類標準不同。

對於複雜⻚面,View和ViewModel能夠多個,按照組件的模式去考慮。

對於表格,ViewModel對應的是表格的cell,dataSource數組中放ViewModel的序列。

表格的delegate和dataSource,⽬前來看,放在Controller中是最⽅便的。固然,爲了給Controller 減負,再新增一個類TableDelegate也是很不錯的方法。

若是表格包含在一個組件中,⽤用容器器view作delegate和dataSource是一個不錯的選擇。 主要想法就是千方百計「架空」Controller,讓它只作一個調度者,管理⻚面的⽣命週期就能夠了了。

實在非它不可的時候,才讓它作具體的事情。

不引入ReactiveCocoa等龐大的第三方庫。這⾥裏裏有一篇文章不錯,值得學習一下。ReactiveCocoa 和 MVVM 入門


VIPER 這是比MVVM分類更更細的一種模式。

View: 也是View + Controller
Present:至關於ViewModel,叫展現器器 Interactor:交互器器,側重於業務邏輯;從網絡取數據,數據庫等功能都在這裏。 Entity:就是Model,僅僅是數據定義
WireFrame:就是Router,是⻚面跳轉

值得借鑑的地⽅方

將⻚頁⾯面跳轉獨立出來,作成公共模塊

將業務邏輯獨立出來,作成公共模塊

若是隻是對於單個頁面,分這麼多類,感受有點囉嗦了。不不夠對於多⻚面的模塊來講,仍是有借鑑意義的

其餘架構

一些實際在用,可是沒有通用縮寫名稱的架構 分層模式

將服務service的概念引入客戶端,做爲一箇中間層,進⾏隔離 業務邏輯做爲服務模塊,經過服務的方式進行訪問 數據訪問跟業務邏輯,表現層分開,是跟後臺的接口層

表現層只關注UI,至關於VIPER中的V和P;或者是MVVM中的ViewModel(僅顯示邏輯)和 View,可是沒有雙向綁定;

平臺模式


當前的APP,大多數是Native和H5的混合,將二者的接口代碼統一成通用模塊是比較好的作法 插件化也是一個愈來愈廣泛的趨勢,好比分享,第三方登陸,支付等等,都由第三方以插件的形

式提供。對這些插件集中管理也是好的作法

APP隨着公司發展壯大,分出不不一樣的事業部,在同一公司多個APP或者不一樣業務;這樣就有兩個 相反的發展趨勢:一方面,想共用模塊,讓多個業務共享;另外一方面,各⾃業務又要隔離,獨立發展。公司也有可能成立公共的平臺部。各業務部⻔之間是縱向拆分;業務和平臺之間是橫向拆分。 這就致使二維劃分的立體架構。

 

 

Step0:平臺型應用

以URL的⽅式,由主App調⽤子App 形式相似於調用打電話,發短信,發郵件 ,URL的定義須要統籌考慮

Step1:縱向劃分

分Native,H5,插件,三部分

Native和H5之間提供統一的橋接模塊

Native和插件之間提供統一的橋架模塊

若是加⼊ReactNative,那麼也要提供Native和ReactNative之間的橋接模塊。這個能夠先預留, 也能夠後再添加。

Step2:橫向劃分

Native部分進行橫劃分,由於這一塊是最耗資源的部分

最上層是界面層(名字能夠叫表現層或者UI層),這⾥裏能夠借用MVVM的思想。M不不用考慮,由 下層以服務的形式提供。VM僅僅作顯示邏輯,在Swift中⽤用struct。這一層是跟產品的交流層,儘可能薄,而且可以快速應對變化。業務邏輯等能分出去的功能,一概分出去。核心和重點就是讓 Controller只作調度者,萬不得已能夠酌情參與不多一部分的view工做。

最底層是微服務層(micro service)。這一層提供基本的功能,⽐如網絡,緩存,加解密,系統信息,日誌,統計等等。微服務的概念是隻能供其餘模塊調用,不能調用其餘模塊的服務。本層中的模塊之間也不能相互調用。這裏是一些基礎的組件,按照功能劃分,相互間的隔離是第一考慮要素。要求高內聚。

中間是服務層(service),這⾥的服務能夠調⽤用微服務,也能夠相互之間調用。

分三層相對簡單一點。固然也能夠分出一些接口層,服務層還能夠分出公共服務層,業務邏輯層 等。這個能夠根據須要靈活配置。可是整體上分三層(界面、服務、微服務)。

不要跨層調用,界面層只能調用服務層提供的服務。服務層能夠⾃己完成工做,也能夠調用其餘 服務或者微服務完成工做。

Step3:層內劃分

界面層:按照⻚面進行組織,提供公共的UI組件,能夠理解爲(M)VM。VM做爲將「界面顯示」 轉換爲「數據操做」的媒介,利用Swift的屬性觀察者特性,進行⼀級綁定。不引入RxSwift等函數式編程的大型第三方庫。

服務層:分爲公共服務,跳轉邏輯,業務邏輯等模塊,按照邏輯功能劃分。跟具體⻚面沒必要相關, 跟界面層的接口爲各ViewModel種定義的協議。

微服務層:按照功能劃分,不設計業務邏輯,分網絡、數據庫、加解密,日誌,統計等功能 框架圖


語言選擇Swift,最低支持版本iOS8,有條件的從iOS9開始

服務和微服務都以framework的形式提供,模塊間的隔離須要重點考慮。

服務service和微服務僅僅是邏輯上的層次結構,在具體的工程組織上,都採用一級framework封 裝,相互間的層級和調用採用相互間的依賴隱含表示。

提供一個界⾯面隔離的service.framework,界⾯層只調用它完成全部任務。做用至關於 Foundation。

以workspace的⽅式組織⼯程,第三方管理⼯具採用Carthage。有條件的狀況下,微服務以及部 分服務能夠採用私有Carthage的形式,更方便複用。

插件也要求以framework的形式提供,不接受.a的靜態庫。

若是暫時須要用到Object-C、C、C++,都統一成framework的形式,之後逐步用Swift替換。 類圖


界面層 AppDelegate、ViewController僅做爲調度者存在,不作任何具體的事情。

ViewModel僅僅作顯示邏輯相關的事情,僅僅起到將界⾯面轉換爲數據的做用。用結構體struct,每 個成員都是普通變量,而且都有默認值,表明了頁面的肯定性。ViewModel是⼀種數據結構,作顯 示邏輯的事情。

UI組件僅由View和ViewModel組成,只能包含顯示邏輯,不能包含跳轉邏輯,業務邏輯等。

ViewModel放UI層和Service層都有必定道理:放UI層表示顯示邏輯;放service層表示UI和service 之間的數據接口。考慮再三,以爲仍是應該放UI層。ViewModel最大的做⽤仍是在於將UI變化轉變爲數據操做,本質上離UI應該更近一些。

⾄於UI層和Service層之間的接口,仍是定義相關的的ViewModel protocol⽐較好。這些protocol的 定義放在service中(因爲framework的影響),將ViewModel的一些基本需求放在protocol中。 service中⽤用Model或者仍是用其餘來知足這個protocol,就不作要求了。用protocol做爲接口比單純用Model作接口要好。由於Model隨着後臺API定義而變,而protocol只至關於一個基類,類型更靈活


除了定義一個ViewModel的protocol以外,再定義一個是service的protocol,(既然引⼊入service概 念,就能夠淡化logic和data的概念)。

界面層保持最輕量級。⻚面跳轉邏輯,具體業務邏輯等⼯做所有下沉到服務層來作。

ViewModel是一個struct,主要作顯示邏輯,概念相對⽐較小,⼀般⼀個頁面⼀個或者多個。而service是一個類,概念比較大,能夠多個⻚面共用一個。尺度能夠根據具體狀況靈活掌握。不一樣的頁面,經過擴展遵循不一樣的協議區分開來。類自己可能比較大,可是每一部分都是相對比較小的。

服務層

service.framework做爲一個粘合層存在,AppDelegate、ViewController只要import service就能夠 調⽤相關服務了。

金融.framework、保險.framework等屬於業務特有的邏輯 Router、⽤用戶、分享等屬於業務無關的公共邏輯
層內的各模塊間能夠相互調用 具體存在形式,單例例、類、或者framework等,可根據具體狀況靈活決定。 爲告終構清晰,圖中的調用關係線只畫出了不多的一部分,⼤大部分線都沒有畫出來。

微服務層 從開發的⻆角度,按照功能分類;是工程師之間交流的技術語言,⽽不是跟產品交流的業務語言 功能⾼內聚,做爲被調用的基礎模塊模塊之間不要存在相互調用的關係以framework的形式存在。⾼內聚,⾼複用。

相關文章
相關標籤/搜索