組件化開發(fā)的個(gè)人理解和實(shí)際運(yùn)用

前言:

上一篇準(zhǔn)備工作組件化開發(fā)之私有庫(kù)制作以及常見(jiàn)問(wèn)題 已經(jīng)說(shuō)明了如何去制作私有庫(kù)并上傳,以及私有庫(kù)podspec文件的一些寫法問(wèn)題,有不清楚的可以通過(guò)上述傳送門去瞅一瞅,這一篇主要寫一下個(gè)人對(duì)于組件化開發(fā)的一些心得和實(shí)戰(zhàn)記錄,后續(xù)會(huì)附上具體demo以供朋友們閱讀,有說(shuō)的不對(duì)的地方也請(qǐng)指出,不要罵我23333,畢竟本人也是菜鳥一枚,自行摸索組件化,難免有些紕漏

體會(huì):

組件化適合多人開發(fā),也是近來(lái)比較熱門的項(xiàng)目架構(gòu)設(shè)計(jì)方式。16年本人便從網(wǎng)上看了些組件化相關(guān)的資料,比較經(jīng)典的是蘑菇街方案蘑菇街App的組件化之路以及蘑菇街的組件化之路.續(xù)和@casatwy基于蘑菇街方案的探討iOS應(yīng)用架構(gòu)談 組件化方案,那時(shí)候看不懂啊,腦袋疼,壓根兒不理解,后來(lái)17年又看了【一縷殤流化隱半邊冰霜】的iOS 組件化 —— 路由設(shè)計(jì)思路分析,以及組件化架構(gòu)漫談 結(jié)果是對(duì)組件化越來(lái)越懵逼,對(duì)于組件化遲遲不敢下手,找不到入口。
最近想要嘗試下組件化到底是一種什么感受,斷斷續(xù)續(xù)看了一年多的組件化理論知識(shí),如今終于要開啟嘗試之旅,心中還是有些忐忑的,于是先去整了私有庫(kù)相關(guān)的一些準(zhǔn)備工作,接下來(lái)嘗試將項(xiàng)目中的一些基礎(chǔ)模塊,公共模塊和功能模塊給抽了出來(lái),算是走出了第一步。

理解:

我個(gè)人對(duì)于組件化的認(rèn)知比較簡(jiǎn)單,覺(jué)得它就是一種解耦的方式,各人管各自的事情,在多人開發(fā)的場(chǎng)景下,這種方式肯定是非常有利于提高開發(fā)效率的,個(gè)人開發(fā)的話有興趣可以嘗試,畢竟是吃力不討好的事情,比如我吃飽了撐的就來(lái)試試~~~
一般項(xiàng)目模塊都是耦合很嚴(yán)重的,如下:


初始結(jié)構(gòu).png

圖中的關(guān)系錯(cuò)綜復(fù)雜,各種耦合,看起來(lái)也是無(wú)可奈何,特別是后期維護(hù),牽一發(fā)而動(dòng)全身,恨不能一鍵刪除推倒重來(lái),這也難不倒思路五花八門的開發(fā)者們,于是為了解耦合,有了下一張圖:


優(yōu)化結(jié)構(gòu).png

但這個(gè)還有問(wèn)題,雖然各個(gè)模塊之間的耦合解了,但是各個(gè)模塊還要依賴中間件,中間件也要依賴各個(gè)模塊,這還是相當(dāng)于沒(méi)有解耦,所以與時(shí)俱進(jìn),有了下一張圖:


最終結(jié)構(gòu).png

這里表示的是只讓模塊對(duì)中間件依賴,中間件完全不依賴任何模塊,我們所說(shuō)的解耦合其實(shí)也就是這種效果,如果能做到這種,那么,每個(gè)模塊的負(fù)責(zé)人都不用再擔(dān)心另一個(gè)模塊如何,只需要和中間層進(jìn)行溝通即可

對(duì)于中間件,網(wǎng)上流行的有三種用法,一種是蘑菇街的URL方法,一種是target-action硬編碼的方法,另外一種是protocol方法,我個(gè)人采用的是target-action方法,這里就簡(jiǎn)單介紹一下,而后再結(jié)合示例demo具體運(yùn)用。

