1. 程式人生 > >宜人貸-iOS客戶端元件化介紹

宜人貸-iOS客戶端元件化介紹

文章簡介:

本文將從三個方面講解我們元件化專案。第一部分,我們將介紹元件化的意義和業內元件化的程序;第二方面我們將具體介紹元件化所使用的技術,以及元件化過程中所面對的問題;而第三方面,我們會展示我們元件化的相關成果。

第一部分:元件化意義及業內現狀

隨著公司的發展壯大,開發的業務線越來越多,我們的開發團隊人數將會隨之增長。在這種情況下,我們原始的開發架構將無法滿足我們的業務需求,將不斷的暴露出問題。

就拿淘寶來說,淘寶在13年開啟的“All in 無線”戰略中,就將阿里系大多數業務都加入到手機淘寶中,使客戶端出現了業務的爆發。在這種情況下,單工程架構則已經遠遠不能滿足現有業務需求了。所以在這種情況下,淘寶在13年開啟了外掛化架構的重構,後來在14年迎來了手機淘寶有史以來最大規模的重構,將其徹底重構為元件化架構。

舉個簡單的例子:

當小王一個人開發時,隨心所欲,程式碼本地管理都是可以滿足開發的。但是隨著公司業務、功能不斷增加,小李、小張等都陸續加入了團隊,為了協作開發,則需要code management、code review、code merge、code standards等等這些輔助的開發工具和規則。但是隨著公司繼續壯大,code提交數量急劇增大、業務劃分越來越獨立,review、merge等工作靠一個人已不堪重負,不同業務的程式碼暴露在整個開發組成員下,程式碼安全也同樣經受著考驗,小王剛寫完程式碼,發現已經有20+個提交,剛解決完衝突想要提交,發現又有10+個提交,想死的心都有了,在這種心情下,只想快點解決衝突、快點提交,code merge的問題率也就跟著上升。而打包、測試、UI資源、需求等也有同樣的問題,這裡就不再贅述了。

那麼怎麼解決這些問題呢?演算法裡有一種思想,分而治之,可以很好地概括元件化的思想,既然我們太龐大了,那麼我們分為各個小的元件,如果還大,我們繼續顆粒化,最終達成一個舒適的開發組大小。彼此之前通過標準的方式互相交流,協作開發;當組成app的時候,通過標準的方式引入,在自己開發一個元件時,根本不用考慮其他的10個還是100個元件,只需要對自己開發的元件負責即可。
結構轉換
業內元件化開發模式其實比較早就建立了,但是在早期探路階段,由於技術上的不完備,沒有前車之鑑,採取的方式多少有些繞彎路。

隨著包管理、路由等技術的實現和深化,以蘑菇街的元件化為經典案例,像是阻塞的通路一下開啟,各大廠汲取經驗紛紛完成了比較穩定的元件化實現,如滴滴的TheOne專案,手淘的Atlas專案,微信小程式的WePY等都有異曲同工之妙。

第二部分:元件化所涉及的技術以及難點

前面也說了,之所以可以實現比較完美的元件化,是因為一些工具、技術得以實現,其中比較重要的技術點如:pod庫管理工具、路由router、runtime的元件間呼叫、生命週期分發等。

1、pod庫管理工具:

對於pod來說,他解決了我們元件的空間隔離和引入組裝問題。
我們實際上是需要它兩方面的知識:

  • 怎麼使用庫
  • 怎麼建立庫

會使用PPT做炫酷的展示和開發一個有這些功能的PPT程式是完全不同的東西,所以官網也給了兩套document。

介紹pod完全可以花3個篇章來寫,即怎麼使用庫、怎麼建立庫、怎麼使用建立的私有庫,這裡直接有我寫好的分享文章,歡迎檢視,而這裡由於篇幅問題,就不詳細說了:

2、路由

路由是元件化的中介軟體技術,他解決了我們元件化的耦合問題,它的存在使我們空間隔離元件成為可能。
舉個栗子:

當我們想跳轉一個A頁面的時候,通常來講我們需要import A頁面的標頭檔案,在寫相應的跳轉方法,但是這樣,我們就耦合了A檔案,也就無法與之獨立,如果A頁面是其他業務的檔案,那麼我們將與其他業務耦合,這樣千絲萬縷的聯絡,使我們整個工程根本無法獨立拆分。

而路由的出現,幫助我們斬斷最後一絲亂麻。

  • 傳統路由方式JLRouter:
    JLRouter是比較穩妥的路由方案,他通過url對映block的方式,將行為和url進行連線,大多數的元件化工程都是基於這種路由方案進行的重構。這種方案簡單易懂,但是要維護一個全域性的url list,並且作為url的引數只能是簡單型別,但是這些問題並不影響他發揮的作用。
    這裡就有很好的介紹文章:

  • iOS OC特性runtime-CTMediator:
    在元件化之初,個人是十分喜歡使用新技術的,所以在技術選型時,我並沒有採用傳統的url Router方案,而是使用了一種新的Target-Action,完全解耦的,且可以傳複雜引數的runtime方案-CTMediator,該方案是iOS OC語言的特性,充分利用了該語言最大的runtime特性,在執行期間確定呼叫的物件,完全解耦合,不需要任何list檔案就能做到呼叫。

