百度App组件化之路
原創(chuàng):GuoJin 百度APP技術(shù)團隊-資深技術(shù)專家 文章來源:百度APP技術(shù)微信公眾號
??????????組件化是一個老生常談的涉及面很廣的話題,即不是做好一件事而是做好一系列的事情才能達成;其中包含組件化框架在內(nèi)的各架構(gòu)層級、構(gòu)建系統(tǒng)、依賴管理系統(tǒng)、以及配套的防劣化機制與規(guī)則規(guī)范。
??????????本文主要基于百度App背景、目標和組件化歷程來講述保障并行開發(fā)和組件復(fù)用的手段,盡量避免過多發(fā)散到構(gòu)建系統(tǒng)、依賴管理系統(tǒng),以及組件化框架這樣的具體子方向。組件化的重要性取決于應(yīng)用規(guī)模、團隊規(guī)模、產(chǎn)品技術(shù)目標;所述內(nèi)容雖然是從iOS平臺出發(fā),但方法論與實現(xiàn)路徑適用于大部分平臺。
背景與目標
百度App(大型App)復(fù)雜度來源
- 業(yè)務(wù)規(guī)模大:百度App技術(shù)方向及子方向70+,單端代碼量180w+;
目標:隔離各組件間影響避免故障蔓延,并控制整體App的復(fù)雜度; - 團隊規(guī)模大:有代碼權(quán)限的數(shù)百人;
目標:保障高效并行開發(fā); - 公司內(nèi)部接入業(yè)務(wù)多:30+,非單純基礎(chǔ)庫,與百度App關(guān)系復(fù)雜;
目標:處理接入業(yè)務(wù)與百度App架構(gòu)及架構(gòu)中各組件關(guān)系,保障快速高效接入與基礎(chǔ)能力復(fù)用。 - 迭代速度快:3周一個版本,2周開發(fā)1周測試;
目標:避免高速迭代情況下組件化程度劣化。 - 技術(shù)形態(tài)多:H5、NA、Hybrid、Talos、Flutter并存;
目標:保障基礎(chǔ)能力復(fù)用,構(gòu)建系統(tǒng)支撐。
另外啟動速度、體積等準入流程的約束;以及目標的多樣性也是大型App復(fù)雜度來源因素;由背景產(chǎn)生的目標是天生的技術(shù)需求,除此之外,百度App在不同階段有不同的產(chǎn)品技術(shù)目標。
百度App不同階段的不同目標
- 合作業(yè)務(wù)三方庫復(fù)用;單個技術(shù)組件輸出(最早的需求,2014年),對單個組件輸出來講,如何避免輸出時,拔出蘿卜帶出"泥";
- 矩陣產(chǎn)品孵化(2017年~2019);
- 小程序開源復(fù)用(2018年):輸出組件兼容不同宿主,保持部分依賴組件可替代性;
目標多樣性要求在開發(fā)時考慮到各個目標的訴求,在方案設(shè)計時盡量避免和這些目標沖突。
重要架構(gòu)迭代
初始態(tài)-2013(鉆木取火):
這一時期,百度App瀏覽器角色較重,大家都在一個工程里開發(fā),各業(yè)務(wù)和基礎(chǔ)邏輯交錯,沒有邊界,你中有我、我中有你;UI架構(gòu)比較復(fù)雜,每個RD都要從App主入口開始看懂主流程代碼,小心翼翼的開發(fā)。
這一時期的架構(gòu)是這樣:
這一時期的主要問題有:
- 一些基礎(chǔ)庫、甚至開源三方庫都會有業(yè)務(wù)侵入;沒有明確分層和防修改機制,入侵成本極低;
- 首屏各業(yè)務(wù)間沒有容器隔離,牽一發(fā)而動全身,極容易互相影響;
- 對各業(yè)務(wù)共用的服務(wù)(遠程配置、端能力)沒有服務(wù)組件化,if else/switch case式邏輯無限蔓延;
- 邏輯、資源沒有合理歸屬,數(shù)據(jù)沒有拆分,基礎(chǔ)組件對外輸出困難;
- 插件接口層沒有體系化建設(shè),穩(wěn)定性欠佳(fragile);接入業(yè)務(wù)成為百度App里的超級模塊,依賴關(guān)系難以控制。
2014-2015(蒸汽機時代):
雖然當(dāng)時團隊規(guī)模只有幾十人,但已經(jīng)意識到了組件化的重要性;接入業(yè)務(wù)逐步變多,同時也有部分技術(shù)組件對外輸出的需求;這一階段:
- 首先拆出三方庫,粗粒度拆出基礎(chǔ)庫,歸到業(yè)務(wù)組件下層;百度App和接入業(yè)務(wù)復(fù)用這部分基礎(chǔ)庫;
- 引入框架容器,對首屏各業(yè)務(wù)及棧式導(dǎo)航容器中的業(yè)務(wù)進行隔離;
- 對新興的業(yè)務(wù)組件或需要重構(gòu)的業(yè)務(wù),首先采用組件化模式開發(fā),邏輯、資源、數(shù)據(jù)各有歸屬,同時明確外部依賴;
- 初步制定了依賴規(guī)范,禁止層級反向依賴,這一階段只是規(guī)范,沒有工具鏈的強制支撐;
- 組件除基礎(chǔ)庫外的依賴通過Adapter注入來實現(xiàn)。
這一時期的架構(gòu)是這樣:
這一時期的主要問題有:
- 組件歸屬的模糊性,部分組件游離在基礎(chǔ)庫和業(yè)務(wù)組件之間,同層組件間的依賴與調(diào)用關(guān)系不夠清晰;
- 組件間通過Adapter進行一對一解耦,雖然有比較明確的外部依賴關(guān)系,但解耦效率不高;
- 主App中還遺留端能力接口,與通過插件系統(tǒng)接入的一些SDK。
2016-2017(電力時代)
這一時期重點建設(shè)了組件化框架(Pyramid、SchemeRouter)與分發(fā)框架(RemoteConfig、PMS、預(yù)取分發(fā)),及數(shù)據(jù)拆分框架(CocoaSetting);進一步保障了各組件能做到邏輯、數(shù)據(jù)各有歸屬;
這一時期的架構(gòu)是這樣:
2018-2019(理想態(tài)-核能時代)
這一時期,組件化框架相對完善,各組件已能做到邏輯、資源、數(shù)據(jù)各有歸屬。主工程進一步被弱化;
- 層級更加明確清晰,游離與基礎(chǔ)庫層和業(yè)務(wù)組件層間的通用服務(wù)有了歸屬;組件可以自下而上的對外輸出;
- 整個App通過中央倉庫的組件列表(Central Repo Specs),經(jīng)過EasyBox組裝整個工程;
- 框架容器加載及系統(tǒng)事件分發(fā)統(tǒng)一到輕量級的AppLauncher;
- 對接入SDK,按架構(gòu)層級屬性歸屬;如僅被某一個業(yè)務(wù)組件引用,則有這個業(yè)務(wù)組件負責(zé)管理,降低對外的復(fù)雜度;
- 服務(wù)層可共享服務(wù)相對完善。
組件化的進階-中臺化(星際遠航)
中臺化的大潮滾滾而來,除云端一體化復(fù)用外,對組件化也提出了其他的更高要求。共享組件庫+構(gòu)建系統(tǒng)(EasyBox)合力,已能達到矩陣產(chǎn)品組合輸出能力。
組件化的實現(xiàn)路徑
自下而上的組件化建設(shè)
1、編譯隔離、架構(gòu)分層及層級訪問限制機制建立
- 編譯隔離:通過構(gòu)建系統(tǒng)(EasyBox)提供的編譯規(guī)則文件明確每個組件的對外接口,明確組件的外部依賴(這方面IDE也經(jīng)常好心辦壞事,讓組件間可以低成本的隨意訪問,逐步模糊了組件的邏輯邊界,加深了組件間的依賴);
- 層間限制:通過構(gòu)建系統(tǒng)(EasyBox)建立反向訪問限制,即下層組件不可以訪問上層組件;
- 同層訪問:同層組件間也不能無限制調(diào)用,通信及訪問限制通過組件化Pyramid框架來完成;各組件間維持較清晰的接口邊界和邏輯邊界。
2、三方庫規(guī)范化與基礎(chǔ)庫體系化
1)基礎(chǔ)庫主要存在以下問題:
- 沒有防修改機制,業(yè)務(wù)侵入成本低;
- 交叉依賴問題:同一基礎(chǔ)依賴的邏輯歸屬到同一組件里;
基礎(chǔ)庫要在無業(yè)務(wù)侵入的情況下經(jīng)過一定程度的抽象到架構(gòu)底層,二進制化實行組件負責(zé)人制度,并進行體系化建設(shè)避免上述問題。
2)三方庫主要存在以下問題:
- 沒有防修改機制,業(yè)務(wù)侵入成本低;
- 三方庫在一定用戶規(guī)模或業(yè)務(wù)規(guī)模下,確實存在bug,而github的push request不及時或無響應(yīng);
所有三方庫更新到最新發(fā)布版并二進制化避免業(yè)務(wù)侵入;差異部分明確修改點,通過運行時單獨打補丁;對外輸出時,明確這一點。
3、建立運行時分發(fā)與隔離服務(wù)
為避免各組件對共有邏輯、共有數(shù)據(jù)集中式處理,建立容器及分發(fā)機制來分發(fā)事件、數(shù)據(jù)、以及邏輯調(diào)用。
Pyramid組件化框架:
- 這里主要講Pyramid框架的分發(fā)作用,Pyramid將系統(tǒng)事件分發(fā)給各子組件;
- 除此之外,組件化框架還有另外兩個作用:
1)Pyramid框架組件間通信:adapter一對一方式解耦升級為一對多解耦;
2)它將組件間的強依賴轉(zhuǎn)變?yōu)槿跻蕾?#xff0c;這讓技術(shù)組件對外輸出時,被依賴的組件具有某種程度的可替代性;
端能力:
- 分離SchemeRouter與SchemeHandler邏輯,SchemeRouter歸屬服務(wù)層組件化框架,SchemeHandler歸屬各組件;
- 由于Scheme參數(shù)不夠明確清晰,在百度App中Scheme主要用于和H5的通信,較少用于頁面路由;
配置分發(fā)服務(wù):將集中解析并調(diào)用各業(yè)務(wù)處理邏輯改造為分發(fā)機制,并最終升級為云控服務(wù);
數(shù)據(jù)拆分服務(wù):配合配置分發(fā)服務(wù),將數(shù)據(jù)拆分到各組件內(nèi)部管理;
資源/預(yù)取分發(fā)服務(wù):建立資源/預(yù)取分發(fā)服務(wù);
框架容器:通過Tab導(dǎo)航容器、棧式導(dǎo)航容器將各控制器UI數(shù)據(jù)拆分到各子控制器、事件分發(fā)傳遞給各子控制器;
分發(fā)與隔離機制、容器機制是并行開發(fā)的重要保障。
4、服務(wù)層建立
多業(yè)務(wù)調(diào)用的低依賴組件去業(yè)務(wù)化抽象成通用服務(wù):賬號、分享、云控、統(tǒng)計、性能、AI等
5、建立組件模型
建立組件模型,各業(yè)務(wù)模塊快速組件化。
- 通俗的講,就是指導(dǎo)各業(yè)務(wù)模塊明確功能范圍,做到邏輯、資源、數(shù)據(jù)、私有SDK各有歸屬;
- 最終每個組件是一個獨立的功能單元、邏輯單元、數(shù)據(jù)及資源管理單元,H5通信單元,性能量化單元,編譯輸出單元(1個或多個)。
- 為了更靈活的組合輸出,組件的接口封裝層和服務(wù)對接層可以進行不同粒度編譯單元拆分;主要目的是分離依賴,滿足輸出靈活性;
6、業(yè)務(wù)組件化
按照組件模型,確定業(yè)務(wù)的功能范圍、邏輯與接口邊界,快速組件化。
7、劣化控制
組件接口變更、依賴變更、Warning數(shù)變化都會記錄通知相關(guān)負責(zé)人,這些在Tekes平臺管理;敬請繼續(xù)關(guān)注后續(xù)公眾號文章;沒有防劣化機制,填坑速度永遠比不上挖坑速度;一人填坑的速度也永遠比不上多人挖坑速度。
收益總結(jié)
1.研發(fā)效率的提升,主要體現(xiàn)在以下幾個方面:
- 復(fù)雜度控制:復(fù)雜度控制在組件內(nèi)部,對外"簡單可依賴";
- 并行開發(fā):組件化框架及各分發(fā)服務(wù)具備設(shè)計時的隔離性,保障大規(guī)模并行開發(fā)效率;以遠程配置為例,原來新增一項開發(fā)時間為4+小時,現(xiàn)在僅需0.5小時;效率提升8倍+;
- 復(fù)用:為矩陣產(chǎn)品輸出輪子;參考百度App矩陣產(chǎn)品,復(fù)用率都在50%以上;
- 編譯速度提升:因為組件具有獨立編譯單元的屬性,在編譯過程中組件源碼和編譯產(chǎn)物可以等價替換,所以組件化也為后續(xù)組件二進制化打下基礎(chǔ),百度App編譯速度也平均值從15分鐘/次優(yōu)化到2分鐘/次;
2.質(zhì)量上,組件化具備設(shè)計時的隔離性,確保單個組件的故障影響范圍內(nèi)斂到自己內(nèi)部,不會引發(fā)整體crash;
3.為啟動速度、體積等方向提供量化單位;
4.建立健全架構(gòu)體系,分組件深度優(yōu)化。
吳軍博士在《文明之光》一書中評價希臘人對世界文明的貢獻這樣寫到:近代自然科學(xué)的很多體系都是在古希臘時代奠定的,希臘人在學(xué)術(shù)研究上有別于東方文明之處不在于一兩項科學(xué)發(fā)明和發(fā)現(xiàn),而在于他們將自然科學(xué)各學(xué)科分門別類,對每一個學(xué)科都建立起一整套系統(tǒng)的體系,在此基礎(chǔ)上,演繹或歸納出普遍規(guī)律性,即定理或定律,繼而成為自然科學(xué)各個學(xué)科的基石和支柱。
雖然沒有這樣的高度,但對軟件開發(fā)來講,也有異曲同工的作用。
結(jié)語
"自己"得來終覺淺,引用一段話作為結(jié)語,節(jié)選自《每個架構(gòu)師都應(yīng)該研究下康威定律》
架構(gòu)的目標是用于管理復(fù)雜性、易變性和不確定性,以確保在長期的系統(tǒng)演化過程中,一部分架構(gòu)的變化不會對架構(gòu)的其它部分產(chǎn)生不必要的負面影響。這樣做可以確保業(yè)務(wù)和研發(fā)效率的敏捷,讓應(yīng)用的易變部分能夠頻繁地變化,對應(yīng)用的其它部分的影響盡可能的小。
參考
- 每個架構(gòu)師都應(yīng)該研究下康威定律:
https://www.infoq.cn/article/every-architect-should-study-conway-law - 3 Key Software Principles You Must Understand:
https://code.tutsplus.com/tutorials/3-key-software-principles-you-must-understand–net-25161
總結(jié)
以上是生活随笔為你收集整理的百度App组件化之路的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Eclipse打印Java的char默认
- 下一篇: unity之动画编辑器