1. 程式人生 > >iOS App元件化開發實踐

iOS App元件化開發實踐

前因

其實我們這個7人iOS開發團隊並不適合元件化開發。原因是因為價效比低,需要花很多時間和經歷去做這件事,帶來的收益並不能徹底改變什麼。但是因為有2~3個星期的空檔期,並不是很忙;另外是可以用在一個全新的App上。所以決定想嘗試下元件化開發。

所謂嘗試也就是說:去嘗試解決元件化開發當中的一些問題。如果能解決,並且有比較好的解決方案,那就繼續下去,否則就放棄。

背景

脫離實際情況去談方案的選型是不合理的。

所以先簡單介紹下背景:我們是一家納斯達克交易所上市的科技企業。我們公司還有好幾款App,由不同的幾個團隊去維護,我們是其中之一。我們這個團隊是一個7人的iOS開發小團隊。作者本人是小組長。

之前的App已經使用了模組化(CocoaPods)開發,並且已經使用了 

二進位制化 方案。App已經在使用自動化整合。

雖然要開發一個新App,但是很多業務和之前的App是一樣的或者相似的。

為什麼要寫這篇部落格?

想把整個過程記錄下來,方便以後回顧。

我們的思路和解決方案不一定是對的或者是最好的。所以希望大家看了這篇部落格之後,能給我們提供很多建議和別的解決方案,讓我們可以優化使得這個元件化開發的方案能變得更加好。

技術棧

  • gitlab
  • gitlab-runner
  • CocoaPods
  • CocoaPods-Packager
  • fir
  • 二進位制化
  • fastlane
  • deploymate
  • oclint
  • Kiwi

成果

使用元件化開發App之後:

  • 程式碼提交更規範,質量提高。體現在測試人員反饋的bug明顯減少。
  • 編譯加快。在都是原始碼的情況下:原App需要150s左右整個編譯完畢,然後開發人員才可以開始除錯。而現在元件化之後,某個業務元件只需要10s~20s左右。在依賴二進位制化元件的情況下,業務元件編譯速度一般低於10s。
  • 分工更為明確,從而提升開發效率。
  • 靈活,耦合低。
  • 結合MVVM。非常細緻的單元測試,提高程式碼質量,保證App穩定性。體現在測試人員反饋的bug明顯減少。
  • 回滾更方便。我們經常會發生業務或者UI變回之前版本的情況,以前我們都是checkout出之前的程式碼。而現在元件化了之後,我們只需要使用舊版本的業務元件Pod庫,或者在舊版本的基礎上再發一個Pod庫。
  • 新人更容易上手。

對於我來說:

  • 更加容易地把控程式碼質量。
  • 更加容易地知道小組成員做了些什麼。
  • 更加容易地分配工作。
  • 更加容易地安排新成員。

解耦

我們的想法是這樣的,就算最後做不成元件化開發,把這些應該重用的程式碼抽出來做成Pod庫也沒有什麼影響。所以優先做了這一步。

哪些東西需要抽成Pod庫?

我們之前的App已經使用了模組化(CocoaPods化)開發。我們已經把會在App之間重用的Util、Category、網路層和本地儲存等等這些東西抽成了Pod庫。還有些一些和業務相關的,比如YTXChart,YTXChartSocket;這些也是在各個App之間重用的。

所以得出一個很簡單的結論:要在App之間共享的程式碼就應該抽成Pod庫,把它們作為一個個元件。

我們去仔細查看了原App程式碼,發現很多東西都需要重用而我們卻沒有把它們元件化。

為什麼沒有把這些程式碼元件化?

因為當時沒想好怎麼解耦,舉個例子。

有一個類叫做YTXAnalytics。是依賴UMengAnalytics來做統計的。 它的耦合是在於一個方法。這個方法是用來收集資訊的。它依賴了User,還依賴了currentServerId這個東西。

