IOS可插拔业务模块化架构设计

1,355 阅读3分钟

引言:

在软件项目中如果有A,B,C...不同业务模块. 在缺乏良好架构设计的情况下,随着需求迭代不同模块与工程的耦合会越来越高. 本文以IOS平台为例,提出实现无侵入的增/删业务模块的架构设计方案. 其中一些思想和方案其他平台也可通用.

架构设计

我们从[垂直] 和[水平] 两个视角思考架构的设计,如下图:

image.png

垂直--分层 通用能力下沉

梳理各业务的公用依赖,将各业务所使用的如网络, 存储, 缓存,日志, Crash堆栈, 用户行为采集等通用能力下沉. 业务可以单向依赖基础支撑层的下沉模块. 基础支撑层可以再进行细分,由于本文主要讨论业务模块层的解藕设计,这里不展开.

水平--解藕 Event通讯

模块A B ...N可以相互调用. 应用可以随意移除某个模块,而且能保证应用还能正常运行(只是不具备该移除的业务).

选择1. 关于面向协议编程的方案

面向接口的协议式编程,业务抽象接口定义比较明确. 比如某模块A想替换为新的模块AA, 我们只要保证接口一致, 调用方(使用方)无需修改代码即可无痛的替换. 但是协议仍然是抽象的依赖, 而且无法避免交叉依赖情况. 当我们修改了接口的命名, 或者想完全移除某个模块, 就需要调用方配合修改. 如果代码分散在不同业务团队,由于跨部门的协调改动,处理编译依赖灯,其成本可能变得比较高.

选择2. 使用event,通过中介者进一步解藕

  1. 中介对象存储的角色和行为:
  • Event, 定义的Event Key
  • 订阅对象Target,动态创建不同的业务实体对象
  • 响应方法Action,方法调用
  1. 业务模块角色和行为:
  • 订阅其他模块Event subscribeEvent
  • 发布自身业务Event dispatchEvent
  • 处理自身的业务逻辑 handleEvent
    由于只依赖Event对象, 而不用引入具体的业务头文件,实现了解藕.
  1. 使用config文件实现业务的增删配置

中介者初始化时遍历config内文件, 创建业务的入口对象. 增删配置文件即可实现模块的动态增删.由于我们创建业务实体类是通过runtime机制, 即使移除业务也不会导致编译错误

其他

  1. 依赖和加载顺序问题 可以在配置文件内指定,通过代码按队列顺序加载.

  2. 性能提示
    避免在初始化时做一些耗时操作,以避免内存占用过大及影响应用冷启动速度.建议用lazyload方式加载真正耗费资源的业务对象.

  3. 关于协议编程 即使使用Event我们也需要将一些行为抽象为协议接口. 所不同的是此时的协议不是某个具体业务协议的定义, 而是事件分发加载状态等通用行为的定义.