iOS工程模块化
iOS工程模块化
1. 模块化的初衷
现在的开发环境跟以前不一样了, 在全社会日积月累地进行开发后,趋向于无限多的轮子被造了出来, 而一个工程中, 混合使用的技术栈, 也变得丰富, 跨平台技术日新月异.
Native、Web、React Native、Weex、Flutter等等的框架让一个项目在什么都有一点后变得越来越脆弱.一个依赖如果同时被多个功能耦合使用, 那么它的改动将影响很大, 并且需要让依赖它的功能都进行响应的测试, 以验证修改的可用性.
要减少这些依赖导致的脆弱性, 即使这些规范是日常开发中不会随意变动的, 但难免有些赶鸭子上架的时候被开发者思考不周地进行修改的情况, 就要制定足够的规范.
同样地, 如果规范过多, 也会限制开发中的效率, 所以为了能减少这种情况, 可以回归到模块的本身来, 即对一个模块的输入与输出.
模块在遵循设计原则的基础后, 是不需要理会外部的调用情况的, 那么对于内部, 只要执行正常, 即正确的输入有正确的输出, 那么内部到底是什么, 不需要更多的关注.
但iOS工程接入很多的模块后, 可以明显感觉集成时间、编译时间的上升, 后续的还有调试艰难等问题, 这些都是模块化需要解决的问题, 而不仅仅是封装一个又一个的库.
2. 模块化的样子
很多事物只要量一大, 一些原本不需要考虑的事情都变得重要, 可能是一个项目的健壮性、可维护性, 也可能是开发调试的效率, 也可以是迭代功能的周期变长等.
综合考虑项目的模块化情况, 一个项目该拥有的模块管理相关情况包括但不限于以下几点:
- 无耦合、易于集中管理的模块调度工具
- 清晰的自下而上的模块调用层次
- 易于集成、方便调试的工具
对于这几点来说, 目前的解法如下:
- 两个解偶的依赖
- 各模块的使用依赖整理后封装
- 通过CocoaPods配置管理的插件.
3. 模块化的实践
3.1 依赖
Zouter, 是一个在CTMediator的基础上增加功能的项目依赖, 通过优先级排序和集中管理来调度所需模块.
Zodifier, 是一个属性修改器, 相关对象在初始化时配置好需要修改的属性, 在变动后, 立即生效, 摆脱了通知导致的数据不同步问题.
3.2 模块层次
各模块的层级, 按照相互关系与设计原则规划.
3.3 CocoaPods插件
CocoaPods, 是市面上大部分iOS项目使用的集成依赖的工具, 它提供可自定义的插件使用, 所以直接通过CocoaPods插件来管理这些依赖在模块化后的集成时间、编译时间、调试难题是个不错的解法.
这里记录一下开发CocoaPods插件的思路和遇到的坑.
- CocoaPods插件的开发调试
- iOS中的动态库和静态库本质
- CocoaPods对依赖的管理流程
- 模块化二进制化的思路与坑
- 二进制集成, 源码集成的原理
3.4 二进制模块的后台服务
因为这里的方案是将二进制的Pod放到静态服务器中, 考虑到移植性和通用性, 将静态服务器部署到OCI容器中.
由于Docker
的背刺, 选择了Podman
来管理镜像和容器, 但其实除了守护进程外, 没有啥区别.
3.5 总仓库
Zource是这一切的仓库, 经历了3次迭代重构, 终于可以在商用App上使用了.
该插件与美团的ZSource
对比, 还欠缺集成二进制依赖时查看源码这个能力.
但已经完善了单项目单配置的能力, 每个项目, 都可以单独配置一份自己的静态私有依赖库, 无论是自己私人集成, 还是团队集成, 都能做到互不干扰.