+ (NSDictionary*)collectEventInfo:(NSString*)event withData:(NSDictionary*)data
{
.......
    return @{
        @"event" : event,
        @"eventType" : @"event",
        @"time" : [[[NSDate date] timeIntervalSince1970InMillionSecond] stringValue],
        @"os" : device.systemName,
        @"osVersion" : device.systemVersion,
        @"device" : device.model,
        @"screen" : screenStr,
        @"network" : [YTXAnalytics networkType],
        @"appVersion" : [AppInfo appVersion],
        @"channel" : [AppInfo marketId],
        @"deviceId" : [ASIdentifierManager sharedManager].advertisingIdentifier.UUIDString,
        @"username" : objectOrNull([YTXUserManager sharedManager].currentUser.username),
        @"userType" : objectOrNull([[YTXUserManager sharedManager].currentUser.userType stringValue]),
        @"company" : [[ServiceProvider sharedServiceProvider].currentServerId stringValue],
        @"ip" : objectOrNull([SSNetworkInfo currentIPAddress]),
        @"data" : jsonStr
    };
}

解決方案是,搞了一個block,把獲取這些資訊的責任丟出來。

[YTXAnalytics sharedAnalytics].analyticsDataBlock = ^ NSDictionary *() {
        return @{
                 @"appVersion" : objectOrNull([PBBasicProviderModule appVersion]),
                 @"channel" : objectOrNull([PBBasicProviderModule marketId]),
                 @"username" : objectOrNull([PBUserManager shared].currentUser.username),
                 @"userType" : objectOrNull([PBUserManager shared].currentUser.userType),
                 @"company" : objectOrNull([PBUserManager shared].currentUser.serverId),
                 @"ip" : objectOrNull([SSNetworkInfo currentIPAddress])
                 };
    };

我們的耦合大多數都是這種。解決方案都是弄了一個block,把獲取資訊的職責丟出來到外面。

我們解耦的方式就是以下幾種:

  1. 把它依賴的程式碼先做成一個Pod庫,然後轉而依賴Pod庫。有點像是“依賴下沉”。
  2. 使用category的方式把依賴改成組合的方式。
  3. 使用一個block或delegate(協議)把這部分職責丟出去。
  4. 直接copy程式碼。copy程式碼這個事情看起來很不優雅,但是它的好處就是快。對於一些不重要的工具方法,也可以直接copy到內部來用。

初始化

AppDelegate充斥著各種初始化。 比如我們自己的程式碼。已經只是截取了部分!

[self setupScreenShowManager];

    //event start
    [YTXAnalytics createYtxanalyticsTable];
    [YTXAnalytics start];
    [YTXAnalytics page:APP_OPEN];
    [YTXAnalytics sharedAnalytics].analyticsDataBlock = ^ NSDictionary *() {
        return @{
                 @"appVersion" : objectOrNull([AppInfo appVersion]),
                 .......
                 @"ip" : objectOrNull([SSNetworkInfo currentIPAddress]),
                 };
    };

    [self registerPreloadConfig];
    //Migrate UserDefault 轉移standardUserDefault到group
    [NSUserDefaults migrateOldUserDefaultToGroup];
    [ServiceProvider sharedServiceProvider];

    [YTXChatManager sharedYTXChatManager];
    [ChartSocketManager sharedChartSocketController].delegate = [ChartProvider sharedChartProvider];

    //初始化最初的行情集合
    [[ChartProvider sharedChartProvider] addMetalList:[ChartSocketManager sharedChartSocketController].quoteList];

    //初始化環信資訊Manager
    [YTXEaseMobManager sharedManager];

比如第三方:

//註冊環信
    [self setupEaseMob:application didFinishLaunchingWithOptions:launchOptions];

    //Talking Data
    [self setupTalkingData];
    [self setupAdTalkingData];
    [self setupShareSDK];
    [self setupUmeng];
    [self setupJSPatch];
    [self setupAdhocSDK];
    [YTXGdtAnalytics communicateWithGdt];//廣點通

首先這些初始化的東西是會被各個業務元件都用到的。

那我元件化開發的時候,每一個業務元件如何保證我使用這些東西的時候已經初始化過了呢?難道每一個業務元件都初始化一遍?有引數怎麼辦,能不能使用單例?

但問題是第三方庫基本都需要註冊一個AppKey,我每一個業務元件裡都寫一份?那樣肯定不好,那我配置在主App裡的info.plist裡面,每一個業務元件都初始化一下好了,也不會有什麼副作用。但這樣感覺不優雅,而且有很多重複程式碼。萬一某個AppKey或重要引數改了,那每一個業務元件豈不是都得改了。這樣肯定不行。另外一點,那我的業務元件必須依賴主App的內容了。無論是在主App裡除錯還是把主App的info.plist的相關內容拷貝過來使用。

更關鍵的是有一些第三方的庫需要在application: didFinishLaunchingWithOptions:時初始化。

