純個人學習筆記分享, 不喜勿噴,自行取關! 技術不缺乏締造者,網路不缺乏鍵盤俠,但缺乏分享技術的源動力!
近幾年元件化大家吵的沸沸揚揚的,它其實也不是什麼黃金聖衣,穿上立馬讓你的小宇宙提升幾個檔次,也不是海皇的三叉戟,入手就能呼風喚雨,它不過就是一種app的架構思路。其實真的很簡單,如果你的專案從釋出之初就是用元件化,那麼在開發的過程當中勢必會少很多麻煩,難點其實是對我們龐大古老的工程進行元件化的改造。
一.下面我們來談談元件化到底是什麼
其實元件化說白了就是將一個單一的工程分解為各個獨立的元件,然後按照某種方式任意組織成為一個擁有完整業務邏輯的工程。
舉個例子大家就明白了,一輛完整的汽車從來都不是由一個工廠將所有的零部件生產完成的,而是輪胎廠生產輪胎,發動機廠生產發動機,玻璃廠生產玻璃等等,然後再組裝成為一輛完整的汽車。我們的各個元件或者說模組就是汽車的各個零部件,我們的整個工程我們也把它叫做宿主工程就是我們的汽車,我們按照一定的規則把他們拼裝起來就是一個業務邏輯完整的工程。
二.元件化產生的原因
那麼元件化為何應運而生,其實在我們的開發過程中,如果本身專案的規模不大,業務線比較少,人員也比較少,我們使用一般的單一開發模式就好了。但是隨著我們的專案不斷的迭代更新,業務線越來越多,發開人員也元件增多,這個時候就會暴露各種各樣的問題
-
耦合性嚴重
-
編譯速度慢
-
測試不獨立
-
無法使用自己擅長的設計模式 ......
-
耦合性嚴重 關於耦合性嚴重這點舉個大家深有體會的例子,我們對接手二手甚至N手專案的時候都是深惡痛絕的,因為我們不知道以前的開發人員的思路和架構,這個時候我們往往面臨著三類問題 1.程式碼的重構 2.增加新功能 3.改bug 就拿我們改bug來說,我們由於不瞭解人家的思路,我們把面前的bug改掉了,結果我們出了更多得bug,越改越多,頭疼至極,因為我們可能將眼前bug改掉的同時,其他同樣依賴改動地方的程式碼卻不適用了,這就非常尷尬了。 同樣地對我們的新功能開發和程式碼重構也是如此,我們好不容易將自己的功能模組搞定的時候,由於對老模組有依賴,一旦老模組中存在某些bug,會導致我們整個工程都跑不起來,我們不但測試不了自己新寫的功能模組,而且我們可能連bug在哪都不是一時半會兒就找到的,再加上解決的時間我們將耗費大量的時間和精力,大大降低了我們的發開效率。
-
編譯速度慢 隨著工程的業務線越來越多,發開人員不斷增加,我們的專案越來越龐大,往往專案編譯少則一兩分鐘多則幾分鐘,雖然並不影響我們的開發工作,但是我們使用元件化的開發配合二進位制化,我們完全可以提高整個專案的編譯時間。
-
測試不獨立
從這張圖我們能看到我們在發開完畢我們自己的模組之後,我們需要對自己的模組進行測試,但是主工程裡面的其他模組存在一個bug,導致我們的工程編譯不了,那麼我們開發的模組勢必也是測試不了的,真的很尷尬。
- 無法使用自己擅長的設計模式 這個我們稍微說一下大家應該能明白,如果你的公司主要是使用MVVM的架構模式進行開發的,而你只會使用MVC進行開發,是不是很尷尬,當然我們可以按照MVC去套用MVVM進行開發,但是我給大家畫一張圖大家就明白了
假設說我們的設計模式按照模組劃分的話,我們沒法使用MVC去套用我們的MVVM,這樣我們除了去學習MVVM之外別無他法,可關鍵是你真的有足夠的時間在短時間內上手嗎? 當然如果我們按照功能模組來劃分的話,我們的MVC倒是可以套用我們的MVVM,但是你能保證不出問題嗎?
三.元件化的優勢
那麼我們使用元件化之後到底能達到什麼樣的效果呢?
- 元件的獨立 我們終於可以獨立編寫我們的模組,獨立編譯而不用漫長的等待主工程長達數分鐘的編譯,我們再也不用擔心因為各種非自己功能模組中的bug讓我們寸步難行無法單獨測試了。
- 資源的重用 我們專案中各種分類,巨集定義,基礎配置這些基礎的程式碼,以及我們的輪播器,選項卡等等這些功能性的自定義UI元件再也不用重複的拖取或者重寫,我們只需要以pod庫的形式直接匯入到工程中就OK啦。
- 高效的迭代 當我們需要增加或者刪除某些模組,我們只需要將對應的路徑刪除掉,就可以一次性將整個模組增加或者移除又不會影響宿主工程的正常執行,十分高效。 ※配合二進位制,可大大提高專案的編譯速度 我們把業務性、功能性、基礎性的模組拆分成元件以後,可以採用靜態庫打包,framework庫的形式二進位制化元件,這樣將大大提高我們的編譯速度。
四.元件化應該考慮的問題
- 元件的劃分 我們一般將元件劃分為三類 基礎元件: 包含基本配置(常量,巨集)、分類(各種系統類的擴充套件)、網路(AFN、SDWebImage封裝)、工具(日期時間處理、檔案處理、裝置資訊等)
功能元件: 包含控制元件(彈幕、輪播器、選項選單、圖文選單等)、功能(斷點續傳、音訊處理等)
業務元件: 業務線一(子業務線一,子業務線二.....) 業務線二(子業務線一,子業務線二.....)
- 元件層級之間的關係
從這張圖我們可以看出來,我們三大元件類,其實是有層級關係的,我們的業務元件既要使用我們的基礎元件也要使用我們的功能元件,它屬於我們基礎元件和功能元件的上一層,而我們的基礎元件和功能元件屬於同一層級,他們之間是不能互相產生依賴關係的。
如果說我們的功能元件的彈幕需要使用到基礎元件中的有關佈局View的分類,我們這個時候最好的做法並不是將讓我們的功能元件依賴於我們的基礎元件,這樣的話別人要使用我們的彈幕卻要將我們整個基礎元件都下載下來,那麼我們的元件化就失去了原有的意義。我們在這裡推薦的做法是講我們所需要的那塊程式碼直接拷貝到我們的功能元件當中去,這樣做的好處在於我們的功能元件不需要依賴我們的基礎元件。
同樣在我們三大元件類的內部,元件之間也不能產生依賴關係,好比我們的彈幕不能依賴於我們的播放器,總不能別人要使用我們的彈幕還得把播放器給下載下來把,這樣也是不合理的,對我們業務元件也是一樣的,我們要增加或者刪除某個業務線,結果導致其他的業務線沒法正常的使用了,這都是不可取的。
但是某些時候我們確實需要使用其他元件裡面的內容,但是他們之間又不能產生依賴關係,這個時候我們就要使用到元件間的通訊,這個在後面會講到元件間如何通訊。
-
元件的存在形式 元件內部:根據設計模式劃分資料夾結構 元件形式(對外):每個元件都是以pod庫的形式存在 元件測試:單獨的測試工程(這裡我們可以通過建立pod模板庫形式,直接擁有測試工程)
-
我們是以Cocoapods的形式安裝各個元件的
這張圖我們可以看到,我們的業務元件是可以依賴我們的基礎元件和我們的功能元件的,而我們的業務元件都是以pod庫的形式藉助我們Cocoapod安裝到我們宿主工程中去,我們的宿主工程面向的都是我們的業務元件。
- 元件間的通訊 上面提到了我們同層次間的元件或者是我們三大元件內部的元件之間是不能有依賴關係的,但是確實有些時候我們一個元件內部發生了一些事件想要告訴其他元件,或者需要呼叫某些元件的服務,這個時候我們就需要用到元件之間的通訊。 這裡我們來講講其中的一種方式--中介軟體,我們用一張示意圖來描述一下
在這裡我們看到我們元件都是通過中介軟體來進行互動的,元件將內部發生的變化告訴給中介軟體,中介軟體在通知其他元件。我們元件把各自的服務給中介軟體,需要對應服務的元件就會去找中介軟體拿,這樣的話我們元件之間不會產生依賴關係,同時又能進行通訊。
五.分離元件的難點--解耦
一般在元件化的分離各個元件的時候,解耦這個話題我們是迴避不了的,但是其實我們一般會遇到兩種情況 1.元件裡面依賴其他公共功能 2.元件內部需要對接某個服務
元件裡面依賴其他公共功能 對於這種情況,我們一般最快的方式就是直接copy程式碼,雖然這個過程比較噁心,但是好處就是不會有額外的依賴,對於一些不重要的工具方法,我們都可以拷貝到內部來使用。
舉個例子大家都明白了,我們使用獲取螢幕尺寸的方法,而這個方法我們一般寫成巨集定義放在我們的基礎元件中,我們的業務元件中要用到這個方法沒這個時候我們沒必要把我們基礎元件也整個下載下來,我們直接複製貼上這短程式碼就好了。
我們也可以把元件依賴的程式碼先做成一個pod庫,然後依賴這個pod庫就好了,這樣我們的問題就迎刃而解了。
元件內部需要對接某個服務
比如我們控制元件的內部涉及到載入網路圖片,我們一般會用到我們的SDWebImage的框架,雖然我們可以在使用遠端私有索引庫的時候新增依賴,那麼我們在下載我們的私有庫裡面元件的時候我們可以將SDWebImage一併整合到我們的宿主工程中。如果開發過程中,公司用得不是SDWebImage不是會很尷尬嗎?
所以我們使用的方式就是使用block或者代理把這部分職責丟出去,那麼我們就可以自用的選擇我們所需要使用的第三方框架或者公司內部寫的框架,不用再糾結了
關注微信公眾號:iOSSir,每日更新蘋果資訊、技術乾貨!
掃一掃關注微信公眾號喲!也可加入iOS技術交流群:551346706 獲取大廠面試最新相關資訊和技術進階相關資料!