一泽论、為什么要組件化
1.實(shí)現(xiàn)之間解耦漓库、減少項(xiàng)目的編譯時(shí)間廷支,提升業(yè)務(wù)開發(fā)效率。
通常一個(gè)工程中會(huì)有多個(gè)模塊,而模塊之間會(huì)有依賴關(guān)系城侧,比如A調(diào)用B阅仔,那么在A模塊中就會(huì)引用B模塊的頭文件甚脉,同時(shí)可能B模塊又會(huì)依賴C模塊猾瘸,C模塊又會(huì)依賴A模塊等等,最終的結(jié)果是各模塊高度耦合古话,特別是大型的工程雏吭,耦合特別嚴(yán)重。如下圖所示
1)首先是將模塊拆分成組件單獨(dú)管理胀莹,拆分成單獨(dú)的庫(kù),這樣各組件在進(jìn)行開發(fā)的時(shí)候婚温,只需要編譯自己的庫(kù)文件描焰,大大減少文件的編譯時(shí)間,我們的工程栅螟,之前編譯需要20分鐘左右荆秦,現(xiàn)在只需幾分鐘,這個(gè)對(duì)效率提高力图,非常明顯步绸。
2)各個(gè)庫(kù)單端管理,可以進(jìn)行權(quán)限設(shè)置吃媒,只有各組件相關(guān)人員才可以修改組件代碼瓤介,不會(huì)出現(xiàn)一個(gè)大的工程中,A修改了B的代碼的情況赘那,可以一定程度上保證代碼的安全性刑桑。
2.合并項(xiàng)目容易出現(xiàn)沖突。
在每次發(fā)版以后募舟,release分支會(huì)向dev分支合并代碼祠斧,由于各組件會(huì)提交許多代碼,不同的開發(fā)者可能會(huì)同時(shí)修改同一個(gè)文件拱礁,引起沖突琢锋,這樣一個(gè)工程中就會(huì)出現(xiàn)多處的合并沖突辕漂,比如一個(gè)幾十人的團(tuán)隊(duì),這個(gè)沖突的概率非常大吩蔑,需要各組件的人去dev分支修改自己組件的沖突钮热,如果沖突沒有解決,整個(gè)工程都無法運(yùn)行烛芬,影響整個(gè)團(tuán)隊(duì)的開發(fā),非常影響效率飒责。
3.模塊拆分成組件赘娄,方便對(duì)外付能
假設(shè)一個(gè)項(xiàng)目中有多個(gè)組件,相互耦合宏蛉,這個(gè)時(shí)候想單獨(dú)將一個(gè)組件拆分出來遣臼,提供給它人使用,幾乎是不可能的拾并,而組件化接觸這種耦合之后揍堰,我們可以直接將某個(gè)組件單獨(dú)提供給它人使用,各個(gè)組件可以像積木一樣嗅义,相互組合起來屏歹,形成一個(gè)新的APP對(duì)外付能。
二之碗、組件化方案
組件化方案蝙眶,主要分為兩個(gè)部分,一是代碼如何解耦褪那,二是如何進(jìn)行版本管理幽纷,下面分別進(jìn)行詳細(xì)講解。
1.代碼解耦
1)組件原則
組件通常分為兩種類型的組件:基礎(chǔ)組件博敬,業(yè)務(wù)組件友浸。
*業(yè)務(wù)組件依賴基礎(chǔ)組件
*基礎(chǔ)組件不可依賴業(yè)務(wù)組件。
*業(yè)務(wù)組件間不可相互依賴偏窝。
2)組件間的通信方式:
組件間通信方式收恢,業(yè)內(nèi)主要有兩種實(shí)現(xiàn)方式:
1.協(xié)議式框架,比如蘑菇街的這種方案囚枪。蘑菇街 App 的組件化之路
2. 中間者架構(gòu)派诬,比如casatwy的方案。casatwy關(guān)于蘑菇街組件化的討論
我們來總結(jié)一下目前的方案
蘑菇街方案-基于URL和協(xié)議
1)通過URL傳遞簡(jiǎn)單參數(shù)(組件間簡(jiǎn)單參數(shù)調(diào)用)
2)通過協(xié)議調(diào)用傳遞復(fù)雜參數(shù)(組件間復(fù)雜參數(shù)調(diào)用)
缺點(diǎn):
1)頁(yè)面間調(diào)用不需要URL形式链沼,對(duì)于復(fù)雜參數(shù)默赂,組件間調(diào)用通過URL無法滿足需求。
2)注冊(cè)URL時(shí)充分不必要條件括勺,完全可以用runtime來解決這個(gè)問題缆八。
3)使用多種方案曲掰,不利于管理和維護(hù)。
4)protocol主要存在的問題就是分散調(diào)用導(dǎo)致耦合奈辰。
5)需要組件向ModuleManager注冊(cè)Url(因?yàn)閁RL調(diào)用時(shí)通過注冊(cè)時(shí)的callBack來實(shí)現(xiàn)的栏妖,不是基于runtime,所以需要注冊(cè))奖恰,會(huì)導(dǎo)致浪費(fèi)內(nèi)存吊趾。
casatwy的方案-基于Category和Target-Action
主要是基于Mediator模式和Target-Action模式,中間采用了runtime來完成調(diào)用瑟啃。通過mediator的Category來輸出組件的對(duì)外調(diào)用方法论泛。使用同一種方案,實(shí)現(xiàn)組件間調(diào)用蛹屿。
優(yōu)點(diǎn):
1)不需要注冊(cè)URL
2)使用同一種方案屁奏,基于Target-Action模式實(shí)現(xiàn)組件間的調(diào)用。
3)區(qū)分app內(nèi)部調(diào)用和外部調(diào)用错负。
4)同一種方法可以實(shí)現(xiàn)簡(jiǎn)單參數(shù)和復(fù)雜參數(shù)的調(diào)用坟瓢。
我們的方案-基于URL和Target-Action
利用runtime實(shí)現(xiàn)Target-Action模式設(shè)計(jì),通過定義URL協(xié)議確定Target和Action犹撒,通過params來傳遞所有頁(yè)面間調(diào)用的參數(shù)折联,error返回調(diào)用的錯(cuò)誤信息,completion來實(shí)現(xiàn)調(diào)用后的回調(diào)油航。類似以下形式
組件調(diào)用方式:[XXMediator openURL:@"mediator://Target/Action" arg:params error:error completion:callBack]
組件輸出調(diào)用方法:每個(gè)組件有一個(gè)XXModule的類崭庸,在該類中實(shí)現(xiàn)對(duì)外輸出的方法,提供XXMediator中Target和Action谊囚。類的頭文件中包含組件可以調(diào)用的類以及需要傳遞的參數(shù)怕享。
優(yōu)點(diǎn):
1)一種調(diào)用方式,可以實(shí)現(xiàn)簡(jiǎn)單和復(fù)雜參數(shù)調(diào)用镰踏。
2)不需要注冊(cè)函筋,調(diào)用簡(jiǎn)單
3)所有調(diào)用使用同一個(gè)方法實(shí)現(xiàn),只需要引用Mediator奠伪,不需要引用Mediator 的category跌帐。
4)通過URL實(shí)現(xiàn)Target-Action,可以利用URL規(guī)則解析出Target和Action绊率,實(shí)現(xiàn)調(diào)用谨敛。
2.版本管理
版本管理使用 cocoapods,每個(gè)組件都拆成獨(dú)立的pod庫(kù)滤否,并生成一個(gè)配置表脸狸,來進(jìn)行組件間的依賴組件的版本管理,具體內(nèi)容這里就不敘述了。
三炊甲、組件化遇到問題
1.使用Target-Action方式進(jìn)行調(diào)用泥彤,有個(gè)問題就是runtime的時(shí)候,如果對(duì)應(yīng)Target-Action修改了卿啡,怎么提示調(diào)用方
1)靜態(tài)檢測(cè)URL吟吝,判斷Target-Action是否存在。
2)動(dòng)態(tài)調(diào)用router颈娜,debug模式下剑逃,Target-Action不存在就crash。
2.調(diào)用方如何知道接收方需要哪些key的參數(shù)官辽?調(diào)用方如何知道有哪些target可以被調(diào)用炕贵?
1)category方式下,可以直接通過category中的方法來進(jìn)行確認(rèn)野崇。
2)我們的方案中,每個(gè)組件的對(duì)應(yīng)moudle類中亩钟,類的頭文件中包含組件可以調(diào)用的類以及需要傳遞的參數(shù)乓梨。
3.調(diào)用參數(shù)解析處理在那里比較好?
各組件內(nèi)部清酥,因?yàn)檫@些參數(shù)的使用扶镀,各組件開發(fā)者自己最清楚。如果在category解析焰轻,Mediator中會(huì)參雜業(yè)務(wù)邏輯臭觉。
4.A調(diào)用B時(shí),如果B要回傳參數(shù)給辱志,怎么做蝠筑?
通過callBackBlock回調(diào)回傳,參數(shù)是id類型揩懒,可以傳任意對(duì)象什乙,比如是一個(gè)UIViewController或者一個(gè)NSDictionary都可以。
四.組件化的缺點(diǎn):
1.會(huì)增加開發(fā)者的學(xué)習(xí)成本
2.組件拆分顆粒度把握不好已球,會(huì)產(chǎn)生很多中間代碼和冗余臣镣。
3.圖片資源管理不好,會(huì)產(chǎn)生很多冗余圖片智亮。
4.組件化過程中忆某,會(huì)帶來一些組件之間的調(diào)試問題,前期會(huì)影響團(tuán)隊(duì)效率阔蛉。
總結(jié):
組件化是一把雙刃劍弃舒,如果在工程規(guī)模較小的時(shí)候,進(jìn)行組件化馍忽,可能反而會(huì)影響團(tuán)隊(duì)開發(fā)效率棒坏,帶來一些問題燕差,比如上面提到的缺點(diǎn),只是在工程和團(tuán)隊(duì)達(dá)到一定規(guī)模的時(shí)候坝冕,進(jìn)行組件化才會(huì)有更大的收益徒探。
參考資料:
蘑菇街 App 的組件化之路
iOS應(yīng)用架構(gòu)談 組件化方案
蘑菇街 App 的組件化之路·續(xù)
iOS 組件化方案探索
iOS組件化方案 - MrPeak雜貨鋪
京東iOS客戶端組件管理實(shí)踐 - InfoQ