iOS從2007年誕生至今已有近10年的歷史,10年的時間對iOS技術(shù)圈來說足夠產(chǎn)生相當(dāng)可觀的沉淀幻枉,尤其這幾年的技術(shù)分享氛圍無論國內(nèi)國外都顯得異常活躍。本文就iOS架構(gòu)這一主題苗傅,結(jié)合開發(fā)圈里討論較多的幾種主流方式,再配以博主自己的理解班巩,做下現(xiàn)狀分析渣慕。給自己做下知識梳理的同時,也期望能引入新的思考抱慌。
架構(gòu)的定義
過去6年多幾乎絕大部分時間都浸淫在iOS平臺逊桦,翻閱過不少關(guān)于架構(gòu)的文章,發(fā)現(xiàn)眾人對架構(gòu)的理解頗有些差異抑进,總體來說可分為四類:
第一類:精簡型應(yīng)用架構(gòu)
這類架構(gòu)的文章分析主要還是圍繞MVC展開强经,以蘋果自帶UIViewController優(yōu)劣為出發(fā)點(diǎn),再結(jié)合主流的MVP单匣,MVVM夕凝,MVCS等變種進(jìn)行分析演變。這類的探討重點(diǎn)在于M户秤,V码秉,C三類角色的定義以及之間的數(shù)據(jù)事件流向的規(guī)范。很多小型應(yīng)用所面臨的問題及其架構(gòu)層面的解決方案都集中在這一類鸡号。
第二類:綜合型應(yīng)用架構(gòu)
對于用戶量級在千萬級或以上的應(yīng)用來說转砖,MVC這一層面的思考已無法應(yīng)對業(yè)務(wù)瘋狂增長所帶來的負(fù)擔(dān)。這類應(yīng)用往往需要專業(yè)資深的架構(gòu)師出面進(jìn)行深層次的思考設(shè)計鲸伴,業(yè)內(nèi)不少大廠如淘寶府蔗,天貓,攜程等都做過一些分享汞窗。不過到了這一層級的戰(zhàn)斗姓赤,不光考驗(yàn)架構(gòu)師的技術(shù)積累,更重要的是架構(gòu)師對于業(yè)務(wù)的整體理解仲吏。我姑且把這類架構(gòu)名之為:綜合型應(yīng)用架構(gòu)不铆。綜合型應(yīng)用架構(gòu)一般不會提到MVC,更多是在探討“層”與“模塊”的劃分和耦合裹唆。后面我會就幾個經(jīng)典樣本做下詳盡深入的分析誓斥。
第三類:深度優(yōu)化的綜合型應(yīng)用架構(gòu)
綜合型應(yīng)用架構(gòu)是應(yīng)對大規(guī)模業(yè)務(wù)增長的必經(jīng)之路,一旦架構(gòu)成型许帐,后期業(yè)務(wù)膨脹會不停的打磨架構(gòu)本身劳坑,產(chǎn)品本身對體驗(yàn)質(zhì)量的追求會要求架構(gòu)師和技術(shù)團(tuán)隊不停的優(yōu)化架構(gòu)細(xì)節(jié)。這種優(yōu)化可以分為兩塊成畦,第一是組件或模塊劃分的粒度越來越細(xì)距芬,第二是組件模塊的深度優(yōu)化涝开,比如網(wǎng)絡(luò)層的深度優(yōu)化,sqlite優(yōu)化(多線程蔑穴,F(xiàn)TS忠寻,安全等),數(shù)據(jù)加密存和,HotFix奕剃,Hybrid等,一些開源的第三方庫已不能滿足要求捐腿,需要團(tuán)隊自己重造輪子纵朋。這一層面的架構(gòu)設(shè)計涉及面廣,對架構(gòu)師茄袖,團(tuán)隊技術(shù)人員的技術(shù)深度和業(yè)務(wù)理解能力有較高要求操软,短短一篇技術(shù)文章往往只能走馬觀花的介紹個大概,每一次優(yōu)化幾乎都可以作為一個專題來講解宪祥。
第四類:組織型應(yīng)用架構(gòu)
這類架構(gòu)在第三類的基礎(chǔ)之上更進(jìn)了一步聂薪,除了關(guān)注系統(tǒng)層面的架構(gòu)設(shè)計之外,更對團(tuán)隊或部門之間協(xié)作方式蝗羊,各系統(tǒng)模塊的演進(jìn)方式藏澳,產(chǎn)品發(fā)布流程等都做了規(guī)范。除去業(yè)務(wù)膨脹帶來的壓力耀找,人員增長翔悠,各團(tuán)隊協(xié)作依賴增強(qiáng)等都會對app的質(zhì)量,迭代速度產(chǎn)生影響野芒,這些問題也需要從架構(gòu)層面去解決蓄愁。這類結(jié)合技術(shù)架構(gòu)和組織架構(gòu)的分享還比較少。
以上四種類型的架構(gòu)又可以看做一般App從簡至繁狞悲,公司規(guī)模隨之增長的演進(jìn)過程撮抓,技術(shù)圈絕大部分的架構(gòu)類分享文章都可以歸為上述四類。
對于什么是架構(gòu)的學(xué)術(shù)定義摇锋,似乎大家并不太在意丹拯,更關(guān)心的是如何解決自身項目當(dāng)下的問題。雖然在我看來第一類架構(gòu)更像是在討論設(shè)計模式乱投,但這里面確實(shí)又有非常多的知識可以深入挖掘,這里就把所有“解決應(yīng)用整體設(shè)計問題”的討論都?xì)w類于架構(gòu)這一話題顷编。
值得一提的是戚炫,架構(gòu)師的視野和積累一般都受限于自己所經(jīng)歷項目及業(yè)務(wù)的規(guī)模。如果有機(jī)會媳纬,工程師還是應(yīng)該盡可能去BAT這類巨頭級公司歷練一下双肤,知識深度和廣度的構(gòu)建絕非紙上可得施掏。
樣本分析
這里我以圈子里幾個經(jīng)典的架構(gòu)分享為樣本,做下解剖分析茅糜。樣本的選取主要以搜索引擎及評論熱度為標(biāo)準(zhǔn)七芭,排名不分先后。
第一類樣本:
如果一篇架構(gòu)的文章是以探討MVC為起點(diǎn)蔑赘,很有可能作者所說的架構(gòu)就可以被歸為第一類樣本狸驳。
Xcode自帶的UIViewController模板經(jīng)常被戲稱為“Massive View Controller”,主要是因?yàn)閁IViewController除了負(fù)責(zé)Controller生命周期回調(diào)之外缩赛,還承擔(dān)了View和Controller的工作耙箍。不少架構(gòu)的探討以此為基礎(chǔ),將Controller的M酥馍,V辩昆,C三個角色重新進(jìn)行劃分,又或者衍生出MVP旨袒,MVVM汁针,MVCS,VIPER等其他組織方式砚尽。重新定義MVC之后施无,網(wǎng)絡(luò)訪問,持久化尉辑,安全等通用功能模塊往往就由Controller或者Presenter負(fù)責(zé)了帆精,這些負(fù)責(zé)業(yè)務(wù)邏輯的功能類直接依賴于成熟穩(wěn)定的第三方基礎(chǔ)庫,比如AFNetworking隧魄,F(xiàn)MDB等卓练。
但是,應(yīng)付過復(fù)雜龐大業(yè)務(wù)模塊的工程師會會有經(jīng)驗(yàn)购啄,無論以何種方式組織Controller襟企,數(shù)據(jù)流向和事件傳遞再清晰合理,單純代碼量的膨脹就足以讓Controller變得難以維護(hù)狮含。MVC顽悼,MVP,MVVM都可以變得Massive几迄。想象一下將10本書放在床頭蔚龙,你可以按翻閱頻次,閱讀習(xí)慣將書合理擺放映胁,但當(dāng)你面對100本書的時候木羹,已不是如何擺放的問題拍霜,而是需要一個新的書柜文虏。說到這里我挺服VIPER的拼窥,五個角色劃分虹蒋,嘗試可以在床頭放下100本書的Pattern。我們先來看看“10本書”的樣本脐瑰。
樣本名:iOS 架構(gòu)模式–解密 MVC妖枚,MVP,MVVM以及VIPER架構(gòu)
作者:Bohdan Orlov
這篇文章是第一類樣本的典型绝页,綜合對比了MV(X)系列架構(gòu)。我們來看下主要論點(diǎn)忌穿。
論點(diǎn)摘要:
文章認(rèn)為優(yōu)秀的架構(gòu)具備以下三個特質(zhì):
Balanced distribution of responsibilities among entities with strict roles.
能把代碼職責(zé)均衡的劃分到不同的功能類里抒寂。
這是我們關(guān)注架構(gòu)的原動力,有個粗淺的評判標(biāo)準(zhǔn)掠剑,同一個業(yè)務(wù)單位(Controller)里面屈芜,不能一個類1000多行代碼,另一個類卻只有10來行朴译。當(dāng)我們考慮網(wǎng)絡(luò)請求的代碼是該放在controller當(dāng)中還是model當(dāng)中的時候井佑,在“代碼量”上要做到“雨露均沾”,不能少數(shù)類“營養(yǎng)不良”眠寿。所以不論你的MVC躬翁,MVP或者VIPER是如何劃分職責(zé)的,各個角色所承擔(dān)的職責(zé)應(yīng)當(dāng)看起來是均勻分配的盯拱。
Testability usually comes from the first feature.
方便測試
測試是個有趣的話題盒发,不同公司實(shí)踐差異很大。我知道有些團(tuán)隊的產(chǎn)品質(zhì)量嚴(yán)重依賴于QA團(tuán)隊狡逢,有些卻干脆沒有測試團(tuán)隊宁舰,完全依賴于開發(fā)人員自己保證質(zhì)量,這兩種風(fēng)格一般取決于CTO的技術(shù)決策奢浑,和公司大小倒沒多少關(guān)系蛮艰。對于開發(fā)人員自測的情況,如果代碼架構(gòu)清晰雀彼,各角色職責(zé)分配合理壤蚜,易測性是隨之而來的副產(chǎn)品。
Ease of use and a low maintenance cost
易用且方便維護(hù)
易用是針對團(tuán)隊里的開發(fā)人員而言的徊哑。其實(shí)到底是用MVP還是MVVM袜刷,或者M(jìn)VVM里數(shù)據(jù)如何流動,這些具體的規(guī)范到底采用何種形態(tài)不是最重要的問題莺丑,關(guān)鍵是在團(tuán)隊所有成員能有一致的認(rèn)識著蟹,無論是寫代碼還是Debug都能快速切入。
圍繞上面三個特質(zhì),作者一一分析對比了傳統(tǒng)MVC草则,Apple MVC,MVP蟹漓,MVVM炕横,VIPER在這三方面的表現(xiàn),結(jié)論是到底選用哪個純粹是個人口味問題葡粒。相較于結(jié)論份殿,作者對各個Pattern的角色定義及分析才是真正有價值的部分,我們在閱讀評斷其他類似架構(gòu)文章的時候嗽交,也應(yīng)該重在了解作者對于角色的理解卿嘲。大家可以基于這一點(diǎn),閱讀下其他一些類似的文章夫壁。VIPER理論上并不能歸類于MV(X)系列拾枣,而是突破了MVC的思考方式,比如定義了Router處理頁面流程盒让,這對架構(gòu)師是個很好的思路梅肤,在對MV(X)重新設(shè)計的時候也應(yīng)該能有新的思考,所謂“君子不器”邑茄。
MV(X)都是以MVC為原型進(jìn)行變化姨蝴,MV(X)到底如何使用沒有教科書式的標(biāo)準(zhǔn)答案,關(guān)鍵在于架構(gòu)師和團(tuán)隊各成員能達(dá)成一致的認(rèn)識肺缕,在遇到問題時能不斷的做調(diào)整重構(gòu)左医,遇到難以跨越的瓶頸時,能跳出MV(X)尋找解決方案同木。
第二類樣本:
在開始分析第二類樣本之前浮梢,有幾個概念比較重要,是我們深入討論各個綜合型樣本的前提泉手。組件黔寇,模塊,層的定義斩萌。
在我看來缝裤,組件是比模塊更小的功能單位,不具備業(yè)務(wù)屬性颊郎,只處理基礎(chǔ)通用的問題憋飞,類似于工具箱。比如我們給NSString寫的Category提供base64姆吭,給NSDate寫的Category做日期格式化等等榛做。
模塊較之組件粒度更大一些,另外最重要的區(qū)別是帶有業(yè)務(wù)屬性,和業(yè)務(wù)場景相關(guān)聯(lián)检眯。比如購物車模塊厘擂,注冊登錄模塊,支付模塊等等锰瘸,模塊往往會對一些通用的組件產(chǎn)生依賴刽严。
層是另一個維度的概念了,我平常閱讀技術(shù)文章的時候避凝,發(fā)現(xiàn)很多人會把模塊和層的概念混淆舞萄,可以用一張圖來區(qū)分模塊與層的概念:
對于層不允許跨層訪問,也就是說A不能直接訪問C管削,下層不允許訪問上層倒脓,B無法知道A的實(shí)現(xiàn)細(xì)節(jié)。層的概念可類比TCP/IP協(xié)議棧含思。模塊就靈活多了崎弃,A,B含潘,C三者之間可以任意訪問依賴吊履。所以一般來說層對架構(gòu)的約束更高,但使得依賴更規(guī)范好維護(hù)调鬓,模塊在復(fù)雜的場景下很容易結(jié)成一個網(wǎng)狀的依賴形態(tài)艇炎,難以維護(hù)。第二類項目架構(gòu)都是圍繞層與模塊的劃分所展開腾窝,有的有嚴(yán)格的層次結(jié)構(gòu)缀踪,有的不分層次,通過接口嚴(yán)格規(guī)范各模塊交互虹脯,有的二者結(jié)合驴娃,在某一層內(nèi)再做模塊劃分,下面我們分析的樣本都屬于上面三種情形循集。
在開始分析之前唇敞,建議大家全篇了解下iOS開發(fā)圈關(guān)于組件化的討論,我之前做過一個總結(jié)咒彤,里面有各篇文章鏈接:http://mrpeak.cn/blog/module/ 疆柔。
樣本名:餓了么移動APP的架構(gòu)演進(jìn)
作者:圣迪
這篇架構(gòu)演進(jìn)的講解是典型的從第一類到第二類的過渡,可簡化為以下幾步:
1.使用傳統(tǒng)MVC快速迭代App镶柱。
2.業(yè)務(wù)發(fā)展旷档,有多個App需要開發(fā),開始組件化歇拆,使用CocoaPods進(jìn)行組件管理鞋屈,目標(biāo)是并行開發(fā)和代碼重用范咨。架構(gòu)圖如下:
如果讀過上面關(guān)于組件化的文章,這張架構(gòu)圖就很好理解了厂庇,在做好模塊劃分和管理之后渠啊,通過Router的方式將讓各模塊產(chǎn)生耦合。這種架構(gòu)方式已初步具備一個應(yīng)付大規(guī)模業(yè)務(wù)增長的架構(gòu)模型权旷。
3.Hybrid昭抒,幾乎所有運(yùn)營類主導(dǎo)的App都會最終投入Hybrid的懷抱,運(yùn)營團(tuán)隊對快速上線的要求只能在H5或者Hybrid上得以實(shí)現(xiàn)炼杖,不過這和架構(gòu)本身關(guān)系不太大,是另一個大的話題盗迟。
4.React-Native & Hot Patch坤邪,這和第三步類似都是由運(yùn)營驅(qū)動,幾乎是所有內(nèi)容運(yùn)營型app的必經(jīng)之路罚缕。
這四步的演化文章介紹的還比較粗略艇纺,更多的細(xì)節(jié)(比如Router內(nèi)部實(shí)現(xiàn),業(yè)務(wù)組件和非業(yè)務(wù)組件的分工邮弹,組件間耦合的方式等)沒有介紹黔衡,或者餓了么App端也還在探索當(dāng)中。
第三類樣本:
樣本名:攜程移動APP架構(gòu)優(yōu)化之旅
作者:陳浩然
攜程App端的架構(gòu)演化在餓了么架構(gòu)基礎(chǔ)之上腌乡,多了很多優(yōu)化的細(xì)節(jié)盟劫。
提到了對于基礎(chǔ)SDK組件和業(yè)務(wù)組件的具體劃分:
核心功能SDK化
? 通訊、定位与纽、Hybrid侣签、數(shù)據(jù)庫、登錄急迂、分享影所、基礎(chǔ)庫等
? 直接提供給其他BU獨(dú)立App使用
公用業(yè)務(wù)功能組件化
? 地圖、日歷僚碎、城市猴娩、圖片、通訊錄等13個公共組件
? 減少各BU重復(fù)開發(fā)工作量
性能數(shù)據(jù)指標(biāo)采集:
? 網(wǎng)絡(luò)性能:網(wǎng)絡(luò)服務(wù)成功率勺阐、平均耗時卷中、耗時分布
? 定位:獲取經(jīng)緯度成功率、城市定位成功率
? 啟動時間渊抽、內(nèi)存仓坞、流量等指標(biāo)
? 多種緯度:系統(tǒng)、App版本腰吟、網(wǎng)絡(luò)狀況无埃、位置等
網(wǎng)絡(luò)優(yōu)化
? 使用TCP長連接實(shí)現(xiàn)網(wǎng)絡(luò)服務(wù)
? 根據(jù)網(wǎng)絡(luò)狀況2G/3G/4G/WIFI進(jìn)行調(diào)優(yōu)參數(shù)
? 根據(jù)連接/讀/寫不同階段使用重試機(jī)制
? 使用IP列表避免DNS解析失敗或者劫持
? 根據(jù)網(wǎng)絡(luò)延遲選擇服務(wù)端IP(使用Ping)
? 使用ProtocolBuffer+Gzip減少Payload
還有Hybrid徙瓶,HotFix,React Native等就不一一列舉了嫉称,這些細(xì)節(jié)性強(qiáng)的分享有很高的學(xué)習(xí)價值侦镇,能對剛涉足某一塊優(yōu)化的架構(gòu)師起到方向指引的作用。
這些看似簡單的劃分往往很考驗(yàn)架構(gòu)師的大局觀和經(jīng)驗(yàn)织阅,涵蓋面和合理的粒度掌控才能讓技術(shù)團(tuán)隊的開發(fā)工作高效并行壳繁。
第四類樣本:
樣本名:Facebook iOS Architecture
作者:Facebook
除了和上面樣本類似的模塊化,組件優(yōu)化的介紹之外荔棉,還有兩方面新的信息:
在關(guān)于Infrastructure的介紹當(dāng)中有張示意圖介紹團(tuán)隊分工:
視頻當(dāng)中不光介紹了基礎(chǔ)組件闹炉,業(yè)務(wù)模塊的劃分,和說明了這些劃分對應(yīng)的團(tuán)隊是如何進(jìn)行協(xié)作润樱。
最底層的是基礎(chǔ)設(shè)施團(tuán)隊渣触,負(fù)責(zé)基礎(chǔ)SDK的開發(fā),可以對應(yīng)之前談到的非業(yè)務(wù)組件壹若。
中間層是業(yè)務(wù)團(tuán)隊嗅钻,按業(yè)務(wù)模塊進(jìn)行劃分,一個業(yè)務(wù)對應(yīng)一個團(tuán)隊店展,團(tuán)隊負(fù)責(zé)全平臺的開發(fā)养篓,業(yè)務(wù)團(tuán)在開發(fā)過程當(dāng)中可反過來回饋基礎(chǔ)SDK。
最上面是產(chǎn)品的發(fā)布團(tuán)隊赂蕴,產(chǎn)品發(fā)布團(tuán)隊配合業(yè)務(wù)團(tuán)隊對產(chǎn)品的發(fā)布周期和質(zhì)量做保障柳弄。
在Facebook iOS客戶端架構(gòu)設(shè)計當(dāng)中有關(guān)于model層介紹:
之前看過不少架構(gòu)分享文章,少有對model層深入探討的概说,一般提到都是一筆帶過语御。model層涉及app數(shù)據(jù)持久化,以及runtime的狀態(tài)維護(hù)席怪,對app的穩(wěn)定性和迭代效率起到至關(guān)重要的影響应闯。
Facebook的model layer采用的是immutable策略,model雖然能被各層訪問挂捻,但model的修改統(tǒng)一由model layer提供接口碉纺。上層業(yè)務(wù)團(tuán)隊一旦想修改某個model property,需要向model layer維護(hù)團(tuán)隊提出申請刻撒,這一設(shè)計對狀態(tài)的維護(hù)相當(dāng)謹(jǐn)慎骨田。
我的思考
將架構(gòu)的類型歸為上述四類也是方便自己搭建關(guān)于架構(gòu)的知識體系,看架構(gòu)類文章的時候先做好分類再按類別查漏補(bǔ)缺汲取營養(yǎng)声怔。我個人在第一類态贤,第二類架構(gòu)方面做過一些嘗試和積累,第三類優(yōu)化上做過一些知識總結(jié)醋火。
第一類比如之前的技術(shù)分享:
iOS的應(yīng)用層CDD架構(gòu)http://mrpeak.cn/blog/cdd/
這種優(yōu)化應(yīng)用層的架構(gòu)方式是在MV(X)系列基礎(chǔ)之上新的嘗試悠汽,已在公司項目當(dāng)中有過實(shí)踐箱吕,成效尚可。
第二類比如:
用Swift搭建數(shù)據(jù)驅(qū)動型iOS架構(gòu)http://mrpeak.cn/blog/swift-dda/
搭建數(shù)據(jù)驅(qū)動型Android架構(gòu)http://mrpeak.cn/blog/dda-android/
用了Swift和Java實(shí)現(xiàn)相同的架構(gòu)思路柿冲,這種架構(gòu)方式也是從已有成熟的項目當(dāng)中總結(jié)提煉而來茬高。
第三類主要是優(yōu)化和總結(jié)的文章:
iOS網(wǎng)絡(luò)請求優(yōu)化之DNS映射
關(guān)于架構(gòu)的總結(jié)就到這里,以上全是一家之言假抄,一則梳理怎栽,二則分享,任何想法建議宿饱,歡迎交流熏瞄。
歡迎關(guān)注公眾號: