談?wù)劷M件化的歷程

組件化是一個不可避免的階段,個人認為也是一個越早越好的階段。特別在一個公司內(nèi)的產(chǎn)品越來越多的時候,顯得尤為重要。

什么是組件化


組件化的字面意思,是代碼上可復(fù)用的結(jié)果,而實際上組件化遠不止這個層面。

在沒有組件化的時候,每個項目都是各做各的事情,包括一個組內(nèi)也是存在重復(fù)造輪子的行為,等到需要抽離獨立模塊的時候,又發(fā)現(xiàn)耦合過大,花費大量人力來解耦或者重構(gòu),甚至不了了之。

新項目的快速成型

立項 ---> 確定需求 ---> 搭建主工程框架 ---> 引入需要的組件 ---> 補充沒有的組件 ---> 成品

在一定的積累下,一個公司內(nèi)部的新產(chǎn)品開發(fā),都可以快速的搭建起一個擁有公司基礎(chǔ)業(yè)務(wù)組件的框架,專心做差異的業(yè)務(wù)開發(fā),而無須重新花費力氣重新開發(fā)這些基礎(chǔ)功能,例如一些性能監(jiān)控,數(shù)據(jù)上報,測試框架等。

研發(fā)思維于流程的質(zhì)變

組件化并不局限于基礎(chǔ)底層的東西,業(yè)務(wù)邏輯,界面封裝都可以成為一個組件,例如通用下發(fā)配置,相機相冊界面等,都可以成為大組件化的一個積累過程。

在這樣的環(huán)境下,研發(fā)的開發(fā)流程會變成下面這樣

獲得需求 ---> 前期分析和設(shè)計 ---> Coding ---> 組件化(如果可以) ---> 完成開發(fā)

區(qū)別在于,在組件化的大環(huán)境下,大家在開發(fā)前期,會思考這個需求是否可以成為一個通用方案,而進行一些前期的分析和設(shè)計,可以的話,就會從中找到可以組件化的部分,成為一個獨立模塊。即使不能組件化,也會對于后續(xù)這個模塊的低耦合方面有所貢獻,引導(dǎo)大家面向接口編程,保持下層穩(wěn)定性。

潛在的激勵

每個研發(fā)都希望自己的代碼得到認可,組件化可以潛在的推動這個事情。從組內(nèi)組件化,到跨項目通用,到公司內(nèi)公用,最后發(fā)展成對外開源,是一個不斷鼓勵代碼優(yōu)化和維護的過程。

探索之路


早期的開發(fā)可能都會經(jīng)歷過這么幾個階段,現(xiàn)在或許直接就到了最后的形態(tài),再往后就在于是否堅持了。

以下列出了幾種我經(jīng)歷過的工程形態(tài),有些或許現(xiàn)在還是這樣,我們可以順著理一下,這里都是基于iOS的開發(fā)來討論。

一個工程走天下

在早期,或者現(xiàn)在還有些項目,一個app只有一個主程序,所有代碼按照文件夾來劃分,實際上都在一個target上,很多開發(fā)會覺得很方便啊,這樣有什么不好呢?

  • 容易造成import泛濫
    • import沒有顯示來源,不利于代碼理解和解耦
    • 沒有一個很好的尋找特定代碼的方向,容易重復(fù)造輪子
      • 文件夾劃分太弱,不利于大家規(guī)劃同類的東西在一起,甚至一些通用的基礎(chǔ)方法直接寫在業(yè)務(wù)代碼里
      • 比如系統(tǒng)的Foundation,如果我找一個字符串操作相關(guān),我一下子就知道該去這里找了
    • 后期要解耦或者抽離的時候,工作量很大,如果還有交叉循環(huán)依賴,就更痛苦了
  • 代碼沒有得到隔離
    • 太容易觸碰到的東西,很容易誘發(fā)不能用就改實現(xiàn)的行為
    • 或者完全基于實現(xiàn)來使用接口,沒有達到一個面向接口編程的目的
    • owner也沒有動力完善接口,基于實現(xiàn)告訴使用者怎么用
  • 跨項目復(fù)雜度高
    • 代碼復(fù)用全靠copy
    • 修改bug容易另外一個項目忘記修改
    • 如果實現(xiàn)得太業(yè)務(wù)化,另外一邊也用不起來

當然也不能一棍子打死所有案例,有些app就是簡單,沒必要那么復(fù)雜化,但是怎么也會有一些自定義的基礎(chǔ)類封裝吧,統(tǒng)一管理出來是個好習(xí)慣,說不定那天會感激自己的多此一舉

至于公司級別的app,基本上就不會簡單到那個地步了,至少我個人是這么覺得的。

多工程模式

多工程模式下,一般有點規(guī)模的一個功能,都會獨立成一個工程,放在主工程下,成為一個子工程,主工程依賴這個target即可。

多工程和多文件夾的最大區(qū)別在于

  • 工程可以有不一樣的配置,文件夾只是很弱的視覺劃分
  • 工程有明確的一個獨立的姿態(tài)
    • 工程一般會有一個Dependency的文件夾,把依賴的文件,庫,子工程放這里,一目了然
    • 哪天需要復(fù)用,我很快了解這些依賴有什么,解決這些依賴就可以了,文件夾的話,你需要看完每個文件的.h.m,才能匯總起來一共依賴了些什么
    • 方便整個功能移植到其他app,或者在demo上測試開發(fā),不影響主項目的流程

這里的好處是沒有異議的,但是怎么很好地解決依賴問題是一個探索的過程

0x1 拖拽文件

從早期我們遇到一個子工程,需要一來到另外一個子工程的文件的時候,第一想到的辦法就是把那些文件的.h拖到這個工程來,然后發(fā)現(xiàn)這個.h又依賴了另外的.h,直到把所有頭文件都拖進來了,總算完事了。

但是突然有一個文件上的改動,這個行為可能要重新做一次,這就很恐怖了。

0x2 子工程化依賴

既然我們已經(jīng)用工程化的行為來模塊化了每個業(yè)務(wù)或者說每個功能集,為什么不還局限于對某個文件的依賴呢?

你依賴一個業(yè)務(wù)里面的文件,很大概率你就會用到這個業(yè)務(wù)里的其他文件,既然這樣,我們就把文件級別的依賴升華到工程級別的依賴。

也就意味著我們不再一個文件一個文件的拖,而是整個子工程拖到自己的工程下面,那么這個工程就可以訪問整個子工程的公開文件了,何樂而不為呢?

0x3 統(tǒng)一工程化依賴

但是我們發(fā)現(xiàn),依然沒有完全解決這個問題,想象一下,如果某個工程被其他很多工程都依賴了,而這個工程位置變了,一個基礎(chǔ)模塊工程,一下子需要放到很多很多工程下,這個操作也是很難受的。

我們想了一下,創(chuàng)建了一個Bridge工程,所有工程都依賴Bridge工程,同時所有工程都是Bridge工程下的子工程。

乍看之下好像有點死循環(huán),其實不然。

  • Bridge工程的編譯并沒有依賴它的子工程的運行,而是依賴子工程下的腳本,但是子工程依賴Bridge工程的編譯
  • Bridge工程的編譯會引發(fā)每個子工程腳本,生成自己的頭文件路徑,從而給到使用者
  • 主程序同樣不依賴Bridge工程,還是按順序依賴其他真是子工程的編譯

這種情況下,為了方便大家,還創(chuàng)建了一個工程模板,統(tǒng)一標準創(chuàng)建,且附帶好所有腳本,唯一需要做的,就是把自己拖進Bridge工程的依賴當中。

0x4 腳本時代

說到底,Bridge工程 開始還是需要人為拖動,且不利于新人理解

我們回歸到最原始最本質(zhì)的問題上:可以使用目標.h文件

清晰了這么一點就好辦了

  • 每個工程只需要搭配一個配置文件,聲稱我這里哪些文件是Public的,這樣就可以了
  • 然后我們寫一個腳本,遍歷工程文件夾下所有配置文件,在對應(yīng)的目錄生成這些Public Headersoft-link,這樣每個子工程都有自己的一個Public Headers的目錄
  • 使用者引用對應(yīng)的路徑即可

(可能很多人覺得這只是一個framework的事情,但是那時候還沒有framework,而且目前一些老項目說不定還在支持iOS7)

腳本能帶來的好處是很大的,除了方便了很多以外,甚至可以做到任何交叉循環(huán)依賴,在每個子工程上可以說用的風(fēng)生水起了。

但是埋下的問題也是很可怕的

  • 首先是這套方案是內(nèi)部使用的,并不能推廣出去,連跨組推廣都有一定的復(fù)雜度,更別說公司外了
  • 然后這套方便的方案,在設(shè)計模式層面上,可以說破壞的很厲害了,會削弱研發(fā)的設(shè)計思維
  • 使用過程沒有規(guī)范化,新人有一定的學(xué)習(xí)和理解成本

Workspace模式

0x5 Pod的到來

Pod的規(guī)范化可以說帶來了一個最終的項目工程形態(tài)(當然也有些公司有自己更好的一套方案),主要得益于:

  • 業(yè)內(nèi)的一個通用標準和規(guī)范,降低相互之間的一個學(xué)習(xí)成本
  • 更深一層的代碼隔離,更好的代碼引入方式,更豐富的配置
  • 對私對公的repo機制,插件可自定制化,更少的人為配置依賴操作
  • 不同分支倉庫的組件差異化

對于Pod的模式和使用上,這里就沒必要多說了,可以到Cocoapods的官網(wǎng)了解詳細的內(nèi)容,也可以Google一些插件定制化的東西來滿足特定的需求。


這里先回答一個疑問,Pod畢竟也不是很晚期的東西了,為什么早期或者中期不直接開始引入這個模式呢?

一個客觀原因是,在當時Pod剛起步,或者說還沒有到現(xiàn)在這么普及,我們還在觀望和不熟悉的階段,的確是有點躊躇,通俗點說,對于陌生的東西,就是有點慫。

另外一個是歷史原因,我們雖然看到前面幾個階段有很多不規(guī)范不成熟的地方,但是它們在當時的確是一個相對較佳的方案,我們來分析一下為什么:

  • 這些舊方式都沒有任何難度,想到一個優(yōu)化點就可以馬上動手,對原來的代碼框架修改很少,可以說非常輕量化
  • 0x4模式雖然很大程度上破壞了設(shè)計模式層面,但是不得不說在中國互聯(lián)網(wǎng)公司快速開發(fā)迭代的節(jié)奏下,還是獲得很多人的青睞,畢竟項目的發(fā)版壓力還是有的
  • 歷史代碼的解耦難度大,一下子需要抽離出來,不是一件容易的事情,另外大家對歷史 相對穩(wěn)定 的代碼,也是睜一只眼閉一只眼的態(tài)度

阻力是什么


從前面的分析看來,不難發(fā)現(xiàn),組件化的阻力從來不是技術(shù)上的,而是在于流程上的。

從技術(shù)層面上分析,組件化無非就是

  • 選定組件化的方式
    • Pod的方式對我來說已經(jīng)非常合適了,不行就加點定制化的東西進去
    • 如果牛逼一點的公司可以有自己更優(yōu)的方案,但是畢竟維護一整套東西也是個成本
  • 代碼解耦抽離
    • 從快速抽離的角度來看,解耦的做法,沒有什么是一個中間層解決不了的,如果有,就兩個
    • 復(fù)雜的模塊頂多多費點時間,缺乏人力的情況下,甚至可以大合集先包含進去,盡早先收攏再優(yōu)化
  • 后期維護
    • 只是一個繼續(xù)開發(fā)的過程而已

阻力從來都出現(xiàn)在流程上

組件化的推進,畢竟不是一個組的事情,也不能局限在一個部門上。在所有方案都確定好的時候,你發(fā)現(xiàn)需要跨團隊跨部門跨子公司來溝通的時候,才是真正的阻力。因為每個部門每個組的情況都不一樣,他們有著各自的項目壓力和技術(shù)方向,更有著不一樣的想法。

如何推進


推進的過程,我個人覺得是個藝術(shù)活,論外交手腕的重要性(會心一笑)