//初始化環信,shareSDK, 友盟, Talking Data等
[self setupThirdParty:application didFinishLaunchingWithOptions:launchOptions];

有沒有更好的辦法呢?

首先我寫了一個 YTXModule 。它利用runtime,不需要在AppDelegate中新增任何程式碼,就可以捕獲App生命週期。

在某個想獲得App生命週期的類中的.m中這樣使用:

YTXMODULE_EXTERN()
{
    //相當於load
    isLoad = YES;
}
+ (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(nullable NSDictionary *)launchOptions
{
    //實現一樣的方法名,但是必須是靜態方法。
    return YES;
}

分層

因為在解決初始化問題的時候,要先設計好層級結構。所以這裡突然跳轉到分層。

上個圖:

我們自己定了幾個原則。

  • 業務元件之間不能有依賴關係。
  • 按照圖示不能跨層依賴。
  • 所謂弱業務元件就是包含著少部分業務,並且可以在這個App內的各個業務元件之間重用的程式碼。
  • 要依賴YTXModule的元件一定要以Module結尾,而且它一定是個業務元件或是弱業務元件。
  • 弱業務元件以App代號開頭(比如PB),以Module結尾。例:PBBasicProviderModule。
  • 業務元件以App代號開頭(比如PB)BusinessModule結尾。例:PBHomePageBusinessModule。

業務元件之間不能有依賴關係,這是公認的的原則。否則就失去了元件化開發的核心價值。

弱業務元件之間也不應當有依賴關係。如果有依賴關係說明你的功能劃分不準確。

初始化

我們約定好了層級結構,明確了職責之後。我們就可以跳回初始化的設計了。

建立一個PBBasicProviderModule弱業務元件。

  • 它通過依賴YTXModule來捕捉App生命週期。
  • 它來負責初始化自己的和第三方的東西。
  • 所有業務元件都可以依賴這個弱業務元件。
  • 它來保證所有東西一定是是初始化完畢的。
  • 它來統一管理。
  • 它來暴露一些類和功能給業務元件使用。

反正就是業務元件中依賴PBBasicProviderModule,它保證它裡面的所有東西都是好用的。

因為有了PBBasicProviderModule,所以才讓我更明確了弱業務元件這個概念。

因為我們懶,如果把PBBasicProvider定義為業務元件。那它和其他業務元件之間的通訊就必須通過Bus、Notification或協議等等。

但它又肯定是業務啊。因為那些AppKey肯定是和這個App有關係的,也就是App的相關配置和引數也可以說是業務;我需要初始化設定那些Block依賴User資訊、CurrentServerId等等肯定都是業務啊。

那隻好搞個弱業務出來啊。因為我不能打破這個原則啊:業務元件之間不能互相依賴。

再進一步分清弱業務元件和業務元件。

業務元件裡面基本都有:storyboard、nib、圖片等等。弱業務元件裡面一般沒有。這不是絕對的,但一般情況是這樣。

業務元件一般都是App上某一具體業務。比如首頁、我、直播、行情詳情、XX交易大盤、YY交易大盤、XX交易中盤、資訊、發現等等。而弱業務元件是給這些業務元件提供功能的,自己不直接表現在App上展示。

我們還可以建立一些弱業務元件給業務元件提供功能。當然了,不能夠濫用。需要準確劃分職責。

最後,程式碼大概是這樣的:

@implementation PBBasicProviderModule

YTXMODULE_EXTERN()
{

}

+ (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(nullable NSDictionary *)launchOptions
{
    [self setupThirdParty:application didFinishLaunchingWithOptions:launchOptions];
    [self setupBasic:application didFinishLaunchingWithOptions:launchOptions];

    return YES;
}

+ (void) setupThirdParty:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        [self setupEaseMob:application didFinishLaunchingWithOptions:launchOptions];
        [self setupTalkingData];
        [self setupAdTalkingData];
        [self setupShareSDK];
        [self setupJSPatch];
        [self setupUmeng];
//        [self setupAdhoc];
    });
}

+ (void) setupBasic:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [self registerBasic];

    [self autoIncrementOpenAppCount];

    [self setupScreenShowManager];

    [self setupYTXAnalytics];

    [self setupRemoteHook];
}

+ (YTXAnalytics) sharedYTXAnalytics
{
    return ......;
}
......

設想

