天天看點

iOS開發-APP元件子產品化的了解子產品化的意義元件化方案

文章目錄

  • 子產品化的意義
    • 子產品化的粒度
    • 元件
  • 元件化方案
    • MGJRouter 的路由映射
    • CTMediator 中間者
      • Category的編寫

子產品化的意義

當項目大到一定程度,開發人員也多,所有的代碼都集中到一個倉庫,送出修改都要等其他人送出完成不報錯才能開始,非常麻煩。

再者就是代碼之間耦合嚴重,到處引用,穿插錯綜複雜,往往改變一個變量,需要修改很多處代碼,很容易出錯。

對于這種情況,就要進行架構整治,子產品化無疑是一個好的方案。

子產品化的粒度

對于子產品化,并不是一味的全部分離成子產品就是最好的。子產品之間或許會有必要的引用以及上下級依賴關系,沒必要完全的獨立。再者需要考慮到業務變化時,可能又要重新劃分子產品,工作量和成本又高了。

iOS 子產品化的劃分應該遵循 SOLID原則 ,如下幾點:

  • (S)單一原則

    :對象的功能要單一,不要是很多功能的集合體

例如

CALayer

負責動畫視圖顯示,

UIView

則負責事件傳遞,事件響應

  • (O)開閉原則

    :“開”,是指對于元件功能的擴充是開放的,是允許對其進行功能擴充的;開閉原則中“閉”,是指對于原有代碼的修改是封閉的,即不應該修改原有的代碼。
  • (L)裡氏替換原則

    :子類對象是可以替換基類對象的。所有引用基類的地方必須能透明地使用其子類的對象。

例如

KVO

的實作機制,利用

isa-swizzling

父類指向子類。

  • (I)接口隔離原則

    :接口的用途要單一,不要一個接口上根據入參不同實作不同的功能。

可以使用多個專門的協定,而不是使用一個龐大臃腫的協定。

  • (D)依賴反轉原則

    :方法應該依賴抽象,不要依賴執行個體。面向接口程式設計,不要面向實作程式設計。讓調用接口感覺不到内部是如何操作。

還一個

(D)迪米特法則

:如果兩個軟體實體無須直接通信,那麼就不應當發生直接的互相調用,可以通過第三方轉發該調用。其目的是降低類之間的耦合度,提高子產品的相對獨立性。即高聚合,低耦合。

可以順帶記憶

元件

可組裝,獨立的業務單元,高内聚,低耦合的特性。

iOS開發的元件,不應是

UI控件

,也不是

UIViewController

這種大UI和功能的集合,應該是包含

UI控件

,小功能集合的元件這樣劃分。

元件化方案

MGJRouter 的路由映射

https://github.com/meili/MGJRouter

蘑菇街的元件化方案

MGJRouter

[MGJRouter registerURLPattern:@"mgj://detail?id=:id" toHandler:^(NSDictionary *routerParameters) {
    NSNumber *id = routerParameters[@"id"];
    // create view controller with id
    // push view controller
}];
           

是一個路由方案

url-block

,通過注冊

url

block

到一個單例中的

字典routes

中。

當調用

就通過

Url

去從

字典routes

取其

block

來執行。這樣記憶體中維護了很多映射關系,

Url

這樣的使用方式,也比較繁瑣。而且需要将

Url

的時機必須要在調用之前,在

+load

進行注冊又拖長了App啟動時間,在其他時機注冊又需要統籌兼顧。

另外還有

protocol-class

url-controller

,這些方式都大同小異,需要維護一個映射表,是一個短闆,個人更傾向于

CTMediator

這種中間者架構

CTMediator 中間者

https://github.com/casatwy/CTMediator

其實就是使用

runtime

通過

[target performSelector:action withObject:params];

取到需要的資料,例如界面,視圖。

如何使用這些界面視圖就不關

CTMediator

的事了,這些界面,視圖就可以封裝成單獨的子產品,互無關系。

Category的編寫

CTMediator

的關鍵在于其分類的編寫,每個子產品功能的分類由其子產品開發者編寫。

- (UIViewController *)CTMediator_viewControllerForDetail
{
    UIViewController *viewController = [self performTarget:kCTMediatorTargetA
                                                    action:kCTMediatorActionNativeFetchDetailViewController
                                                    params:@{@"key":@"value"}
                                         shouldCacheTarget:NO
                                        ];
    if ([viewController isKindOfClass:[UIViewController class]]) {
        // view controller 傳遞出去之後,可以由外界選擇是push還是present
        return viewController;
    } else {
        // 這裡處理異常場景,具體如何處理取決于産品
        return [[UIViewController alloc] init];
    }
}
           

這是

demo

中分類的一個方法實作,

kCTMediatorTargetA

隸屬于

子產品A

kCTMediatorTargetA

中有一個

kCTMediatorActionNativeFetchDetailViewController

方法可以擷取一個

UIViewController`,

通過寫

CTMediator

對于子產品A的分類,就可以擷取子產品A中相關的界面以及UI,例如

CTMediator_viewControllerForDetail

iOS開發-APP元件子產品化的了解子產品化的意義元件化方案

這樣的優勢在于,沒有了

key-value

的映射關系,不需要維護

url映射表

,更不需要存儲block塊,

Category For A

由開發

子產品A

的人員來寫,他很熟悉

子產品A

(對于他來說将

子產品A

中某個界面取出,并設定相關參數是很簡單的事情),通過分類再轉給不熟悉的人(無需關心

子產品A

的内容)使用,就很友善了。

對于遠端

url

調用,同樣是通過将

url

解析成對應的動作,例如取某個視圖,推出某個界面。

元件化能讓工程架構更加清晰,每個人負責一個子產品,通過pod導入,互不影響。