iOS组件化/模块化的方案总结

一、为什么要组件化

1.实现之间解耦、减少项目的编译时间,提升业务开发效率。

通常一个工程中会有多个模块,而模块之间会有依赖关系,比如A调用B,那么在A模块中就会引用B模块的头文件,同时可能B模块又会依赖C模块,C模块又会依赖A模块等等,最终的结果是各模块高度耦合,特别是大型的工程,耦合特别严重。如下图所示

模块耦合
如果想避免耦合,那么我们需要设计一种结构避免,各模块之间耦合,可以如下图所示结构:
理想的模块关系
这种结构有什么好处呢?
1)首先是将模块拆分成组件单独管理,拆分成单独的库,这样各组件在进行开发的时候,只需要编译自己的库文件,大大减少文件的编译时间,我们的工程,之前编译需要20分钟左右,现在只需几分钟,这个对效率提高,非常明显。
2)各个库单端管理,可以进行权限设置,只有各组件相关人员才可以修改组件代码,不会出现一个大的工程中,A修改了B的代码的情况,可以一定程度上保证代码的安全性。

2.合并项目容易出现冲突。

在每次发版以后,release分支会向dev分支合并代码,由于各组件会提交许多代码,不同的开发者可能会同时修改同一个文件,引起冲突,这样一个工程中就会出现多处的合并冲突,比如一个几十人的团队,这个冲突的概率非常大,需要各组件的人去dev分支修改自己组件的冲突,如果冲突没有解决,整个工程都无法运行,影响整个团队的开发,非常影响效率。

3.模块拆分成组件,方便对外付能

假设一个项目中有多个组件,相互耦合,这个时候想单独将一个组件拆分出来,提供给它人使用,几乎是不可能的,而组件化接触这种耦合之后,我们可以直接将某个组件单独提供给它人使用,各个组件可以像积木一样,相互组合起来,形成一个新的APP对外付能。

二、组件化方案

组件化方案,主要分为两个部分,一是代码如何解耦,二是如何进行版本管理,下面分别进行详细讲解。

1.代码解耦

1)组件原则
组件通常分为两种类型的组件:基础组件,业务组件。
*业务组件依赖基础组件
*基础组件不可依赖业务组件。
*业务组件间不可相互依赖。

2)组件间的通信方式:
组件间通信方式,业内主要有两种实现方式:
1.协议式框架,比如蘑菇街的这种方案。蘑菇街 App 的组件化之路
2. 中间者架构,比如casatwy的方案。casatwy关于蘑菇街组件化的讨论

我们来总结一下目前的方案
蘑菇街方案-基于URL和协议
1)通过URL传递简单参数(组件间简单参数调用)
2)通过协议调用传递复杂参数(组件间复杂参数调用)
缺点:
1)页面间调用不需要URL形式,对于复杂参数,组件间调用通过URL无法满足需求。
2)注册URL时充分不必要条件,完全可以用runtime来解决这个问题。
3)使用多种方案,不利于管理和维护。
4)protocol主要存在的问题就是分散调用导致耦合。
5)需要组件向ModuleManager注册Url(因为URL调用时通过注册时的callBack来实现的,不是基于runtime,所以需要注册),会导致浪费内存。

casatwy的方案-基于Category和Target-Action
主要是基于Mediator模式和Target-Action模式,中间采用了runtime来完成调用。通过mediator的Category来输出组件的对外调用方法。使用同一种方案,实现组件间调用。
优点:
1)不需要注册URL
2)使用同一种方案,基于Target-Action模式实现组件间的调用。
3)区分app内部调用和外部调用。
4)同一种方法可以实现简单参数和复杂参数的调用。

我们的方案-基于URL和Target-Action
利用runtime实现Target-Action模式设计,通过定义URL协议确定Target和Action,通过params来传递所有页面间调用的参数,error返回调用的错误信息,completion来实现调用后的回调。类似以下形式
组件调用方式:[XXMediator openURL:@"mediator://Target/Action" arg:params error:error completion:callBack]
组件输出调用方法:每个组件有一个XXModule的类,在该类中实现对外输出的方法,提供XXMediator中Target和Action。类的头文件中包含组件可以调用的类以及需要传递的参数。

优点:
1)一种调用方式,可以实现简单和复杂参数调用。
2)不需要注册,调用简单
3)所有调用使用同一个方法实现,只需要引用Mediator,不需要引用Mediator 的category。
4)通过URL实现Target-Action,可以利用URL规则解析出Target和Action,实现调用。

2.版本管理

版本管理使用 cocoapods,每个组件都拆成独立的pod库,并生成一个配置表,来进行组件间的依赖组件的版本管理,具体内容这里就不叙述了。

三、组件化遇到问题

1.使用Target-Action方式进行调用,有个问题就是runtime的时候,如果对应Target-Action修改了,怎么提示调用方
1)静态检测URL,判断Target-Action是否存在。
2)动态调用router,debug模式下,Target-Action不存在就crash。

2.调用方如何知道接收方需要哪些key的参数?调用方如何知道有哪些target可以被调用?
1)category方式下,可以直接通过category中的方法来进行确认。
2)我们的方案中,每个组件的对应moudle类中,类的头文件中包含组件可以调用的类以及需要传递的参数。

3.调用参数解析处理在那里比较好?
各组件内部,因为这些参数的使用,各组件开发者自己最清楚。如果在category解析,Mediator中会参杂业务逻辑。

4.A调用B时,如果B要回传参数给,怎么做?
通过callBackBlock回调回传,参数是id类型,可以传任意对象,比如是一个UIViewController或者一个NSDictionary都可以。

四.组件化的缺点:

1.会增加开发者的学习成本
2.组件拆分颗粒度把握不好,会产生很多中间代码和冗余。
3.图片资源管理不好,会产生很多冗余图片。
4.组件化过程中,会带来一些组件之间的调试问题,前期会影响团队效率。

总结:

组件化是一把双刃剑,如果在工程规模较小的时候,进行组件化,可能反而会影响团队开发效率,带来一些问题,比如上面提到的缺点,只是在工程和团队达到一定规模的时候,进行组件化才会有更大的收益。

参考资料:
蘑菇街 App 的组件化之路
iOS应用架构谈 组件化方案
蘑菇街 App 的组件化之路·续
iOS 组件化方案探索
iOS组件化方案 - MrPeak杂货铺
京东iOS客户端组件管理实践 - InfoQ

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353