這個PBBasicProviderModule簡直就是個大雜燴啊,把很多以前寫在AppDelegate裡的東西都丟在裡面了。毫無優雅可言。

的確是這樣的,感覺沒有更好的辦法了。

既然已經這樣了。我們可不可以大膽地設想一下:每個開發者開發自己負責的業務元件的時候不需要關心主App。

因為我知道美團的元件化開發必須依賴主App的AppDelegate的一大堆設定和初始化。所以乾脆他們就直接在主App中整合除錯,他們通過二進位制化和去Pod依賴化的方式讓主App的構建非常快。

所以我們是不是可以繼續汙染這個PBBasicProviderModule。不需要在主App專案裡的AppDelegate寫任何初始化程式碼?基本或者儘量不在主App裡寫任何程式碼?改依賴主App變為依賴這個弱業務元件?

按照這個思路我們搬空了AppDelegate裡的所有程式碼。比如一些初始化App樣式的東西、初始化RootViewController等等這些都可以搬到一個新的弱業務元件裡。

而業務元件其實根本不需關心這個弱業務元件,開發人員只需要在業務元件中的Example App中的AppDelegate中初始化自己業務元件的RootViewController就好了。

其他的事情交給這個新的弱業務元件就好了。而主App和Example App只要在Podfile中依賴它就好了。

所以最後的設想就是:開發者不會去改主App專案,也不需要知道主App專案。對於開發者來說,主App和業務元件之間是隔絕的。

有一個更大的好處,我只要更換這個弱業務元件,這個業務元件就能馬上適配一個新App。這也是某種意義上的解耦。

Debug/Release

誰說不用在主App裡的AppDelegate寫任何程式碼的,打臉。。。

我們在對二進位制Pod庫跑測試的發現,原始碼能過,二進位制(.a)不能過。百思不得其解,然後仔細檢視程式碼,發現是這個巨集的鍋:

#ifdef DEBUG

#endif

DEBUG在編譯階段就已經決定了。二進位制化的時候已經編譯完成了。 而我們的程式碼中充滿著#ifdef DEBUG 就這樣這樣。那怎麼辦,這是二進位制化的鍋。但是我們的二進位制化已經形成了標準,大家都自覺會這麼做,怎麼解決這個問題呢。

解決方案是:

建立了一個PBEnvironmentProvider。大家都去依賴它。

然後原來判斷巨集的程式碼改成這樣:

if([PBEnvironmentProvider testing])
{
//...
}

在主App的AppDelegate中這樣:

#if DEBUG && TESTING
//PBEnvironmentProvider提供的巨集
CONFIG_ENVIRONMENT_TESTING
#endif

原理是:如果AppDelegate有某個方法(CONFIG_ENVIRONMENT_TESTING巨集會提供這個方法),[PBEnvironmentProvider testing]得到的結果就是YES。

為什麼要寫在主App裡呢?其實也可以丟在PBBasicProviderModule裡面,提供一個方法啊。

因為主App的AppDelegate.m是原始碼,未經編譯。另外注意TESTING這個巨集。我們可以在xcode設定里加一個macro引數TESTING,並且修改為0的情況下,能夠生成一個實際是DEBUG的App但裡面內容卻是線上的內容。

這個需求是來自於我們經常需要緊急通過xcode直接build一個app到手機上以解決或確認線上的問題。

雖然打臉了,但是也還好,以後也不用改了。再說這個是特殊需求。除了這個之外,主App沒有其他程式碼了。

業務元件間通訊

我們解決了初始化和解耦的問題。接下來只要解決元件間通訊的問題就好了。

然後我找了幾個第三方庫,選用了 MGJRouter 。本來直接依賴它就好了。

後來覺得都使用Block的方式會導致這樣的程式碼,全部堆在了一個方法裡:

+ (void) setupRouter
{
......
[MGJRouter registerURLPattern:@"mgj://foo/a" toHandler:^(NSDictionary *routerParameters) {
    NSLog(@"routerParameterUserInfo:%@", routerParameters[MGJRouterParameterUserInfo]);
}];
[MGJRouter registerURLPattern:@"mgj://foo/b" toHandler:^(NSDictionary *routerParameters) {
    NSLog(@"routerParameterUserInfo:%@", routerParameters[MGJRouterParameterUserInfo]);
}];
......
}