元件化技術選型的思考文章:

首先我們將各業務對外的介面封裝成獨立的庫
這裡寫圖片描述
而在介面中,我們都通過字典的方式進行傳參,保證資料型別的多樣性;另外我們直接在.h檔案中採用markdown語法編寫介面文件。
這裡寫圖片描述
為什麼用這種方式呢?我們考慮到文件和檔案分離容易造成更新不一致的情況,我們希望儘量減輕開發人員的工作數量,而不是維護多個檔案。通常,開發人員直接閱讀.h檔案即可,但當我們想生成文件的時候,我們只需要將內容拷貝到任意的markdown瀏覽器,即可以生成一份正式文件:
這裡寫圖片描述

當我們對外介面編寫完畢,我們只需要將這些介面以runtime的方式,連線到對應的方法上面,編譯器認可這種執行時的處理方式,不會報錯,這時,我們的介面和介面實現就解耦合了,而我們的呼叫方與實現方也基於此而拆分成功。
介面實現:
這裡寫圖片描述
具體runtime的實現程式碼:
這裡寫圖片描述
這短短的數十行核心程式碼,使得我們的方法呼叫通過runtime而解耦合。

3、生命週期分發

將單一工程分成多個獨立工程,每個獨立工程都有自己的生命週期,則生命週期也存在多個,但是合成一個app時,應僅有一份生命週期。
這個問題也同樣包含生命週期檔案AppDelegate的還原,在iOS單工程中,我們的初始化工作一般都是放在AppDelegate的啟動生命週期didFinishLaunch中,隨著開發的進展,這個函式裡面的東西會變得非常龐大
這裡寫圖片描述
這些東西絕大多數並不是業務獨立工程所關注的,但是這些程式碼與啟動app息息相關,有些部分例如頁面結構,各業務開發時,還是希望存在的,那麼怎麼做到生命週期僅有一份的情況下,各個獨立工程又能共享呢?

我們這裡使用了register and dispatch的技術方案,採用register的理由主要是某些業務可能並不需要對生命週期有所操作,那麼不管三七二十一一股腦的分發很不合理,加重app負擔,所以,有需求則註冊,我們只對註冊的業務進行生命週期分發,並且根據註冊的順序進行排程,防止生命週期混亂。

目前我們僅註冊了平臺模組:
這裡寫圖片描述
這裡我們也採用swift的方式重寫AppDelegate,以達到提升啟動速度的目的。
這裡寫圖片描述
我們的獨立工程只需要copy AppDelegate和plist檔案即可,而我們的AppDelegate相信未來也不會有變化,一勞永逸的解決生命週期問題,將處理方式下發給各個子工程。

第三部分:介紹我們元件化的成果

1、1個基礎元件庫、1個公共業務庫、1個DPL視覺庫、4個業務庫、4個業務介面庫、1個主工程
這裡寫圖片描述
我們從一個git庫,分割成12個庫,從許可權劃分、程式碼安全、程式碼合併、開發流程都有了相應的脫變。
2、runtime元件呼叫中介軟體,包含url remote呼叫方式,保證未來需求
這裡寫圖片描述
我們不僅解決我們本地的呼叫解耦,還為遠端呼叫留下了口子,為未來需求準好準備。
3、life circle下發式管理,主工程生命週期減負,子工程肩負更多責任。
4、獨立的jenkins的測試方案,每個子工程不必在等待其他業務完成,測試點完全看自己需要。
這裡寫圖片描述
5、獨立的code許可權管理,分group管理許可權,不再擔心非業務線的開發人員改動自己的程式碼,提升程式碼安全。
6、開發人員的分化更加細緻,不同級別開發人員肩負不同的責任,不再有許可權集中的問題。
7、流水線式開發,組裝過程中僅關心成品的元件,不關心具體過程。
這裡寫圖片描述
8、全部以版本號來控制程式碼,不再跟具體程式碼打交道。
這裡寫圖片描述
而我們的主工程從1300+的檔案變為僅存在不足10個檔案的殼工程,完全以組裝的方式完成App。

展望:

元件化工作任重而道遠,後續優化工作也很繁雜,例如資源優化,編譯速度優化,安全等,這些工作不做也僅僅是比較麻煩而已,但是解決問題不斷進步是技術的永恆追求,希望我們能夠將剩下的問題逐步解決優化。

元件化對公司發展至關重要,是一件現在可做可不做,但是如果不做,數年後回首會後悔的戰略級專案,很高興我們最終完成了目標,幫助公司在未來業務發展上減少了技術障礙。

相關文章及引用: