SDK 整体架构设计原则

做 SDK 的第一件事,不是写代码,而是想清楚怎么“切”。
说白了,就是把一个庞然大物,切成小模块,再让它们互相配合。
我做了快十年 SDK,踩过的坑一半都跟架构有关。
今天聊聊三个最核心的原则:模块分层、依赖倒置、接口隔离。

模块分层

分层是我见过最直观的武器。
把 SDK 分成几层,上层只管调用,下层只管干活。
比如网络层、业务层、UI 层,各管各的。

为什么要分层?
因为不分层,代码就会变成一团乱麻。
改动一个地方,牵扯三个模块,你怕不怕?

我在项目中遇到过一个真实场景:
有个支付 SDK 没有分层,业务逻辑和网络请求混在一起。
后来换了一家三方支付,结果改了半个月,还修了一堆 bug。
如果当时分了层,换底层实现根本不用碰业务代码。

来看一个典型的分层示例:

层次 职责 典型类/接口
表现层 对外暴露 API,处理入参出参 PublicApi
业务层 核心逻辑,状态机,流程编排 PaymentService
数据层 网络请求、本地缓存、文件读写 HttpClient, CacheManager
基础设施层 日志、线程池、加密 Logger, ThreadPool
我曾经犯过一个错: 把加密工具类直接放在业务层里,结果业务层和基础设施层耦合死了。后来想换加密算法,业务层也得跟着改。记住:所有跨层调用必须通过接口,不要直接 new 具体类。

依赖倒置

依赖倒置原则说:要依赖抽象,不要依赖具体实现。
你想想看,底层实现换了,上层代码要不要跟着改?
不该。

怎么做到?
上层定义接口,下层实现接口。
上层只管说“我要一个存储服务”,下层把文件存到本地还是云端,上层不管。

代码更容易看懂:

// 错误 demo:上层依赖具体实现
class UserService {
    private FileStorage storage = new FileStorage(); // 耦合死了!
}

// 正确 demo:依赖接口
interface IStorage {
    void save(String key, byte[] data);
    byte[] load(String key);
}

class UserService {
    private IStorage storage; // 通过构造器注入
    public UserService(IStorage storage) {
        this.storage = storage;
    }
}
我个人习惯: 每个模块对外只暴露接口,内部实现藏起来。这样既能做单元测试(Mock 接口),又能保证替换实现时不动其他模块。

接口隔离

接口隔离说白了就是:别让调用方看见它不需要的东西。
一个臃肿的接口,调用方用不上,却还得依赖它,改接口时所有实现类都爆炸。

举个例子:
一个认证模块,只提供 login()、logout() 就够了。
如果你把 sendSms()、verifyCaptcha() 也塞进去,那所有依赖认证模块的调用方,都被迫跟着变。

正确的做法:拆成细粒度小接口。
每个调用方只依赖自己需要的那一块。

反例(胖接口) 正例(隔离接口)
AuthService { login, logout, sendSms, verifyCaptcha, resetPassword } ILogin { login }
ILogout { logout }
ISms { sendSms }
所有调用方全依赖同一个大接口 每个调用方只依赖自己需要的接口
修改接口影响范围大 修改某个接口不影响其他调用方
避坑指南: 接口不是越多越好,而是“刚好够用”。我以前在一个项目里把接口拆得太碎,每个类只有一个方法…结果调用方需要组合多个接口才能完成一个操作,反而更麻烦。适度隔离,看场景。

三个原则的关系

模块分层是骨架,依赖倒置是肌肉,接口隔离是表皮。
骨、肉、皮缺一不可。
下面这张图展示了它们如何相互配合:

SDK 架构三大原则关系图 SDK 架构三大原则 表现层 (Public API) 业务层 (Core Logic) 基础设施层 (Infra) 接口(抽象) 实现类 A 实现类 B ILogin ILogout IStorage ICache 层次之间通过接口依赖 每个接口功能单一、隔离

这张图里:
左侧是分层结构,从上到下调用;
中间是依赖倒置,两层之间的调用通过接口实现,而非直接依赖具体类;
右侧是接口隔离,每个接口只暴露最少的方法。

记住一句话: 好的 SDK 架构,改一行底层实现,上层代码一行都不用动。如果动了,说明你的分层、依赖、隔离还没到位。

其实这三个原则并不是孤立存在的。
模块分层提供了物理边界;依赖倒置保证了逻辑方向;接口隔离保证了接口粒度。
我在很多项目里发现,只要把这三条落实到位,后期维护成本至少降一半。

嗯,今天的内容就到这。
下次写代码前,先画张图,问自己:
分层了吗?依赖抽象了吗?接口够小了吗?
然后你会发现,bug 少了一半。