這樣感覺很不爽。那我乾脆就把MGJRouter程式碼複製了下來,把Block改成了@selector。並且把它直接加入了 YTXModule 裡面。並且使用了巨集,讓結果看起來優雅些。程式碼看起來是這樣的:

//在某個類的.m裡,其實並不需要繼承YTXModule也可以使用該功能
YTXMODULE_EXTERN_ROUTER_OBJECT_METHOD(@"object1")
{
    YTXMODULE_EXAPAND_PARAMETERS(parameters)
    NSLog(@"%@ %@", userInfo, completion);
    isCallRouterObjectMacro2 = YES;
    return @"我是個型別";
}

YTXMODULE_EXTERN_ROUTER_METHOD(@"YTX://QUERY/:query")
{
    YTXMODULE_EXAPAND_PARAMETERS(parameters)
    NSLog(@"%@ %@", userInfo, completion);
    testQueryStringQueryValue = parameters[@"query"];;
    testQueryStringNameValue = parameters[@"name"];
    testQueryStringAgeValue = parameters[@"age"];
}

呼叫的時候看起來是這樣的:

[YTXModule openURL:@"YTX://QUERY/query?age=18&name=CJ" withUserInfo:@{@"Test":@1} completion:nil];

 NSString * testObject2 = [YTXModule objectForURL:@"object1" withUserInfo:@{@"Test":@2}];

通訊問題解決了。其實頁面跳轉問題也解決了。

頁面跳轉

頁面跳轉解決方案與業務元件之間通訊問題是一樣的。

但是需要注意的是,你一個業務元件內部的頁面跳轉也請使用URL+Router的方式跳轉,而不要自己直接pushViewController。

這樣的好處是:如果將來某些內部跳轉頁面需要給其他業務元件呼叫,你就不需要再註冊個URL了。因為本來就有。

是否去Model化

去Model化主要體現在業務元件間通訊,要不要傳一個Model過去(傳過去的Dictionary中的某個鍵是Model)。

如果去Model化,這個業務元件的開發者如何確定Dictionary裡面有哪些內容分別是什麼型別呢?那需要有個地方傳播這些資訊,比如寫在標頭檔案,wiki等等。

如果不去Model化的話,就需要把這個Model做成Pod庫。兩個業務元件都去依賴它。

最後決定不去Model。因為實際上有一些Model就是在各個業務元件之間公用的(比如User),所以肯定就會有Model做成Pod庫。我們可以把它做成重Model,Model裡可以帶網路請求和本地儲存的方法。唯一不能避免的問題是,兩個業務元件的開發者都有可能去改這個Model的Pod庫。

資訊的披露

跳轉的頁面需要傳哪些引數? 業務元件之間傳遞資料時候本質的載體是什麼?

不同業務開發者如何知曉這些資訊。

使用去Model化和不使用去Model化,我們都有各自的方案。

去Model化,則披露標頭檔案,在標頭檔案裡面寫詳細的註釋。

如果不去Model化,則就看Model就可以了。如有特殊情況,那也是文件寫在標頭檔案內。

總結的話:資訊披露的方式就是把註釋文件寫在標頭檔案內。

元件的生命週期

業務元件的生命週期和App一樣。它本身就是個類,只暴露類方法,不存在需要例項,所以其實不存在生命週期這個概念。而它可以使用類方法建立很多ViewController,ViewController的生命週期由App管理。哪怕這些ViewController之間需要通訊,你也可以使用Bus/YTXModule/協議等等方式來做,而不應該讓業務元件這個類來負責他們之間的通訊;也不應該自己持有ViewController;這樣增加了耦合。

弱業務元件的生命週期由建立它的物件來管理。按需建立和ARC自動釋放。

基礎功能元件和第三方的生命週期由建立它的物件來管理。按需建立和ARC自動釋放。

版本規範

我們自己定的規則。

所有Pod庫都只依賴到minor

"~> 2.3"

主App中精確依賴到patch

"2.3.1"

主App中的業務元件版本號的Main.Minor要和主App版本保持一致。

二進位制化

二進位制化我認為是必須的,能夠加快開發速度。

而我使用的這個 二進位制方案

有個坑就是在gitlab-runner上在二進位制和原始碼切換時,經常需要pod cache clean --all,test/lint/publish才能成功。而每次pod cache clean --all之後CocoaPods會去重新下載相關的pod庫,增加了時間和不必要的開銷。

