iOS組件化方案調研

iOS組件化方案探索

一、什么是組件化?

1、什么是組件?

"組件"一般來說用于命名比較小的功能塊,如:下拉刷新組件、提示框組件。而較大粒度的業務功能,我們習慣稱之為"模塊",如:首頁模塊、我的模塊、新聞模塊。

這次討論的主題是組件化,這里為了方便表述,下面模塊和組件代表同一個意思,都是指較大粒度的業務模塊。

2、什么是組件化?

組件化,或者說模塊化,用來分割、組織和打包軟件。每個模塊完成一個特定的子功能,所有的模塊按某種方法組裝起來,成為一個整體,完成整個系統所要求的功能。

從工程代碼層面來說,組件化的實施通常是通過中間件解決組件間頭文件直接引用、依賴混亂的問題;從實際開發來說,組件之間最大的需求就是頁面跳轉,需要從組件A的pageA頁面跳轉到組件B的pageB頁面,避免對組件B頁面ViewController頭文件的直接依賴。

二、為什么要組件化?

從兩個方面論述:

1、組件化是為了解決什么問題?

一個 APP 有多個模塊,模塊之間會通信,互相調用,如我們的證券app,有首頁、行情、資訊、我的等模塊。這些模塊會互相調用,例如 首頁底部需要展示部分資訊、行情;行情底部需要展示個股資訊;資訊詳情頁需要跳轉到行情,等等。

一般我們是怎樣調用呢,以首頁調用資訊為例,會這樣寫:

#import "HomeViewController.h"
#import "NewsViewController.h"

@implementation HomeViewController

+ (void)gotoNews {

 NewsViewController *detailVC = [[NewsViewController alloc] initWithStockCode:self.codeNum];
 [self.navigationController.pushViewController:detailVC animated:YES];
}

@end

看起來挺好,這樣做簡單明了,沒有多余的東西,項目初期推薦這樣快速開發,但到了項目越來越龐大,這種方式會有什么問題呢?

  • 問題1,每個模塊都離不開其他模塊,互相依賴粘在一起成為一坨:
各模塊互相依賴.png

耦合比較嚴重(因為沒有明確的約束,「組件」間引用的現象會比較多)

  • 問題2,多人同時開發時,容易出現沖突(尤其是Xcode Project文件)
  • 問題3,業務方的開發效率不夠高(只關心自己的組件,卻要編譯整個項目,與其他不相干的代碼糅合在一起)

2、組件化的好處?

一般意義:

  • 加快編譯速度(不用編譯主客那一大坨代碼了);
  • 各組件自由選擇開發姿勢(MVC / MVVM / FRP);
  • 組件工程本身可以獨立開發測試,方便 QA 有針對性地測試;
  • 規范組件之間的通信接,讓各個組件對外都提供一個黑盒服務,減少溝通和維護成本,提高效率;

對于公司已有項目的現實意義:

  • 業務分層、解耦,使代碼變得可維護;
  • 有效的拆分、組織日益龐大的工程代碼,使工程目錄變得可維護;
  • 便于各業務功能拆分、抽離,實現真正的功能復用;
  • 業務隔離,跨團隊開發代碼控制和版本風險控制的實現;
  • 模塊化對代碼的封裝性、合理性都有一定的要求,提升開發同學的設計能力;
  • 在維護好各級組件的情況下,隨意組合滿足不同客戶需求;(只需要將之前的多個業務組件模塊在新的主App中進行組裝即可快速迭代出下一個全新App)

3、什么情況下進行組件化比較合適?

當然組件化也有它的缺點:

  • 學習成本高,對于開發人員對各種工具的掌握要求也比較高,對于新手來說入門較為困難。

  • 由于工具和流程的復雜化,導致團隊之間協作的成本變高,某些情況下可能會導致開發效率下降。

當項目App處于起步階段、各個需求模塊趨于成熟穩定的過程中,組件化也許并沒有那么迫切,甚至考慮組件化的架構可能會影響開發效率和需求迭代。

而當項目迭代到一定時期之后,便會出現一些相對獨立的業務功能模塊,而團隊的規模也會隨著項目迭代逐漸增長,這便是中小型應用考慮組件化的時機了。這時為了更好的分工協作,團隊安排團隊成員各自維護一個相對獨立的業務組件是比較常見的做法。

在這時這個時候來引入組件化方案,是比較合適的時機。長遠來看,組件化帶來的好處是遠遠大于壞處的,特別是隨著項目的規模增大,這種好處會變得越來越明顯

三、如何組件化?

組件化的開展需要解決以下幾個層次的問題:

1、組件化的架構目標?

借用Limboy的圖:

組件化架構.png

2、如何劃分組件?

  • 基礎功能組件
  • 基礎產品組件
  • 個性化業務組件

對于一個沒有實施過組件化拆分的工程來說,其中很可能充滿了大量不合理的類、方法、頭文件和各種錯亂的依賴關系,因此首先要進行的第一步是模塊拆分。

模塊拆分可以分成兩個部分,基礎模塊拆分和業務模塊拆分。基礎模塊通常是穩定的依賴代碼,業務模塊是涉及到業務的需要頻繁改動的代碼。

基礎模塊拆分

基礎模塊是任何一個App都需要用到的,如:性能統計、Networking、Patch、網絡診斷、數據存儲模塊。對于基礎模塊來說,其本身應該是自洽的,即可以單獨編譯或者幾個模塊合在一起可以單獨編譯。所有的依賴關系都應該是業務模塊指向基礎模塊的。
基礎模塊之間盡量避免產生橫向依賴。

業務模塊拆分

對于業務模塊來說,考慮到舊有代碼可能沒有相關的橫向解耦策略,業務模塊之間的依賴會非常復雜,難以單獨進行拆分,因此我們采用的方法是首先從 group 角度進行重新整理。

對業務量很大的工程來說,我個人更加推薦“業務-分層”這樣的結構,而不是“分層-業務”,即類似下面的 group 結構:

- BusinessA
  - Model
  - View
  - Controller
  - Store
- BusinessB
  - Model
  - View
  - Controller
  -Store

而非目前項目中采用的:

- Controllers
  - BusinessA_Controller
  - BusinessB_Controller
- Views
  - BusinessA_View
  - BusinessB_View
- Models
  - BusinessA_Model
  - BusinessB_Model

3、組件化的技術難點?

組件化的實施,直觀上看,只是需要將各業務組件的代碼放到各自的文件夾或者 jar包里就行了。

這里引出的是:

3.1、組件的拆分方式問題:

可以利用CocoaPods 配合 git 做代碼版本管理,獨立業務模塊單獨成庫。

但這僅僅是物理上拆分了,拆分后的代碼編譯是肯定通不過的,因為如下:


#import "MainViewController.h"
#import "HomeViewController.h"
#import "NewsViewController.h"
#import "MeViewController.h"
#import ...

@implementation MainViewController

@end

MainViewController 會找不到依賴的其它各個模塊的頭文件而報錯。這里引出的又是另一個問題:

3.2、組件間如何解耦?

組件間解耦,是組件化必須解決的一個問題。換句話說,就是如何解除業務模塊間的橫向依賴。還是拿上邊舉得例子來說:

App的根視圖MainViewController需要管理首頁、新聞、我的等等頁面時,如何做到 MainViewController 中,不用去 import這一大堆 XXViewController ?

很簡單,按軟件工程的思路,下意識就會加一個中間層Mediator:

中間層.png

這樣一來,各個模塊直接都不需要再互相依賴,而是僅需要依賴 Mediator 層即可。

可直觀上看,這樣做并沒有什么好處,依賴關系并沒有解除,Mediator 依賴了所有模塊,而調用者又依賴 Mediator,最后還是一坨互相依賴,跟原來沒有 Mediator 的方案相比除了更麻煩點其他沒區別。

我們希望最終能過實現的是單向的依賴,即:

單向依賴.png

3.3、對此,可以參考業內的流行方案:

具體實現方案較為抽象,這里暫時先不詳細展開論述,可以參見Demo:

Demo1 基于 Target-Action

Demo2 基于 URL Router

四、其它

開發流程控制

托管平臺選擇

自己利用開源的方案搭建私有的托管平臺,可以最大限制地保證代碼的安全。開源方案當中最知名也是最為廣泛使用的當屬 Gitlab。

組件化使我們從單一的主工程,變成了主工程+多個拆分好的基礎模塊+統一的私有 Spec 倉庫。為了避免某個人的工作對其他人開發環境造成影響,需要對整個組的開發流程進行統一的規范。

不管是對于主倉庫和子模塊倉庫,git-flow 都是首先推薦的工作流程。一個倉庫的 master 分支只有所有者可以有權限更改,其他的貢獻者想更改的話,需要自己創建新的分支(在 Github 上就是進行 fork),然后進行更改,之后把更改向原倉庫發送 Pull Request。Pull Request 就是一個合并的請求,其中可以看到貢獻者的更改,項目主人和其他維護者可以對 Pull Request 進行審核,共同探討修改意見。當項目主人認為修改 OK 之后,就可以合并這個 Pull Request ,把這部分代碼合并到主分支。

這個流程是完全分布式的,也就是說可以同時有多個貢獻者在不同的分支進行工作,最后統一合并到主分支上,實現并行協作。

同時在審核 Pull Request 階段,除了人工審核代碼之外,Github 還加入了對于持續集成的支持,可以檢測這個 Pull Request 是不是能夠通過測試的,進一步保證了代碼的質量。

組件維護問題?

待補充

五、參考資料:

相關技術博客:

1、iOS應用架構談 組件化方案

2、蘑菇街 App 的組件化之路

蘑菇街 App 的組件化之路·續

3、iOS 組件化方案探索

4、《iOS應用架構談 組件化方案》和《蘑菇街 App 的組件化之路》的閱讀指導

5、淺析 iOS 應用組件化設計

6、糯米移動組件架構演進之路

7、餓了么移動APP的架構演進

8、滴滴出行iOS客戶端架構演進之路

9、ios業務模塊間互相跳轉的解耦方案

10、iOS組件化思路-大神博客研讀和思考

11、模塊化與解耦

相關解決方案

1、casatwy/CTMediator

2、mogujie/MGJRouter

3、joeldev/JLRoutes

4、Huohua/HHRouter

5、clayallsopp/routable-ios

6、Lede-Inc/LDBusBundle_IOS

私有Cocoapods實施方案

1、使用Cocoapods創建私有podspec - GeekerProbe

2、Cocoapods系列教程(三)——私有庫管理和模塊化管理

3、iOS組件化實踐方案-LDBusMediator煉就

4、基于 CocoaPods 和 Git 的 iOS 工程組件化實踐

5、Cocoapods代碼管理

6、CocoaPods創建私有Pods

7、如何創建私有 CocoaPods 倉庫

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,646評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,595評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,560評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,035評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,814評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,224評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,301評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,444評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,988評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,804評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,998評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,544評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,237評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,665評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,927評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,706評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,993評論 2 374

推薦閱讀更多精彩內容