一.路由-中間件的定制

同樣的,中間件可以作為一個(gè)組件單獨(dú)存在,我這里將以LWRouter的私有庫(kù)方式去管理路由,里面只提供簡(jiǎn)單的跳轉(zhuǎn)(push present)兩種交互方式

1. 創(chuàng)建路由組件的私有庫(kù),方式參照上篇文章
2. 路由的實(shí)現(xiàn)
+ (UIViewController *)router_getControllerFromClass:(NSString *)classNam {
    Class class = NSClassFromString(classNam);
    return [[class alloc] init];
}
+ (void)router_jumpToDestination:(UIViewController *)destinationVc from:(UIViewController *)sourceVc jumpType:(YGRouterJumpType)jumpType animation:(BOOL)animation params:(id)params {
    [self router_jumpToDestination:destinationVc from:sourceVc jumpType:jumpType animation:animation params:params callback:nil];
}
+ (void)router_jumpToDestinationWithName:(NSString *)destination from:(UIViewController *)sourceVc jumpType:(YGRouterJumpType)jumpType animation:(BOOL)animation params:(id)params {
    UIViewController *destinationVc = [self router_getControllerFromClass:destination];
    [self router_jumpToDestination:destinationVc from:sourceVc jumpType:jumpType animation:animation params:params];
}

+ (void)router_jumpToDestinationWithName:(NSString *)destination from:(UIViewController *)sourceVc jumpType:(YGRouterJumpType)jumpType animation:(BOOL)animation params:(id)params callback:(void(^)(id callback))callback {
    UIViewController *destinationVc = [self router_getControllerFromClass:destination];
    [self router_jumpToDestination:destinationVc from:sourceVc jumpType:jumpType animation:animation params:params callback:callback];
}
+ (void)router_jumpToDestination:(UIViewController *)destinationVc from:(UIViewController *)sourceVc jumpType:(YGRouterJumpType)jumpType animation:(BOOL)animation params:(id)params callback:(void(^)(id callback))callback {
    if (params) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
        [destinationVc performSelector:@selector(router_params:) withObject:params];
#pragma clang diagnostic pop
    }
    if (callback) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
        [destinationVc performSelector:@selector(router_callback:) withObject:callback];
#pragma clang diagnostic pop
    }
    if (jumpType == YGRouterJumpTypePush) {
        [sourceVc.navigationController pushViewController:destinationVc animated:animation];
    }else {
        [sourceVc presentViewController:destinationVc animated:animation completion:nil];
    }
}

這里提供了push ,modal兩種模式,此外還可以傳參以及回傳等,有其他情況的另行增加方法即可

二:示例demo的搭建以及結(jié)合組件化的過(guò)程

示例工程采用tabbar+nav+vc的模式,我這里分為基礎(chǔ)層,網(wǎng)絡(luò)層,應(yīng)用層和業(yè)務(wù)層以及路由。基礎(chǔ)層主要放一些公共部分和變化不大的的部分,網(wǎng)絡(luò)層主要管理項(xiàng)目中間的網(wǎng)絡(luò)請(qǐng)求部分,應(yīng)用層主要是一些工具類的封裝,業(yè)務(wù)層則是項(xiàng)目的一些業(yè)務(wù)邏輯部分,前三層基本不依賴彼此,業(yè)務(wù)層則需要依賴前三層,業(yè)務(wù)層中分為不同的模塊,模塊間的交互通信則是通過(guò)路由,大致的分配如下圖所示:

項(xiàng)目結(jié)構(gòu).png

從圖中可以很清晰的看到,層次劃分非常的清楚,如果多人配合開發(fā),只需要一個(gè)人負(fù)責(zé)一個(gè)模塊即可。至于項(xiàng)目中的哪些可以規(guī)劃到各個(gè)層級(jí)和模塊中就要視具體的情況而定,我這里主要大致說(shuō)一下自己的理解:

1.比如整個(gè)項(xiàng)目中的基類,我這里指的是不變的那些,如導(dǎo)航控制器,這個(gè)一般設(shè)置后就不需要變化的那種,分類,圖片,xib資源,常量類等都可以放到基礎(chǔ)層

