关于iOS项目组件化的思考(一)
一、前言
关于本次对组件化的思考,更多的属于探究,因为我很清晰这件事情的必要性,但受当前能力及当前项目结构的局限,需要探究出完善且适用于我们项目的方案。下面的例图通通已微信为例。
二、问题简要
- Q1:随着项目工程日益壮大,编译速度越来越慢!
- Q2:各个业务功能模块耦合越来越严重!
- Q3:整个项目的稳定性越来越不可控!

三、组件化到底是什么?
我们都知道最基本的代码设计原则:“Don’t repeat yourself!”
项目组件化,顾名思义,就是将项目中的各个模块按照基础组建,功能组件,业务组件划分成一个个单独的模块,以使得各个模块间可以单独开发、测试、组合运行。
我们要的效果是这样:

我们常用CocoaPods来管理那些优秀的第三方库,其实,组件化后的各个业务模块也可以打包成pods item,交由CocoaPods管理,项目成员每人管理一个pods item,宿主工程持有所有的pods item,打包App时,先pod update,获取到每个人的最新代码,然后打包。如此,同样的功能模块如果实现了自完备性,就可以在多个app中复用,这也是我想要的。

中间组件会包含各类路由等管理、API等

解决的问题:
- 每个组件可以独立运行,减少编译时间
- 最大限度解耦,组件间的通讯交由中间组件
- 代码业务逻辑完整且独立
- 每个人更能专业于自己负责的模块或功能
四、我们应该从何做起?
- 越底层的模块,应该越稳定,越抽象,越具有高复用度。
- 公共模块下沉
- A模块不要依赖任何B模块的代码,通过接口等方式取代
项目中,比如,朋友圈、通讯录、聊天界面,我们点击某人,要跳入此人的详情页,假设个人详情页名为UserInfoDetailPageVC,此时,所有想跳入此页面的地方都要写:
UserInfoDetailPageVC *detailVC = [UserInfoDetailPageVC alloc] init];
detailVC.userId = targetId;
[self.navigationController pushViewController:detailVC animated:YES];
我要说的是,其他模块就不应该知道UserInfoDetailPageVC这个类的存在,为什么?因为他们相互独立,这里就要用到上述的路由,我们只需用注册相关的URL和相关参数。参见JLRoutes的用法。当然也有其他办法,但一定是不能让A模块直接访问B模块。
对于下沉的公共模块,不能有任何业务逻辑,一丁点都不要,如果必须加入业务逻辑,那就不要把它下沉到基础模块,所有要求我们,越是底层的模块,就要越抽象,清晰每一层的职责。
在组件化的过程中,我们不需要说立马就开始引入各种库,也不需要直接各自pods化,但我们至少要先分出清晰的目录结构,尝试的编写各个模块应该暴露出的API,放入各自可以被访问的唯一头文件,尽管其他文件也能被访问到,但我们可以先通过制度来约束,只能访问知道的头文件。我想,这是第一步(如果是新工程就不用这样了,直接建立各个模块的私有仓库,CocoaPods用起来就好了)。
五、写在最后
这里也会有一些问题,工具的使用成本,团队间和模块间的配合成本升高,开发效率短期会降低。但是从长期的影响来说,带来的好处远大于坏处的,因此模块化仍然是最佳的架构选择。