UNKO.fun

Blog Post

组件化实践

October 27, 2019 | 3 min

iOS

Post content

为什么要实现模块化

通过解耦模块实现快速编译、代码隔离、多小组开发、功能隔离。

快速编译

分离模块后,可以对每个模块单独编译成Framework,以此缩短主工程的编译时间。

依赖关系从上到下依次依赖,下层不依赖上层。

【缺少图例】

代码隔离

模块化的结果是每个业务模块不知道其它模块的存在,只在胶水层知道可以调用的接口。这样,调用其它模块的业务由胶水层执行,具体执行结果可能有返回值检查也可能并不关心。

分组开发

大中型项目中,常常会有不同的开发小组,或者来自同一部门,或者来自不同部门,甚至是其它公司,此时项目的划分就非常有必要。模块化下,每个小组负责不同的模块,可以保证开发的高效。

更好的远程配置

由于项目模块化了,服务器下发的远程配置能够更方法快捷的实现。

项目实践

在最近的项目模块化实践中,采用了CTMediator的方案。一个由OC作为胶水层的方案,缺点非常明显,就是对Swift支持太过于匮乏。

最终结构

最终结构应该分为三层。最上层为业务层,这一层模块之间的交互依赖于第二层的胶水层,第一层的模块(业务模块)之间是不会互相引用的。最下层为基础组件,为上层业务提供必需的、可选的功能,例如网络模块。在这三层中,上层可以随意依赖下层,但不能依赖上层或者同层模块。

分步治理

由于是在已有的项目上进行重构去实现模块化,老代码之间的耦合过于严重,不能在短时间内分离完毕,所以需要分布治理。

在分离模块期间,需要在原有三层结构中加入一层,泥球层。泥球层位于第二层,所有未分离的模块放入泥球层中,在未来治理过程中会逐步减少直至移除泥球层。

问题总汇

OC胶水层

问题:由于胶水层的原理是利用OC的反射来做的,所以纯Swift是不支持的,没法在模块间传递纯Swift对象。

方案:对于纯Swift对象,目前采用转化为Data进行传递的方式,在日后治理完泥球层后改用更合适的方案。

模块间模型/协议互通

问题:多个模块间用到的相同的模型/协议怎么才能在模块间正确使用

方案:按照模块化之间不互相依赖的原则,所有模块用到的模型都应该是自己的,所以将出现在多个模块中的模型分别复制到需要使用到模型中,数据传递时直接传递序列化到数据。而协议则特殊,需要放在胶水层中。

混淆

问题:由于胶水层的反射是使用字符串的,所以混淆后能否正确调用需要处理。

方案:暂无。

版本与签名

问题:模块化后,所有的模块需要自己管理版本,并且要保证签名与主工程一致。

方案:版本由Cocoapods管理,所有的流程通过CI/CD配置。

泥球治理

泥球治理是一个长期任务,需要各个业务团队的配合。

规划设计

首先需要架构团队在泥球内划分出不同的业务模块,然后将模块任务分配给应该接收的团队。

新的库类引用

对于新的引用,原则上不允许业务团队自己引入,需要架构团队配合。

主动识别

架构团队主动清理可以放入公共/基础模块的代码。

被动认领

当业务团队需要改动泥球层的代码时,需要将代码拿回自己的模块。如果其它模块因此报错,需要报错模块的团队将这份代码拷贝回自己的模块。