2.網(wǎng)絡(luò)層主要放置網(wǎng)絡(luò)請(qǐng)求,可以使離散的,也可以是集約的。集約型也就是對(duì)AFN的二次封裝,提供的只是get,post等接口。離散型的,推薦YTKNetwork,思想是一個(gè)請(qǐng)求一個(gè)類,這兩者各有優(yōu)劣,關(guān)鍵看個(gè)人取舍。

3.應(yīng)用層主要放一些功能性的文件,如:支付功能,地圖,定位功能,數(shù)據(jù)庫(kù)封裝等

4.業(yè)務(wù)層就是做業(yè)務(wù)功能的,這里可以將每個(gè)模塊細(xì)分為一個(gè)私有庫(kù)方便多人開發(fā)時(shí)每個(gè)人負(fù)責(zé)一個(gè)業(yè)務(wù)模塊去開發(fā)。

5.主工程導(dǎo)入各個(gè)私有庫(kù)文件,提供入口即可

  • 大致的結(jié)構(gòu)如此,當(dāng)然這里只是我個(gè)人對(duì)于模塊和層級(jí)的理解,如果你有更好的劃分方式和心得,歡迎在留言區(qū)進(jìn)行溝通交流。

下面具體講下過(guò)程和引入

1.創(chuàng)建遠(yuǎn)程倉(cāng)庫(kù)并拉取到本地,制作成私有庫(kù)
屏幕快照 2018-11-19 下午3.16.34.png
屏幕快照 2018-11-19 下午2.48.28.png

私有庫(kù)的制作見(jiàn)前文,這里不再贅述

最終導(dǎo)入項(xiàng)目的結(jié)構(gòu)如下:


屏幕快照 2018-11-19 下午6.46.16.png
屏幕快照 2018-11-19 下午6.55.22.png
2.主工程調(diào)用

前面已經(jīng)提到,組件化比較理想的結(jié)構(gòu)是,主工程中只有入口,也就是我們常用的設(shè)置TabBar相關(guān)以及一些必要的配置等,其他都在組件私有庫(kù)中完成,通過(guò)上面的結(jié)構(gòu)我們已經(jīng)實(shí)現(xiàn)了拆分功能為私有化組件,接下來(lái)就是通過(guò)主工程提供入口并組合起來(lái)。


Simulator Screen Shot - iPhone 6s Plus - 2018-11-20 at 13.24.37.png
3.模塊間的通信與交互

主要通過(guò)router,示例代碼如下:

傳參不帶回傳參數(shù)的:


屏幕快照 2018-11-20 下午1.26.37.png

傳參帶回傳參數(shù)的:


屏幕快照 2018-11-20 下午1.26.23.png

若是ModalA和ModalB交互,采用的方式也是如此

具體的使用過(guò)程可以通過(guò)傳送門查看,有關(guān)于組件化方面的心得體會(huì)可以在評(píng)論區(qū)進(jìn)行交流學(xué)習(xí),本人也是初次嘗試使用,有用的不到的地方或者理解有偏頗的地方,還請(qǐng)海涵,多謝朋友們的指正,大家共同學(xué)習(xí),謝謝~~~~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,351評(píng)論 25 708
  • 用兩張圖告訴你,為什么你的 App 會(huì)卡頓? - Android - 掘金 Cover 有什么料? 從這篇文章中你...
    hw1212閱讀 14,118評(píng)論 2 59
  • 該文章屬于劉小壯原創(chuàng),轉(zhuǎn)載請(qǐng)注明:劉小壯[http://m.itdecent.cn/u/2de707c93d...
    劉小壯閱讀 94,257評(píng)論 266 517
  • 先介紹一下自己,大三在校生。昨晚八點(diǎn)多一點(diǎn),帶完家教,去公交車站臺(tái),在紅綠燈處遇到我要做的18路車,方向應(yīng)該是對(duì)的...
    天空在眨眼閱讀 157評(píng)論 0 0
  • 今天兒子上了一天特長(zhǎng),晚上回家路上讓我今晚陪他下象棋,和媳婦處理完事情已經(jīng)九點(diǎn)多了,兒子在家中為他媽媽...
    寶鈞閱讀 164評(píng)論 0 3

友情鏈接更多精彩內(nèi)容