前言:本篇文章是諸葛找房 iOS 技術團隊近半年組件化實施之路的經驗積累與沉澱,近半年來咱們的組件化經歷了從0到1的質變,開發方式由原有的多人混合開發逐漸變爲了相對獨立的分業務線開發,而且已經初步實現了同一組件在不一樣項目下的快速集成,組件化帶來的便捷與迅速正在慢慢地向咱們鋪展開來,後續充滿想象空間。然而對一個已經在線上運營多年的系統進行組件化,並非一條容易的路,這一路咱們升級打怪,聚集全組人的智慧,及時的調整組件化結構,讓它不至於走彎路。今天咱們將主要從工程實施的方方面面與你們分享一點咱們的看法,文章較長,建議你們先收藏哈。git
Router
,Protocol
,Target-Action
.咱們採用了第三種,在此要感謝casa
前輩的智慧與無私貢獻。至於選用哪種,不在今天的討論範圍內,由於不管你打算或者正在使用哪種,與今天咱們要講的都沒有衝突。將一個工程組件化,就像是從新建造一個結構設計不合理的大樓同樣,這個大樓的各類線路、各類管道都雜糅在一塊兒,承重牆和傢俱東倒西歪,雖然能提供正常的居住服務,可是後續對大樓的的改造與裝修卻很費事。爲了之後能容納更多人居住、提供更好的居住體驗,有必要在如今對大樓進行重建。在改造的過程當中,仍然須要提供正常的居住服務,所以大樓不能採用爆破的方式徹底推到重建,由於那樣的成本太高,只能在每一次版本迭代中進行組件化,組件化對用戶和市場來講是無感知的纔對。改造的時候是一個房間一個房間的改造,須要進行房屋的物品歸類、線路拆分、垃圾傾倒等各類準備工做,而後就是把全部相關東西都挪出去進行單獨改造,挪出去的時候要保證整棟大樓不會倒塌,其餘的功能不受影響才能夠,挪出去的東西要組裝成一間功能獨立的屋子,這個屋子就是一個小的生態系統,後續的維修與改造都只須要care這個屋子就能夠;建好這個屋子後,須要再把它放回原處,這間屋子就能夠正常住人了。跨域
一、組件預處理bash
預處理須要在主工程中進行,預處理的主要目的是爲了給第二步組件從主工程抽離達到單獨運行鋪平道路,因爲預處理髮生在主工程中,所以預處理階段不須要考慮代碼同步的問題,預處理主要包括如下幾個方面:網絡
target-action
方案,就都經過mediator
進行頁面跳轉和服務調用,但組件內部能夠沒必要採用這種方式。相似於拆承重牆以前,先從別的地方運一些足夠結實的柱子過來,支撐在原來的地方,保證屋子拆出去後,大樓不會發生倒塌。二、組件抽離、編譯、運行架構
pod lib create XXX
命令建立一個pod
工程, 而後配置該組件的podspec
文件,指明該組件都須要依賴哪些庫。Development Pods
中的class
中,將圖片資源放到Asset
中。三、組件引入工具
以上大體的介紹了業務組件拆分的三個大階段,接下來咱們再看下組件拆分過程當中遇到的一些具體問題,這些問題相信你們在實踐中基本都會遇到。
注:業務組件能夠沒必要進行pod
發版,一是由於業務組件開發中頻繁的發版很耗時間,二是業務組件擁有本身的tag
,沒必要經過pod
版本號進行控制。能夠直接在主工程的podfile
中以開發庫的方式引入業務組件,開發庫通常有兩種方式,分別是path
和commitId
方式。組件化
path
方式path
方式是指業務組件在主工程中以路徑的方式引入,這個路徑能夠是相對的也能夠是絕對的,通常選用相對路徑,即將全部的組件與主工程都放在一個文件夾下,這樣在主工程中就能夠用下面的方式引入業務組件。
pod 'ZGAModule', :path=>'../ZGAModule/'
Jenkins
打包,會污染Jenkins
環境。commitId
方式commitId
方式要求開發庫在主工程中以該組件遠端倉庫地址的方式引入,能夠指定commitId
,也能夠不指定。不指定commitId
的話,就默認始終指向最新的業務代碼。
commitId
:pod 'ZGAModule', :git => 'git@git.zhuge.com:iOS/ZGAModule.git', :commit => '1234567'
commitId
:pod 'ZGAModule',:git => 'git@git.zhuge.com:iOS/ZGAModule.git'
或者pod 'ZGAModule',:git => 'git@git.zhuge.com:iOS/ZGAModule.git', :branch => 'dev'
pod install
安裝各個組件便可;不侵入Jenkins
的環境;commitId
,那麼組件更新後,主工程只能用pod update
的方式更新該組件,速度較慢;若是指定了commitId
,那麼每次改動組件後都獲得主工程的podfile
中,修改該組件的commitId
;commitId
,這樣就會始終指向最新的業務組件;但podfile
中全部的業務組件都有一份以path
方式引入的備份,只不過在遠端這些path
引用是被註釋掉的。之因此有這些path
備份,是爲了方便開發人員在本地自由切換,最大限度的提高開發效率。commitId
方式改爲path
方式,調試經過後,再將podfile
改回去,而後直接提交對應組件的改動。update
該組件便可。install
、commit
、update
等一系列操做,或者經過腳本進行兩個不一樣repo
之間的merge
操做,但這樣作都須要再開發維護一套腳本,致使系統複雜性變高。podfile
的大體寫法#******************** 諸葛私有庫 ********************
#遠端庫
#A業務
pod 'ZGAModule',:git => 'git@git.zhuge.com:iOS/ZGAModule.git'
pod 'ZGBModule',:git => 'git@git.zhuge.com:iOS/ZGBModule.git'
pod 'ZGCModule',:git => 'git@git.zhuge.com:iOS/ZGCModule.git'
# 本地庫(遠端這些本地庫方式必定是被註釋掉的,review的時候若是發現被打開了,那麼能夠將本次提交打回去,或者開發相關腳本進行監測)
#A業務
# pod 'ZGAModule', :path=>'../ZGAModule/'
# pod 'ZGBModule', :path=>'../ZGBModule/'
# pod 'ZGCModule', :path=>'../ZGCModule/'
複製代碼
這裏咱們主要分享下如何在人員有限、需求不斷地狀況下處理好組件化與版本迭代之間的時間衝突。post
首先咱們提出一個簡單的概念,這個概念你們一聽便知:需求開發時間佔比,也就是版本需求開發時間佔當天有效開發總時間的比例,並給出高(80%)
、中(50%-80%)
、低(50%如下)
三個時間檔。假設咱們能夠在版本迭代過程當中需求開發時間佔比爲中
和低
的全部時間段進行組件化開發。測試
下面咱們再看下版本迭代的大體生命週期,不一樣公司可能稍微有些差別,但大體是類似的。spa
一個業務組件的通常生命週期以下 :
組件的開發時機要避開需求開發時間佔比較高的時間段,從上圖中能夠看出,組件的開發時間主要是如下兩個時間階段:
爲了保證線上服務的穩定性,須要對新抽離的組件進行多輪測試,尤爲是組件代碼跟主工程代碼不一樣步的狀況下,更要增強測試。能夠採用三級測試的方式進行測試:
matser
master
主工程差距較大,不少文件被移動,進行代碼合併時必然會產生不少沒必要要的衝突,所以組件化工程測試完畢後,若是不想解決那些衝突,能夠不採起合併到master
的方式,而是直接替換master
上的工程master
遷出git
開發準則和gerrit
代碼review
準則git
項目,目前能夠作到針對某一個業務進行代碼回滾,而沒必要主工程總體回滾,回滾時直接在主工程中從新指定commitId
便可mediator
引用,也不太好,不如拆成一個一個的小組件ZGNewHouseModuleNewHouselistVC
。關於組件的個性化解決方案,目前可供咱們選擇的主要有兩種,一個是在組件內部經過環境變量來區分不一樣端,另外一個是經過git
的分支進行管理。
兩種方案各有優缺點,至於選用哪種方案必須從業務當前的類似性
和業務以後的發展趨勢(只是同步現有的代碼仍是同步之後全部的代碼、產品之間的差別)
、代碼基礎環境類似性
和代碼複雜度
、開發人力
等幾個方面綜合考慮,具體分析,不能盲目的選擇。 簡單看下這兩種方案:
組件須要對外暴露一個設置當前App類型的接口,組件保存該類型後,開發者須要在組件內部有區別的地方經過該App類型進行區分,來展現不一樣的視圖、提供不一樣的功能與服務。
優勢:
缺點:
業務組件爲每個應用都創建對應的分支,以C端的新房組件爲例,master
分支爲C
端的新房,經紀人端的新房從master
分出,能夠叫作newhouse_agent
分支,開發人員在各個分支中進行組件化的差別性開發。共性的東西由master
的維護者開發。從現有的C端實際狀況來看的話,基本不存在個性化分支合併到master
的狀況,由於經紀人業務不太可能面向C端用戶,只存在master
往別的分支合併的狀況,經過git
的代碼合併來同步共性業務。
優勢:
git
多分支進行管理,組件內部,不須要定義App
類型,複雜度低,維護成本低。master
的開發者、通常是組件的建立者維護。個性化需求由對應端的開發者維護,分工明確。原則上容許master
合併到其餘分支,不容許其餘分支合併到master
,其餘分支和分支之間能夠根據業務需求有選擇性的合併。共性業務一樣只須要修改一次便可,原則上master
上是個性化最少的組件。缺點:
master
分支,那麼就必須指定版本號才能夠。merge
操做,而後進行微調,該操做須要進行估時,歸入排期。流程以下圖所示:
綜合分析後,咱們總體採用git
分支、局部採用環境變量的方式進行管理。
zg_pod_upload
:用於簡化pod
庫的發版流程,同時支持組件的本地校驗。zg_pod_initialize
:用於快速建立一個組件化工程,合併了pod lib create
的幾個命令,並在對應的class
文件下,建立對應的組件模板。zg_file_filter
:用於組件引入時的文件去重。zg_file_replace
:文件重命名腳本,用於批量的對業務組件的相關代碼從新命名。bundleID
,那麼須要爲對應的bundleID
申請對應的三方庫配置ID和Key
。Mediator
方案自己就支持帶參數、不帶參數、帶返回值、無返回值、帶block
回調、不帶block
回調的調用。具體可閱讀casa
的系列文章。UI
複用、Model
複用、數據與服務複用
。UI
和Model
的複用,若是就是想複用,能夠把對應的UI
和Model
下沉到Base
層以後再複用。Base
層,以避免打散後續開發的連貫性。target
問題?baseModule
裏,統一管理,將target
的邏輯也寫在baseModule
裏Mediator
進行調用,後續再進行不斷地拆分CommonModuleExports
中,組件B的target
依然放到主工程中,在A中以Mediator
的方式引用B組件,後續再對B組件進行拆分標準老是要有的,有了標準,纔會有前進的方向。然而目前關於如何評價一個業務組件的好壞,尚未統一的標準。咱們在實踐中試着總結了幾條,供你們交流參考。
組件化是一個漫長、繁瑣、複雜但有意義的過程,是一項團隊性的工做,建議你們在過程中增強團隊成員之間的溝通,遇到問題及時解決,及時調整,定好方向後就只管大膽地往前走。同時也歡迎你們與咱們溝通交流,但願咱們的分享可以在實踐中幫到你們!預祝你們新年快樂~