2. 架构设计原则与模式
做SDK集成,说白了就是在别人的地盘上跳舞。你的代码要进入宿主App的进程空间,跟人家的主线程、内存管理、网络栈朝夕相处。这里头稍微犯点错,轻则功能异常,重则整App闪退。
我个人习惯,在动手写第一行代码之前,先把几个核心设计原则刻在脑子里。这些原则不是理论空谈,它们能直接帮你避开线上事故。
2.1 四大核心设计原则
我总结了四个必须遵守的原则,这也是我在十几个商业级SDK项目里踩坑踩出来的。
| 原则 | 核心思想 | 我吃过的亏 |
|---|---|---|
| 高内聚低耦合 | SDK内部逻辑自成一体,对外暴露最小接口 | 曾经把所有工具类扔到一个模块,改一个地方全盘重编 |
| 接口隔离 | 宿主调用方不用依赖它不需要的方法 | 早期我设计了一堆万能初始化接口,结果没人用得了 |
| 依赖倒置 | 高层模块不依赖低层实现,双方依赖抽象 | 硬编码网络库,换一个库要改半个SDK |
| 开闭原则 | 对扩展开放,对修改封闭 | 加一个新渠道要改核心类,上线前总是提心吊胆 |
核心要点:这些原则不是摆设。你在设计SDK模块边界时,每多一份对外暴露,就多一份维护负担。能私有的就别公开,能抽象的别写死。
2.2 分层架构设计
分层是SDK最经典的架构模式。我参与的几乎每个项目都采用了类似的分层方式,只是层数多少、粒度粗细的区别。
为什么一定要分层?你想想看,如果所有代码搅在一起,接口层、业务层、底层实现全部揉成一个胖模块。改一个底层缓存策略,结果接口层的返回格式变了,宿主编译直接报错。这是典型的耦合灾难。
我推荐的三层结构:
- 接口层(API Layer) — 对宿主暴露的门面。稳定、简洁、版本化。
- 业务层(Business Layer) — 核心逻辑编排。调用底层能力,组合成业务功能。
- 基础层(Foundation Layer) — 网络、存储、线程、日志等基础设施。
我在某金融服务SDK里遇到过一件事。业务层直接依赖了一个第三方网络库的某个类。后来对方升级了库,改了类名。全线编译失败。这就是依赖方向反了。正确做法是:业务层依赖接口层定义的抽象,基础层去实现这个抽象。
实用技巧:接口层的每个公开方法,都应该能独立测试。如果某个方法需要事先调用三个其他方法才能用,说明接口设计有问题。我习惯用"宿主视角"写接口:只写调用方真正需要的,不多不少。
2.3 插件化架构模式
插件化不是游戏SDK的专利。我最近几年做的大中型SDK,基本都采用了插件化思路。核心SDK保持轻量,各种扩展能力以插件形式动态加载。
为什么?因为宿主App有包体积限制、有合规审核、有动态升级需求。把所有功能都打进一个aar里,既不现实,也不专业。
插件化架构的几个关键要素:
- SPI机制(Service Provider Interface)— 定义插件接口,运行时通过反射或注册表发现实现。
- 生命周期管理 — 插件的加载、初始化、销毁必须由主SDK统一管控。
- 失败隔离 — 某个插件崩溃,不能拖垮主SDK,更不能让宿主App闪退。
我记得有一次在支付SDK中集成人脸识别插件。那个插件初始化时要加载几百兆的模型文件。如果在主线程加载,宿主App直接ANR。后来我们在插件加载器里加了线程切换和超时保护。嗯,这就是架构设计带来的工程价值。
避坑指南:我曾经见过某个SDK的插件化方案,插件之间居然能直接调用对方的内部类。这完全违背了隔离初衷。插件之间只能通过SPI接口通信,任何直接引用都应该视为架构腐化。
2.4 模块化与组件化
模块化是按功能边界拆包,组件化是按可复用粒度拆包。两者不冲突,但你要先搞清楚自己的场景。
我一般这样区分:
| 维度 | 模块化 | 组件化 |
|---|---|---|
| 目的 | 降低耦合、分离关注点 | 提高复用、独立演进 |
| 粒度 | 偏大(登录、支付、推送) | 偏小(网络库、图片加载、日志) |
| 依赖关系 | 单向依赖,禁止循环引用 | 可被多个上层模块依赖 |
| 版本管理 | 统一版本号 | 独立版本号 + 兼容契约 |
说白了,模块化解决的是"不要搅成一锅粥",组件化解决的是"这块代码能不能拿给下一个项目用"。我建议新手先从模块化入手,等你的SDK规模膨胀到一定程度,再拆组件。别一开始就过度设计。
2.5 架构设计的核心逻辑图
下面这张图,是我在做架构设计时经常画给团队看的。它把分层、模块、插件整合到一个视图中,反映了SDK内部的核心流动方向。
你看,这张图展示了三个层次之间的依赖方向。接口层依赖业务层的抽象。业务层依赖基础层的抽象。基础层提供具体实现。箭头方向就是依赖方向。这刚好体现了依赖倒置原则——高层不直接依赖低层的细节。
2.6 架构设计的持续进化
没有一劳永逸的架构设计。我做过的几个SDK,几乎每年都要做一次架构盘点。为什么?因为业务在变,宿主环境在变,第三方依赖在变。
我一般用这几条标准来判断架构是否需要调整:
- 加一个新功能,需要改动三个以上模块吗?
- 升级一个依赖库,编译错误超过5处吗?
- 单元测试覆盖率低于40%吗?
- 新人接手,需要一周以上才能看懂调用链路吗?
如果任意一条命中,说明架构出现腐化信号。该重构就重构,别等到线上出事故再动手。
我的习惯:每次迭代都留20%的工时给架构优化。不是大改,而是持续的小重构。比如今天抽一个接口,明天解一个循环依赖。这样做,架构不会突然崩塌。
总结一句话:架构设计的本质,是管理复杂度。分层、模块化、插件化、接口隔离——所有这些模式,最终目的都是让你的SDK在宿主App里能稳定、高效、优雅地运行。嗯,想清楚这一点,设计原则就不再是死记硬背的知识点,而是你手里的工程工具。