因為技術(shù)方案都確定好了之后,剩下的技術(shù)手段都是苦力活,真正花時間的可能都是交際手段

  • 推銷方案,并得到認同,保持步調(diào)一致
  • 確定前期目標,收攏的目標項目有哪些,整理出來的組件模塊有哪些,從而確定開刀的主客項目是誰
    • 主客是誰這個很關(guān)鍵,相當于確定公共模塊的標準是誰,用誰的代碼,以后誰來維護
  • 資源分配,也可以說是工作模式,最大的阻力環(huán)節(jié)
    • 各個組來各自安排,這樣會由于各自的項目壓力和人力,把周期拖得很長
    • 統(tǒng)一出人來幫忙各個組抽離組件,這樣涉及到權(quán)限的問題,流程上就有點周折
    • 另外還需要有人負責(zé)打通平臺對接,使得涉及的平臺支持新的方案
  • 效果檢驗,這個是最重要的環(huán)節(jié),不讓其他人看到效果,這個事情只會是一次徒勞的苦力活
    • 最容易看到的效果,就是拿新項目來試水,對比出成品的時間
    • 長期來看的話,就是內(nèi)部開源項目的數(shù)量,組件化的數(shù)量,甚至對外開源的項目情況
  • 持續(xù)維護,需求是源源不斷的,肯定需要有人持續(xù)跟進這個開發(fā)流程上的問題
    • 需要持續(xù)優(yōu)化過程中遇到的問題,需要高保證不出錯
    • 提升使用組件化的帶來的副作用而影響的效率

這個過程如果是從上往下推動的話,顯然比從下往上要容易得多。

最后


組件化顯然是一個不可避免的趨勢,如前面提到的,我個人認為是越早開始越好,對于開發(fā)人員的思維定性來說,一旦長期沒有這個概念,亂糟糟的代碼是不可避免的,也是會互相傳染而泛濫。

雖然很多產(chǎn)品現(xiàn)在都是不在乎實現(xiàn),但求無錯不崩潰的態(tài)度,顯示也不是一個可持續(xù)發(fā)展的做法,一定規(guī)模的公司更是要避免這種短期成品的行為。

也有一部分公司覺得需要的人力很大,在業(yè)務(wù)重壓之下沒有任何資源來做這件事情。我個人認為也是一個比較極端武斷的想法,組件化并不要求一次性到達一個完美的階段,它和業(yè)務(wù)一樣是一個重復(fù)迭代優(yōu)化的過程,在即使最糟糕的情況下,我也可以把所有明顯的獨立模塊大集合先抽離出來,不要求代碼有任何改動,只是單純的抽離,達到一個可用的階段即可,這樣就可以先讓全公司的項目,先用上同一份代碼,無論是資源的釋放,還是邏輯上的統(tǒng)一,都是一個非常好的開端,總之代碼的收攏越早越好。

一些公司也有自己的SDK組,這些其實是組件化的前身,如果能進一步去演進和統(tǒng)一操作,相信會得到更多的好處。

以上僅代表本人個人想法,歡迎吐槽和交流

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,326評論 25 708
  • 一位去年到了市區(qū)工作的老師告訴我,“這里是新天地”。 我被“新天地”三個字所吸引,產(chǎn)生了很多美好的期待。當我真...
    沉睡之光閱讀 350評論 0 0
  • “新媒體運營”!剛打開標題,就好像回到幾個月前一樣,這是我接觸運營最早的一個分支,也正是由于這個分支使我開始下決心...
    張大俠丶閱讀 268評論 0 0
  • 有很多正能量的理由,讓我選擇錢海。 第一,錢海簽合同,白紙黑字,具有法律效應(yīng)。 我們知道現(xiàn)在項目琳瑯滿目,挑花眼,...
    二姐秋梅學(xué)金融閱讀 315評論 0 0
  • Retrofit 配合 RxJava 的使用是越來越廣泛,小到個人項目,大到公司項目,都能看到它,它的使用也是挺簡...
    程序雜念閱讀 971評論 0 1

友情鏈接更多精彩內(nèi)容