为什么要实现模块化
通过解耦模块实现快速编译、代码隔离、多小组开发、功能隔离。
快速编译
分离模块后,可以对每个模块单独编译成Framework,以此缩短主工程的编译时间。
依赖关系从上到下依次依赖,下层不依赖上层。
【缺少图例】
代码隔离
模块化的结果是每个业务模块不知道其它模块的存在,只在胶水层知道可以调用的接口。这样,调用其它模块的业务由胶水层执行,具体执行结果可能有返回值检查也可能并不关心。
分组开发
大中型项目中,常常会有不同的开发小组,或者来自同一部门,或者来自不同部门,甚至是其它公司,此时项目的划分就非常有必要。模块化下,每个小组负责不同的模块,可以保证开发的高效。
更好的远程配置
由于项目模块化了,服务器下发的远程配置能够更方法快捷的实现。
项目实践
在最近的项目模块化实践中,采用了CTMediator的方案。一个由OC作为胶水层的方案,缺点非常明显,就是对Swift支持太过于匮乏。
最终结构
最终结构应该分为三层。最上层为业务层,这一层模块之间的交互依赖于第二层的胶水层,第一层的模块(业务模块)之间是不会互相引用的。最下层为基础组件,为上层业务提供必需的、可选的功能,例如网络模块。在这三层中,上层可以随意依赖下层,但不能依赖上层或者同层模块。
分步治理
由于是在已有的项目上进行重构去实现模块化,老代码之间的耦合过于严重,不能在短时间内分离完毕,所以需要分布治理。
在分离模块期间,需要在原有三层结构中加入一层,泥球层。泥球层位于第二层,所有未分离的模块放入泥球层中,在未来治理过程中会逐步减少直至移除泥球层。
问题总汇
OC胶水层
问题:由于胶水层的原理是利用OC的反射来做的,所以纯Swift是不支持的,没法在模块间传递纯Swift对象。
方案:对于纯Swift对象,目前采用转化为Data进行传递的方式,在日后治理完泥球层后改用更合适的方案。
模块间模型/协议互通
问题:多个模块间用到的相同的模型/协议怎么才能在模块间正确使用
方案:按照模块化之间不互相依赖的原则,所有模块用到的模型都应该是自己的,所以将出现在多个模块中的模型分别复制到需要使用到模型中,数据传递时直接传递序列化到数据。而协议则特殊,需要放在胶水层中。
混淆
问题:由于胶水层的反射是使用字符串的,所以混淆后能否正确调用需要处理。
方案:暂无。
版本与签名
问题:模块化后,所有的模块需要自己管理版本,并且要保证签名与主工程一致。
方案:版本由Cocoapods管理,所有的流程通过CI/CD配置。
泥球治理
泥球治理是一个长期任务,需要各个业务团队的配合。
规划设计
首先需要架构团队在泥球内划分出不同的业务模块,然后将模块任务分配给应该接收的团队。
新的库类引用
对于新的引用,原则上不允许业务团队自己引入,需要架构团队配合。
主动识别
架构团队主动清理可以放入公共/基础模块的代码。
被动认领
当业务团队需要改动泥球层的代码时,需要将代码拿回自己的模块。如果其它模块因此报错,需要报错模块的团队将这份代码拷贝回自己的模块。