如何设计一个良好的 API 接口?
标准化
标准化的关键在于,尽可能少地创建自定义规范和机制,而是遵守业内通用的规范和标准。
一个非常好的案例是 RESTful API。
如果存在多个资源组合的情况怎么办?
可以引入子资源的概念。
例如,查看用户编码为 1001 的用户的权限信息。
[GET] /v1/users/1001/roles/101
资源变化情况难以用标准 RESTful API 来命名怎么办?
可以用一些特殊的 actions 来命名,例如密码修改接口。
[PUT] /v1/users/1001/password/actions/modify
异常响应格式
兼容性
接口不能向下兼容,业务就会收到很大影响。
兼容性问题可能有:
- 多端(安卓、IOS、PC、Pad 等)之间的接口兼容性,版本兼容性
- 服务端不停机升级,由于 API 不兼容导致的服务故障
- ...
引入版本概念就可以解决这些问题。
抽象性
接口抽象都基于业务需求。
因此,我们一方面要定义出清晰的业务问题域模型(如数据模型、领域模型等),并建立起某个问题的现实映射,这样有利于拉起不同角色对于 API 设计认知上的统一。
另一方面,API 的抽象性,就可以很好地屏蔽具体的业务实现细节。为我们提供更好的可拓展性。
简单性
遵守“最少知识原则”。
即,客户端不需要知道太多服务的 API 接口和这些 API 接口的调用细节。
参考设计模式中的外观模式和中介者模式。
高性能
上面说到的外观接口虽然保证了简单性,但是也有缺陷:
- 增加了服务端的业务复杂度。
- 多个服务之间的聚合,导致接口性能比较差。
- 入参字端的各种组合,可能会导致数据库的性能问题。
针对上面的第 3 点,举个例子,查询场景下,暴露了过多的字段给外部组合使用,但是数据库没有相应的缩印,就会发生全表扫描。
所以,我们可以只提供存在索引的字段组合,给外部调用。
Result<Void> agree(Long taskId, Long caseId, Configger configger)
上面要求用户必填taskId
和caseId
来保证数据库合理使用索引。