我們現在通過podspec中增加preserve_paths和執行download_zip.sh解決了cache的問題。原理是讓pod cache既有原始碼又有二進位制.a。具體可以看ytx-pod-template專案中的 Name.podspec 和 download_zip.sh 。

二進位制化還得注意巨集的問題。小心使用巨集,尤其是#ifdef。避免原始碼和二進位制程式碼執行的結果不一樣。

整合除錯

整合除錯很簡單。每一個業務元件在自己的Example App中除錯。

這個業務元件的podspec只要寫清楚自己依賴的庫有哪些。剩下的其他業務元件應該寫在Example App的Podfile裡面。

依賴的Pod庫都是二進位制的。如有問題可以裝原始碼(IS_SOURCE=1 pod install)來除錯。

開發人員其實只需要關心自己的業務元件,這個業務元件是自洽的。

公共庫誰來維護的問題

相關推薦

iOS App元件開發實踐

前因其實我們這個7人iOS開發團隊並不適合元件化開發。原因是因為價效比低,需要花很多時間和經歷去做這件事,帶來的收益並不能徹底改變什麼。但是因為有2~3個星期的空檔期,並不是很忙;另外是可以用在一個全新的App上。所以決定想嘗試下元件化開發。所謂嘗試也就是說:去嘗試解決元件化開發當中的一些問題。如果能解決,並

iOS元件開發

在一個APP開發過程中,如果專案較小且團隊人數較少,使用最基本的MVC、MVVM開發就已經足夠了,因為維護成本比較低。 但是當一個專案開發團隊人數較多時,因為每個人都會負責相應元件的開發,常規開發模式耦合會越來越嚴重,而且導致大量程式碼衝突,會使後期維護和升級過程中程式碼“牽一髮而動全身”,額外

Android元件開發實踐

前兩年安卓外掛化開發在國內進行的如火如荼,出現了不少外掛化的框架,360,攜程等都開源了比較好的外掛化框架,外掛化開發確實是可以給開發者帶來很大的方便。不過外掛化需要解決的問題太多,動態載入類,資源等等,首先就需要對安卓的打包機制,執行機制等等了解的很清楚。對個

Android 業務元件開發實踐

本文原創,轉載請以連結形式註明地址:http://kymjs.com/code/2016/10/18/01元件化並不是新話題,其實很早很早以前我們開始為專案解耦的時候就討論過的。但那時候我們說的是功能元件化。比如很多公司都常見的,網路請求模組、登入註冊模組單獨拿出來,交給一個團隊開發,而在用的時候只需要接入對

Android業務元件開發實踐

1. 寫在前面 原文地址:http://kymjs.com/code/2016/10/18/01 借用阿布倪盟博的一句話:“在MDCC中馮森林老師的《迴歸初心,從容器化到元件化》,為我們這些沒有那麼多精力折騰黑科技開發者們打開了另一扇門” 。 元件

Android業務元件開發實踐(轉載)

借用阿布倪盟博的一句話:“在MDCC中馮森林老師的《迴歸初心,從容器化到元件化》,為我們這些沒有那麼多精力折騰黑科技開發者們打開了另一扇門” 。 元件化並不是新話題,其實很早很早以前我們開始為專案解耦的時候就討論過的。但那時候我們說的是功能元件化。比如很多公司都常

Android業務元件開發實踐(二)

前言:       從個人經歷來說的話,從事APP開發這麼多年來,所接觸的APP的體積變得越來越大,業務的也變得越來越複雜,總來來說只有一句話:這是一個APP臃腫的時代!所以為了告別APP臃腫的時代,讓我們進入一個U盤時代,每個業務模組都是一個具備獨立執行的U盤,插在哪裡都可以完美執行,這就是推進業務元件

iOS 解藕、元件最佳實踐

iOS 解藕、元件化最常用的是使用統跳路由的方式,目前比較常用的 iOS 開源路由框架主要是JLRoutes、MGJRouter、HHRouter等,這些路由框架各有優點和缺點,基本可以滿足大部分需求。目前最常用來作路由跳轉,以實現基本的元件化開發,實現各模組之間的解藕。但是,在實際中開發中會發現,無法徹底使

iOS元件開發-CocoaPods簡介

CocoaPods簡介 任何一門開發語言到達一定階段就會出現第三方的類庫管理工具,比如Java的Maven、WEB的Webpack等。在iOS中類庫的管理工具-CocoaPods。 利用CocoaPods管理第三方庫可以自動化幫我們完成各種庫的依賴和配置,包括配置編譯階段、連結器選項、甚至是ARC環境下的

