iOS從2007年誕生至今已有近10年的歷史,10年的時間對iOS技術圈來說足夠產生相當可觀的沉澱,尤其這幾年的技術分享氛圍無論國內國外都顯得異常活躍。本文就iOS架構這一主題,結合開發圈裡討論較多的幾種主流方式,再配以博主自己的理解,做下現狀分析。給自己做下知識梳理的同時,也期望能引入新的思考。
架構的定義
過去6年多幾乎絕大部分時間都浸淫在iOS平臺,翻閱過不少關於架構的文章,發現眾人對架構的理解頗有些差異,總體來說可分為四類:
第一類:精簡型應用架構
這類架構的文章分析主要還是圍繞MVC展開,以蘋果自帶UIViewController優劣為出發點,再結合主流的MVP,MVVM,MVCS等變種進行分析演變。這類的探討重點在於M,V,C三類角色的定義以及之間的資料事件流向的規範。很多小型應用所面臨的問題及其架構層面的解決方案都集中在這一類。
第二類:綜合型應用架構
對於使用者量級在千萬級或以上的應用來說,MVC這一層面的思考已無法應對業務瘋狂增長所帶來的負擔。這類應用往往需要專業資深的架構師出面進行深層次的思考設計,業內不少大廠如淘寶,天貓,攜程等都做過一些分享。不過到了這一層級的戰鬥,不光考驗架構師的技術積累,更重要的是架構師對於業務的整體理解。我姑且把這類架構名之為:綜合型應用架構。綜合型應用架構一般不會提到MVC,更多是在探討“層”與“模組”的劃分和耦合。後面我會就幾個經典樣本做下詳盡深入的分析。
第三類:深度優化的綜合型應用架構
綜合型應用架構是應對大規模業務增長的必經之路,一旦架構成型,後期業務膨脹會不停的打磨架構本身,產品本身對體驗質量的追求會要求架構師和技術團隊不停的優化架構細節。這種優化可以分為兩塊,第一是元件或模組劃分的粒度越來越細,第二是元件模組的深度優化,比如網路層的深度優化,sqlite優化(多執行緒,FTS,安全等),資料加密,HotFix,Hybrid等,一些開源的第三方庫已不能滿足要求,需要團隊自己重造輪子。這一層面的架構設計涉及面廣,對架構師,團隊技術人員的技術深度和業務理解能力有較高要求,短短一篇技術文章往往只能走馬觀花的介紹個大概,每一次優化幾乎都可以作為一個專題來講解。
第四類:組織型應用架構
這類架構在第三類的基礎之上更進了一步,除了關注系統層面的架構設計之外,更對團隊或部門之間協作方式,各系統模組的演進方式,產品釋出流程等都做了規範。除去業務膨脹帶來的壓力,人員增長,各團隊協作依賴增強等都會對app的質量,迭代速度產生影響,這些問題也需要從架構層面去解決。這類結合技術架構和組織架構的分享還比較少。
以上四種型別的架構又可以看做一般App從簡至繁,公司規模隨之增長的演進過程,技術圈絕大部分的架構類分享文章都可以歸為上述四類。
對於什麼是架構的學術定義,似乎大家並不太在意,更關心的是如何解決自身專案當下的問題。雖然在我看來第一類架構更像是在討論設計模式,但這裡面確實又有非常多的知識可以深入挖掘,這裡就把所有“解決應用整體設計問題”的討論都歸類於架構這一話題。
值得一提的是,架構師的視野和積累一般都受限於自己所經歷專案及業務的規模。如果有機會,工程師還是應該儘可能去BAT這類巨頭級公司歷練一下,知識深度和廣度的構建絕非紙上可得。
樣本分析
這裡我以圈子裡幾個經典的架構分享為樣本,做下解剖分析。樣本的選取主要以搜尋引擎及評論熱度為標準,排名不分先後。
第一類樣本:
如果一篇架構的文章是以探討MVC為起點,很有可能作者所說的架構就可以被歸為第一類樣本。
Xcode自帶的UIViewController模板經常被戲稱為“Massive View Controller”,主要是因為UIViewController除了負責Controller生命週期回撥之外,還承擔了View和Controller的工作。不少架構的探討以此為基礎,將Controller的M,V,C三個角色重新進行劃分,又或者衍生出MVP,MVVM,MVCS,VIPER等其他組織方式。重新定義MVC之後,網路訪問,持久化,安全等通用功能模組往往就由Controller或者Presenter負責了,這些負責業務邏輯的功能類直接依賴於成熟穩定的第三方基礎庫,比如AFNetworking,FMDB等。
但是,應付過複雜龐大業務模組的工程師會會有經驗,無論以何種方式組織Controller,資料流向和事件傳遞再清晰合理,單純程式碼量的膨脹就足以讓Controller變得難以維護。MVC,MVP,MVVM都可以變得Massive。想象一下將10本書放在床頭,你可以按翻閱頻次,閱讀習慣將書合理擺放,但當你面對100本書的時候,已不是如何擺放的問題,而是需要一個新的書櫃。說到這裡我挺服VIPER的,五個角色劃分,嘗試可以在床頭放下100本書的Pattern。我們先來看看“10本書”的樣本。
樣本名:iOS 架構模式–解密 MVC,MVP,MVVM以及VIPER架構
作者:Bohdan Orlov
這篇文章是第一類樣本的典型,綜合對比了MV(X)系列架構。我們來看下主要論點。
論點摘要:
文章認為優秀的架構具備以下三個特質:
Balanced distribution of responsibilities among entities with strict roles.
能把程式碼職責均衡的劃分到不同的功能類裡。
這是我們關注架構的原動力,有個粗淺的評判標準,同一個業務單位(Controller)裡面,不能一個類1000多行程式碼,另一個類卻只有10來行。當我們考慮網路請求的程式碼是該放在controller當中還是model當中的時候,在“程式碼量”上要做到“雨露均沾”,不能少數類“營養不良”。所以不論你的MVC,MVP或者VIPER是如何劃分職責的,各個角色所承擔的職責應當看起來是均勻分配的。
Testability usually comes from the first feature.
方便測試
測試是個有趣的話題,不同公司實踐差異很大。我知道有些團隊的產品質量嚴重依賴於QA團隊,有些卻乾脆沒有測試團隊,完全依賴於開發人員自己保證質量,這兩種風格一般取決於CTO的技術決策,和公司大小倒沒多少關係。對於開發人員自測的情況,如果程式碼架構清晰,各角色職責分配合理,易測性是隨之而來的副產品。
Ease of use and a low maintenance cost
易用且方便維護
易用是針對團隊裡的開發人員而言的。其實到底是用MVP還是MVVM,或者MVVM裡資料如何流動,這些具體的規範到底採用何種形態不是最重要的問題,關鍵是在團隊所有成員能有一致的認識,無論是寫程式碼還是Debug都能快速切入。
圍繞上面三個特質,作者一一分析對比了傳統MVC,Apple MVC,MVP,MVVM,VIPER在這三方面的表現,結論是到底選用哪個純粹是個人口味問題。相較於結論,作者對各個Pattern的角色定義及分析才是真正有價值的部分,我們在閱讀評斷其他類似架構文章的時候,也應該重在瞭解作者對於角色的理解。大家可以基於這一點,閱讀下其他一些類似的文章。VIPER理論上並不能歸類於MV(X)系列,而是突破了MVC的思考方式,比如定義了Router處理頁面流程,這對架構師是個很好的思路,在對MV(X)重新設計的時候也應該能有新的思考,所謂“君子不器”。
MV(X)都是以MVC為原型進行變化,MV(X)到底如何使用沒有教科書式的標準答案,關鍵在於架構師和團隊各成員能達成一致的認識,在遇到問題時能不斷的做調整重構,遇到難以跨越的瓶頸時,能跳出MV(X)尋找解決方案。
第二類樣本:
在開始分析第二類樣本之前,有幾個概念比較重要,是我們深入討論各個綜合型樣本的前提。元件,模組,層的定義。
在我看來,元件是比模組更小的功能單位,不具備業務屬性,只處理基礎通用的問題,類似於工具箱。比如我們給NSString寫的Category提供base64,給NSDate寫的Category做日期格式化等等。
模組較之元件粒度更大一些,另外最重要的區別是帶有業務屬性,和業務場景相關聯。比如購物車模組,註冊登入模組,支付模組等等,模組往往會對一些通用的元件產生依賴。
層是另一個維度的概念了,我平常閱讀技術文章的時候,發現很多人會把模組和層的概念混淆,可以用一張圖來區分模組與層的概念:
對於層不允許跨層訪問,也就是說A不能直接訪問C,下層不允許訪問上層,B無法知道A的實現細節。層的概念可類比TCP/IP協議棧。模組就靈活多了,A,B,C三者之間可以任意訪問依賴。所以一般來說層對架構的約束更高,但使得依賴更規範好維護,模組在複雜的場景下很容易結成一個網狀的依賴形態,難以維護。第二類專案架構都是圍繞層與模組的劃分所展開,有的有嚴格的層次結構,有的不分層次,通過介面嚴格規範各模組互動,有的二者結合,在某一層內再做模組劃分,下面我們分析的樣本都屬於上面三種情形。
在開始分析之前,建議大家全篇瞭解下iOS開發圈關於元件化的討論,我之前做過一個總結,裡面有各篇文章連結:http://mrpeak.cn/blog/module/ 。
樣本名:餓了麼移動APP的架構演進
作者:聖迪
這篇架構演進的講解是典型的從第一類到第二類的過渡,可簡化為以下幾步:
1.使用傳統MVC快速迭代App。
2.業務發展,有多個App需要開發,開始元件化,使用CocoaPods進行元件管理,目標是並行開發和程式碼重用。架構圖如下:
如果讀過上面關於元件化的文章,這張架構圖就很好理解了,在做好模組劃分和管理之後,通過Router的方式將讓各模組產生耦合。這種架構方式已初步具備一個應付大規模業務增長的架構模型。
3.Hybrid,幾乎所有運營類主導的App都會最終投入Hybrid的懷抱,運營團隊對快速上線的要求只能在H5或者Hybrid上得以實現,不過這和架構本身關係不太大,是另一個大的話題。
4.React-Native & Hot Patch,這和第三步類似都是由運營驅動,幾乎是所有內容運營型app的必經之路。
這四步的演化文章介紹的還比較粗略,更多的細節(比如Router內部實現,業務元件和非業務元件的分工,元件間耦合的方式等)沒有介紹,或者餓了麼App端也還在探索當中。
第三類樣本:
樣本名:攜程移動APP架構優化之旅
作者:陳浩然
攜程App端的架構演化在餓了麼架構基礎之上,多了很多優化的細節。
提到了對於基礎SDK元件和業務元件的具體劃分:
核心功能SDK化
• 通訊、定位、Hybrid、資料庫、登入、分享、基礎庫等
• 直接提供給其他BU獨立App使用
公用業務功能元件化
• 地圖、日曆、城市、圖片、通訊錄等13個公共元件
• 減少各BU重複開發工作量
效能資料指標採集:
• 網路效能:網路服務成功率、平均耗時、耗時分佈
• 定位:獲取經緯度成功率、城市定位成功率
• 啟動時間、記憶體、流量等指標
• 多種緯度:系統、App版本、網路狀況、位置等
網路優化
• 使用TCP長連線實現網路服務
• 根據網路狀況2G/3G/4G/WIFI進行調優引數
• 根據連線/讀/寫不同階段使用重試機制
• 使用IP列表避免DNS解析失敗或者劫持
• 根據網路延遲選擇服務端IP(使用Ping)
• 使用ProtocolBuffer+Gzip減少Payload
還有Hybrid,HotFix,React Native等就不一一列舉了,這些細節性強的分享有很高的學習價值,能對剛涉足某一塊優化的架構師起到方向指引的作用。
這些看似簡單的劃分往往很考驗架構師的大局觀和經驗,涵蓋面和合理的粒度掌控才能讓技術團隊的開發工作高效並行。
第四類樣本:
樣本名:Facebook iOS Architecture
作者:Facebook
除了和上面樣本類似的模組化,元件優化的介紹之外,還有兩方面新的資訊:
在關於Infrastructure的介紹當中有張示意圖介紹團隊分工:
視訊當中不光介紹了基礎元件,業務模組的劃分,和說明了這些劃分對應的團隊是如何進行協作。
- 最底層的是基礎設施團隊,負責基礎SDK的開發,可以對應之前談到的非業務元件。
- 中間層是業務團隊,按業務模組進行劃分,一個業務對應一個團隊,團隊負責全平臺的開發,業務團在開發過程當中可反過來回饋基礎SDK。
- 最上面是產品的釋出團隊,產品釋出團隊配合業務團隊對產品的釋出週期和質量做保障。
在Facebook iOS客戶端架構設計當中有關於model層介紹:
之前看過不少架構分享文章,少有對model層深入探討的,一般提到都是一筆帶過。model層涉及app資料持久化,以及runtime的狀態維護,對app的穩定性和迭代效率起到至關重要的影響。
Facebook的model layer採用的是immutable策略,model雖然能被各層訪問,但model的修改統一由model layer提供介面。上層業務團隊一旦想修改某個model property,需要向model layer維護團隊提出申請,這一設計對狀態的維護相當謹慎。
我的思考
將架構的型別歸為上述四類也是方便自己搭建關於架構的知識體系,看架構類文章的時候先做好分類再按類別查漏補缺汲取營養。我個人在第一類,第二類架構方面做過一些嘗試和積累,第三類優化上做過一些知識總結。
第一類比如之前的技術分享:
iOS的應用層CDD架構 http://mrpeak.cn/blog/cdd/
這種優化應用層的架構方式是在MV(X)系列基礎之上新的嘗試,已在公司專案當中有過實踐,成效尚可。
第二類比如:
用Swift搭建資料驅動型iOS架構 http://mrpeak.cn/blog/swift-dda/
搭建資料驅動型Android架構 http://mrpeak.cn/blog/dda-android/
用了Swift和Java實現相同的架構思路,這種架構方式也是從已有成熟的專案當中總結提煉而來。
第三類主要是優化和總結的文章:
關於架構的總結就到這裡,以上全是一家之言,一則梳理,二則分享,任何想法建議,歡迎交流。
打賞支援我寫出更多好文章,謝謝!
打賞作者
打賞支援我寫出更多好文章,謝謝!