我所理解的組件化之路

為什么會有這篇文章呢引镊?

和之前的同事"我是你爸爸"討論了關于組件化的事胸嘁,對我有很大的啟發(fā)。在此特別感謝"我是你爸爸"凹蜂。

最近寫了關于組件二進制化的文章的文章馍驯,有點感觸阁危。

一些朋友來問我關于CocoaPods的問題提到了組件化。

自己一開始準備寫《組件化之路》的博文的汰瘫,但是后來發(fā)現(xiàn)我的理解是有偏差的狂打。

以上,所以我想寫一篇關于《我所理解的組件化之路》的博文來闡述自己的觀點吟吝。

先提出一個新詞菱父,我自己想的。叫做“CocoaPods化”或叫做“l(fā)ibrary化”

什么叫做CocoaPods化剑逃?

CocoaPods化也就是我們公司正在做的浙宜。隨著業(yè)務的擴展,有了多個App蛹磺,有了多個Team粟瞬,我們希望把一些代碼重用。使用CocoaPods把他們做成library是個很好的選擇萤捆。也可以說是CocoaPods化之路裙品。

1.和業(yè)務無關。
開始做這件事的時候俗或,我們會容易的想要把那些Util市怎、Category、JSBrige等等這些和業(yè)務無關的源碼搞在一起做成一個一個CocoaPods庫辛慰。它們變成了YTXUtilCategory区匠、YTXWebViewJavaScriptBridge、YTXNibBrige帅腌、YTXAnimations這些庫驰弄。

2.弱業(yè)務
接下來,進一步地我們會把那些比如網(wǎng)絡請求速客、Server配置戚篙、行情圖、行情Socket等等這些弱業(yè)務的源碼搞在一起溺职。她們變成了YTXRequest岔擂、YTXServerId、YTXChart浪耘、YTXChartSocket智亮、YTXChatUI等等。

為什么說是弱業(yè)務呢点待,稍微分析下阔蛉。比如YTXRequest、YTXChartSocket癞埠、YTXServerId在公司內部各個App状原,各個Team之間是通用的聋呢,在各個業(yè)務組件之間可以重用和組合使用;又帶著鮮明的公司特色颠区,沒法直接開源了就能讓其他開發(fā)者使用削锰。

如果只做到了前2步,我覺得不能稱之為組件化毕莱。只能叫做CocoaPods化或Library化器贩。

3.業(yè)務
這一步,到目前來說沒有做朋截。所以沒法舉我自己實際的例子蛹稍。

比如拿美團App做例子來說。一條業(yè)務線是外賣部服,一條業(yè)務線是電影唆姐。分別由2個Team維護開發(fā)(技術,產品廓八,測試等)奉芦。有各自的KPI。這兩條業(yè)務線是自洽的剧蹂,是分治的声功。

外賣是一個業(yè)務組件,電影也是一個業(yè)務組件宠叼。里面包含了各種內容减噪,各種依賴。外賣可以手寫autolayout车吹,電影可以用storyboard。外賣可以用mvc醋闭,電影可以mvvm窄驹。想怎么搞就怎么搞。他們兩個就像獨立的App一樣证逻。

有不少朋友包括我自己之前乐埠,認為做了前2步就是組件化了。只有真正做到了第3步囚企,并且完善了相關架構丈咐,我才認為能稱之為組件化。

那么我們來看看真正的組件化應該包含什么龙宏,什么情況適合組件化棵逊。業(yè)界內部的討論已經(jīng)有很多了,我來列舉下我自己的看法银酗。

畫一個圖:


default
default

適合的情況

  • 業(yè)務上要分治辆影。
  • Team規(guī)模大徒像,30人+。
  • 業(yè)務越來越多蛙讥,越來越大锯蛀。

如果不符合這些情況,我認為做組件化沒有意義次慢。因為性價比太低旁涤。

有一種情況表面上都符合上面列的條件,但實際上不適合組件化:例如我們公司迫像。雖然有好幾個iOS Team劈愚,雖然總人數(shù)上超過了30人,但每一個Team都只有6~10人侵蒙。每個Team各自維護各自的一個App造虎,各個App業(yè)務上沒有交集,只公用1和2步的CocoaPods庫纷闺。就算有交集算凿,做相同的業(yè)務,也不打算公用或重用這部分代碼(內部有競爭關系)犁功。

我們公司這種情況就像是拆分成了好幾個無關的小公司氓轰,大家都用了github上的一些CocoaPods庫一樣。

還好早期推了第1步和第2步浸卦,避免了每個Team之間都去造差不多功能的輪子署鸡,而能把精力盡量集中在各自的業(yè)務上,避免了一些資源浪費限嫌。

我認為需要包含什么(不分先后順序)

  • App生命周期及事件如何下發(fā)給業(yè)務組件靴庆。
  • 業(yè)務組件之間沒有依賴關系,需要解耦怒医。
  • 解決組件化頁面跳轉的問題炉抒。
  • 解決業(yè)務組件之間通信的問題。
  • 解決如何劃分抽象業(yè)務組件稚叹、基礎功能組件(業(yè)務無關)和弱業(yè)務組件焰薄。
  • 統(tǒng)一的網(wǎng)絡服務,本地存儲方式等扒袖。
  • 去Model化塞茅。
  • 如何披露接口信息,調用方式季率,參數(shù)等等野瘦。
  • 明確組件的生命周期。
  • 提供二進制化方案飒泻。
  • 組件的subspec缅刽。
  • 版本規(guī)范啊掏。
  • 持續(xù)集成。
  • 代碼準入制度衰猛。
  • 統(tǒng)一的命名規(guī)范迟蜜。
  • 集成調試。
  • 代碼維護啡省。

所以我們得出的結論是:不輕易組件化娜睛。而是統(tǒng)籌規(guī)劃好以上所有的內容∝远茫可以不用一步就位全部做好畦戒,但要預先想好每一步的解決方案;能夠承上啟下结序。

如果你要問我說哪一步比較重要障斋,我覺得都挺重要的。要結合自己的實際情況徐鹤,去排一個優(yōu)先級垃环。

App生命周期及事件如何下發(fā)給業(yè)務組件

例如:applicationDidEnterBackground,didRegisterUserNotificationSettings返敬,didReceiveRemoteNotification等等遂庄。
通過注冊方式,App向注冊的業(yè)務組件中的協(xié)議發(fā)送消息劲赠。

業(yè)務組件之間沒有依賴關系涛目,需要解耦

通過依賴協(xié)議,或依賴下沉等方式解耦凛澎。準確拆分業(yè)務組件霹肝,弱業(yè)務組件,基礎功能組件塑煎。保證單一原則沫换、DRY 原則等。

解決組件化頁面跳轉的問題

各種router轧叽。比如MGJRouter
我不建議是淡出使用URL傳參刊棕。理由是可以傳參的對象受限制炭晒。

我們自己有一套叫GOTO的東西。使用分類甥角。唯一的問題网严,你需要知道你要跳轉頁面的去model化參數(shù)是什么,代表該頁面的枚舉是什么嗤无,目前沒法注冊震束。

解決業(yè)務組件之間通信的問題

組件間需要相互調用怜庸,監(jiān)聽回調。不是說不能相互依賴么垢村?對割疾,可以通過依賴協(xié)議或中間件(依賴下沉)等方式解決這個問題。比如CTMediator嘉栓。CTMediator應該是屬于依賴下沉的方式宏榕。

解決如何劃分抽象業(yè)務組件、基礎功能組件(業(yè)務無關)和弱業(yè)務組件

這個得要從各自的實際情況出發(fā)侵佃。但有幾個原則可以借鑒:

  • 重要性
  • 重用性
  • 單一性

統(tǒng)一的網(wǎng)絡服務麻昼,本地存儲方案等

可以通過創(chuàng)建弱業(yè)務Pod庫解決這個問題。

為什么要這么做馋辈?
Team之間人員調動后可以快速入手抚芦。

去Model化

業(yè)務組件間通訊盡量去Model化。否則就得把該Model單獨做成Pod庫迈螟。

去Model化后叉抡,比如使用NSDictionary如何及時傳播具體的參數(shù)信息?(文檔井联?口口相傳卜壕?寫在頭文件?)

如何披露接口信息烙常、調用方式轴捎、參數(shù)和一些規(guī)則等等

文檔?口口相傳蚕脏?寫在頭文件侦副?使用協(xié)議?

各有利弊和適用場景驼鞭。

按目前情況秦驯,我們選擇寫在頭文件。

明確組件的生命周期挣棕。

明確組件的生命周期译隘,就能在App中統(tǒng)一的創(chuàng)建,注冊洛心,集成固耘,協(xié)作,銷毀词身。

提供二進制化方案

二進制化方案能夠提高編譯速度厅目,提升開發(fā)效率。集中注意力在自己維護的業(yè)務組件上。
二進制化方案损敷。

組件的subspec葫笼。

subspec教程。
使用subspec可以降低集成調試門檻拗馒。集中注意力在自己維護的業(yè)務組件上路星。讓組件間依賴更清晰。

版本規(guī)范

可以參考semver瘟忱。

也可以參考我們的:
組件的依賴版本盡量寬泛一點奥额,精確到minor就行。在App里精確到patch就可以了访诱。然后大家只要按照規(guī)范發(fā)版本就可以了垫挨。參考一下這個規(guī)范

持續(xù)集成

主要工具可以有:gitlab runner触菜,jenkins九榔,fastlnefir.im涡相。

持續(xù)集成我們是這樣做的哲泊。

CI工具是gitlab runner。每當一定條件下催蝗,會觸發(fā)build IPA并且上傳到fir.im切威。

dev分支用的是dev證書。
master分支用的是adhoc證書丙号。

測試人員可以通過http://fir.im/TestXXApphttp://fir.im/XXApp來分別下載先朦。

.gitlab-ci.yml中的構建和上傳看起來是這樣的:

xcodebuild -exportArchive -archivePath 'build/p4.xcarchive' -exportPath 'build' -exportOptionsPlist exportOptionsDebug.plist | xcpretty

fir publish build/*.ipa -c $CI_BUILD_REF -T $FIR_TOKEN_DEBUG

在組件化開發(fā)中,一定條件應該是:

  • 業(yè)務組件發(fā)版更新(會自動修改App的Podfile犬缨,然后正常push喳魏。修改的部分不只是業(yè)務組件的版本號,業(yè)務組件可能需要更高版本的其他組件或第三方組件怀薛,它會在Podfile中一并修改這些庫的版本號)
  • dev/master分支正常push
  • 手動觸發(fā)

代碼準入

Build/Test/Lint刺彩,code review,CI枝恋。

有了CI创倔,就可以談談代碼準入了。

  1. Build正常構建成功
  2. 單元測試通過(我們用的Kiwi
  3. Lint通過
  4. deploymate檢查API
  5. OCLint檢查代碼
  6. CocoaPods Lint焚碌。不僅會Build一遍畦攘,還會檢查podspec相關內容設置的對不對。如果沒有用--allow-warnings的參數(shù)呐能,有waring發(fā)生Lint是會不通過的念搬。(建議把warning當作error,不要使用--allow-warings參數(shù))
  7. Code Review摆出。
    1. 檢查發(fā)版規(guī)范朗徊。比如:我們更改了一個弱業(yè)務組件,升了一個patch版本號偎漫,但其實不只是修了bug爷恳,而且還增加了向前兼容的新功能,這個時候應該升的是minor版本號象踊。
    2. 檢查代碼風格温亲。
    3. 檢查潛在的bug。
    4. 檢查其他只有人能看得出的問題杯矩。

.gitlab-ci.yml中的OCLint和dploymate看起來是這樣的:


Deploymate --cli -t jryMobile p4.xcworkspace -V 8.0 -x

xcodebuild -workspace p4.xcworkspace -scheme p4 -configuration Adhoc -archivePath 'build/p4' archive | tee xcodebuild.log | xcpretty

oclint-xcodebuild xcodebuild.log

oclint-json-compilation-database -e Pods -e Chart -e Chart/core/jsoncpp -e RKNotificationHub.m -e TTMessage.mm -e SSNetworkInfo.m -e Tween.mm -e 略...... && echo 'OCLint Passed' || (cat report.json && exit 1)

命名規(guī)范

公司名+組件名+具體名字

集成調試

各自業(yè)務組件如何調試栈虚?應該就和在主App中一樣,只需要在Example App中依賴相關的其他業(yè)務組件即可史隆。

另一種情況是魂务,當業(yè)務組件版本更新時需要自動修改主App的Podfile中的版本,自上而下的觸發(fā)集成泌射。

代碼維護

誰來維護基礎功能組件和弱業(yè)務組件粘姜?如何保證某個Team提交代碼后不會影響其他Team。(包含了:代碼準入熔酷,集成調試孤紧,相互協(xié)作,版本規(guī)范)

需要一個Team專門來做這個事情拒秘。

補充:寫在主App中的業(yè)務号显,要把自己當作業(yè)務組件,不能夠依賴其他業(yè)務組件翼抠。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末咙轩,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子阴颖,更是在濱河造成了極大的恐慌活喊,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件量愧,死亡現(xiàn)場離奇詭異钾菊,居然都是意外死亡,警方通過查閱死者的電腦和手機偎肃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門煞烫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人累颂,你說我怎么就攤上這事滞详×菥悖” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵料饥,是天一觀的道長蒲犬。 經(jīng)常有香客問我,道長岸啡,這世上最難降的妖魔是什么原叮? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮巡蘸,結果婚禮上奋隶,老公的妹妹穿的比我還像新娘。我一直安慰自己悦荒,他們只是感情好唯欣,可當我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著搬味,像睡著了一般黍聂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上身腻,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天产还,我揣著相機與錄音,去河邊找鬼嘀趟。 笑死脐区,一個胖子當著我的面吹牛,可吹牛的內容都是我干的她按。 我是一名探鬼主播牛隅,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼酌泰!你這毒婦竟也來了媒佣?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤陵刹,失蹤者是張志新(化名)和其女友劉穎默伍,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體衰琐,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡也糊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了羡宙。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片狸剃。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖狗热,靈堂內的尸體忽然破棺而出钞馁,到底是詐尸還是另有隱情虑省,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布僧凰,位于F島的核電站慷妙,受9級特大地震影響,放射性物質發(fā)生泄漏允悦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一虑啤、第九天 我趴在偏房一處隱蔽的房頂上張望隙弛。 院中可真熱鬧,春花似錦狞山、人聲如沸全闷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽总珠。三九已至,卻和暖如春勘纯,著一層夾襖步出監(jiān)牢的瞬間局服,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工驳遵, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留淫奔,地道東北人。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓堤结,卻偏偏與公主長得像唆迁,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子竞穷,可洞房花燭夜當晚...
    茶點故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內容