iOS元件開發之——使用Cocoapods打私有的Pod庫

隨著專案和業務的發展,專案中會有很多基礎功能模組和通用業務模組可以抽象出來獨立成元件,這樣可以為我們以後在開發新專案的時候提供共用基礎元件,進行元件化程式設計,不需要重新造輪子,提高開發效率。因此我們就需要一個方案來合理的管理公共的元件。 Spec Repo(配置倉庫)

iOS 元件開發(三):載入資原始檔

經過前兩篇文章的學習,相信對元件化開發有了大致的瞭解,那我們這篇文章就來講講資原始檔的載入吧 這裡我新建了一個LXFMain元件庫,主要是用來顯示TabBar的玩意,然後再進行元件化抽離出來,其中的過程這裡不再贅述,還沒了解過的同學建議先閱讀下這兩篇文

iOS 元件開發(一):遠端私有庫的基本使用

隨著專案功能的不斷增加,越來越多的開發人員加入,業務主線也隨之越來越多,造成耦合越來越嚴重,編譯越來越慢,測試不獨立等一系列問題。為了解決此類情況,我們可以考慮到使用元件化開發 概念 元件化就是將一個單一工程的專案, 分解成為各個獨立的元件, 然後

iOS之旅--釋出自己的CocoaPods庫(元件開發第一步)

從去年的Dev大會上就開始慢慢接觸瞭解元件化,但是沒有實際的專案可以操作,擱淺至今,中間也嘗試性的試驗過,現在來一個總結。 1、思考 抽取專案中獨立的程式碼,作為模組與整體專案分開。首先我能想到的網路庫、工具類、封裝好的一些控制元件,涉及業務的由於業務有

仿京東app,採用元件開發 ARouter + mvp + dagger2 + rxjava + retrofit + fresco 架構

# JD-Test 仿京東app 採用元件化架構 螢幕適配方案可以較好解決多解析度及同分辨率不同dpi適配;### 宣告 : 本專案資源採用抓包獲取,僅供學習交流使用 。 話說一切沒有gif圖的專案都是耍流氓,上圖: 本專案為仿京東專案,資源為抓包獲取,專案框架採用路由框

iOS】利用CocoaPods建立私有庫進行元件開發

之前使用CocoaPods管理過第三方庫,前面也有翻譯文章介紹過CocoaPods的配置方法,隨著專案越來越大,很多公司會使用CocoaPods進行元件化開發,下面利用一個demo介紹一下。 什麼是庫 先說下什麼是庫,庫分為靜態庫和動態庫兩種: - 1

iOS元件開發

一 . 為什麼要元件化? 對於一些小的專案,有一個或者兩三個人可以獨立完成的專案,沒有必要用元件化開發。元件化開發主要是為了解決專案越來越大,開發人員越來越多,專案耦合性高,不利於維護的問題。 二 . 什麼是元件化? 1.元件:一般來說用於命名

iOS元件開發-釋出私有庫

遠端索引庫 將遠端索引庫添關聯到本地 pod repo 檢視本地已關聯倉庫源 pod repo add 本地索引庫名稱 遠端索引庫倉庫地址 pod repo update 索引庫名稱 pod repo remove 本地索引庫名稱  執行命令 新增遠端索引庫`KTPodSpecs`克隆到本

Android 業務組件開發實踐

公司 跳轉 not apk 優勢 避免 項目結構 行為 分享 組件化並不是新話題,其實很早很早以前我們開始為項目解耦的時候就討論過的。但那時候我們說的是功能組件化。比如很多公司都常見的,網絡請求模塊、登錄註冊模塊單獨拿出來,交給一個團隊開發,而在用的時候只需要接入對應模塊的

Android組件開發實踐

理發 modules 開發 顯示 容易 apply strong undefined end Android項目中代碼量達到一定程度,編譯將是一件非常痛苦的事情,短則一兩分鐘,長則達到五六分鐘。Android studio推出instant run由於各種缺陷一般情況下

react元件開發釋出到npm

1.專案目錄 build:webpack打包用(開發環境、釋出環境) example:開發環境的模板頁 lib:打包好的資料夾(用於釋出到npm上) src:想要封裝的公共元件 .babelrc:處理es6語法 package.json:打包的依賴檔案,管理專案模組包 開發環