前言
上一篇中我們對組件化是什么和常用的組件化中間件方案做了簡單的介紹,這篇文章則是用來說明開始進行組件化時需要做哪些準備工作,希望本文能給你帶來幫助。
一、概述
在實施組件化之前,我們需要進行一些準備才能保證接下來的工作順利愉快的進行。首先便是需要對目前的項目結構做分層設計,因為在實施組件化時,層
的概念很重要。那什么是層?又如何分層呢?
首先我們來理解層的概念。以常見的MVC架構為例,一般都是Controller持有View和Model,然后Controller根據需求更新Model并將Model轉為對應的View可用數據,通過View的數據源及代理方法刷新View。這種關系形如下圖:
而項目中的文件結構大概如下:
當項目的功能模塊累加到一定程度時,我們會發現MVC的三個文件夾中內容越來越多,查找起來十分麻煩,因此我們可能會對項目結構做如下優化:
- 對MVC這三個文件夾做拆分,里面分為各個模塊:
- 根據模塊拆分項目,每個模塊內部分為MVC:
拆分到這里時,有時候就會發現項目中會出現一些不知道歸屬于哪個模塊,或者公用的代碼,這時候很多人會選擇建立一個Common
文件夾,用于存放這些零散的代碼:
時間長了,Common內的代碼越來越多,直到某一天發現難以維護了,于是將Common內的提供基礎功能的模塊封裝成二方庫
,通過靜態庫或者直接用CocoaPods
這種依賴管理工具集成:
此時,作為基礎庫的MyNetworking
為A
,B
這種業務模塊提供了基礎功能的支持,這樣就天然形成了層次關系。總結一下,層就是特定功能的代碼集合
。一般來說,設計的比較優秀的分層架構,都會保持上層對下層的單項依賴,例如我們用的平時用的AFNetworking
就是如此:AFHTTPSession
依賴于AFURLSession
,AFURLSession
依賴于NSURLSession
,NSURLSession
依賴于CFNetwork
,這些依賴都是單向的,因此邏輯非常清晰。
同樣,分層的設計也得考慮到這些,例如我們將一個APP分為展示層
、業務層
、數據層
、持久層
這四層,也應當保持單向依賴。這樣可以最大限度的避免復雜的耦合,減少組件化時的困難。
二、如何進行分層
這里以我們公司的項目舉例,目前我們公司重構的項目結構大概如下所示:
這里的分層是根據代碼的依賴關系分層的,基礎庫
應當做到互相獨立,除了依賴于系統框架和一些非常主流的三方框架外,不對其他代碼做任何依賴,每個庫都可以獨立通過單元測試。
對于業務庫的拆分,關鍵點就在于,業務庫雖然包含一定對業務邏輯,但是其中的業務邏輯應當是較大范圍內都通用的業務邏輯,比如三方登陸、分享、支付庫的調用業務。也就是說這一塊的庫應當是可以在同公司多個app中通用的,當然如果你們公司只有一個app,那么可以選擇將這部分于業務組件相結合,但是誰又能保證一個公司永遠只做一個app呢。
而業務組件
則是對業務模塊的封裝,所謂的組件化顆粒度
一般指的就是這一層的封裝顆粒度,理論上顆粒度做到每個頁面是最理想的情況,但實際情況總是千變萬化的,某些頁面的耦合度可能會非常高,拆分的代價太大,得不償失。那么我們完全可以將顆粒度稍微放粗一些,將有緊密業務聯系的頁面組成一個組件,然后暴露使用這個組件的接口即可。
分層的方式有很多,但是做組件化的前提便是將業務部分獨立出來,基礎庫也獨立出來。這兩層不獨立,便無法繼續下去。另外,組件化完成之后,每個組件都可以交由不同的小組分別開發,每個組件也都可以使用不同的設計模式(MVC、MVP、MVVM等),而不會污染其他組件結構。
三、基礎層如何構建
一般來說,常用的網絡請求、數據庫操作、網絡診斷、hotfix等基礎功能都是歸屬于基礎庫,如果有針對于業務特性的定制模塊,應當將其二次封裝擴展作為業務庫?;A庫中一定要避免混入業務邏輯,也就是我之前一直強調的避免雙向依賴。
我們的做法是先將原有與業務功能混合在一起的基礎模塊獨立出來,如網絡庫、中間件、常用語法擴展、數據庫管理等,同時通過對于業務需求相關的地方,提供出protocol供于定制,具體實現可以參考我們的開源代碼:HLNetworking、Lothar。
四、業務組件和業務庫的搭建
(聲明,這段內容很大程度上參考了casatwy大神的這篇博文《在現有工程中實施基于CTMediator的組件化方案》,非常感謝!)
與基礎層類似,為了便于管理,業務組件和業務庫同樣使用CocoaPods做依賴管理。
CocoaPods自身支持git和svn,但是私有源好像是不支持svn的。因此最好還是先弄一個私有git環境,在國內使用coding、oschina這種托管網站,或者自己在公司內網搭建一個gitlab、gogs這樣的服務。環境搭建好之后根據以下步驟建立私有源倉庫,這里我以github上的這個組織作為例子:
首先創建一個空倉庫,我們就起名為
PodSpec
。然后將該倉庫添加到本地pod repo中:
pod repo add myspec https://github.com/ModularizationDemo/PodSpec.git
,其中myspec
為你區分不同的podspec源的名字,而https://github.com/ModularizationDemo/PodSpec.git
則是對應的repo地址。-
創建一個文件夾并起個名字,這里我們就起名為
ModularizationDemo
,然后從git@github.com:ModularizationDemo/config.git
clone一份配置文件到ModularizationDemo
文件夾內,并將舊項目復制一份到ModularizationDemo
文件夾內、重命名為OldProject
,如圖所示(這里的項目我以dsxNiubility的SXNews作為demo):
創建項目文件夾.png
到此為止,準備工作已經完成,你應該已經有了對應的基礎庫,以及準備好的舊項目和config,我們在下一篇將以SXNews為例,詳細說明如何實施組件化。