每个工程师都应该了解的:API 的设计和实现。
API 的签名(Signature)
API 的签名,或者叫协议,是指 API请求(Request)和响应(Response)支持哪些格式和什么样的参数。
API 签名的设计初期,一定要经过反复推敲,尽量避免上线后的改动。
除了一些基本的 RESTful 原则外,签名的定义很多时候是对业务逻辑的抽象过程。一个系统的业务逻辑可能错综复杂,因此 API 设计的时候,就应该做到用最简洁直观的格式去支持所有的需求。
这往往是 API 设计中相对立的两面,我们需要找到平衡:
- 有时候为了支持某一个功能,似乎不得不增加一个很违反设计的接口;
- 有时候我们为了保证
API绝对规范,又不得不放弃对某一些功能的直接支持,这些功能就只能通过迭代调用或客户端预处理的方式来实现。
这种设计上的取舍,通常会列出所有可行的方案,从简单的设计到繁杂的设计;然后通过分析各种使用实例的频率和使用某种设计时的复杂度,从实际的系统需求入手,尽可能让常用的功能得到最简单直接的支持;还要一定程度上 “牺牲” 一些极少用到的功能,反复考虑系统使用场景,尽可能获得一个合理的折衷方案。
API 设计原则
-
保证
API100%RESTful。RESTful的核心是:所有行为(Action)和接口,都应该是相应Resource上的增删改查(CRUD)操作。 -
在请求和响应中,应该尽可能地保持参数的结构化。
如果是一个哈希(
hash),就传一个哈希(不要传hash.to_string)。API的序列化和反序列化机制(Serialization/Deserialization)会将其自动序列化成字符串。 -
认证(
Authentication)和安全(Security)的考虑。安全的考虑始终应该放在首位,保证对特定的用户永远只暴露相关的接口和权限。可以使用证书和白名单,也可以通过用户登陆的证书(
Credentials)生成的验证票据(Token),或者Session/Cookie等方式来处理。此外,所有的API层的日志(Logging),要保证不记录任何敏感的信息。 -
API本身应该是客户端无关的。一个
API对请求的处理尽可能避免对客户端是移动端还是网页端的考虑。客户端相关的响应格式,不应该在API中实现。所有的客户端无关的计算和处理,要尽可能在服务器(Server)端统一处理,以提高性能和一致性。 -
尽可能让
API是幂等(Idempotent)的。同一个请求发一遍和发两遍是不是能够保证结果相同?请求失败后重发和第一次发是不是能保证相同结果?
当然,要不要做成幂等,具体的实现还要看具体的应用场景。
使用现有编程语言的 API 框架
每个语言都已经提供了很好的 API 框架,你需要在设计前先多了解这些框架。
- 对访问权限的统一控制;
- 自动测试的支持;
- 对请求和响应的格式,以及序列化和反序列化的支持;
- 对日志和日志过滤(
Logging Filtering)的支持; - 对自动文档生成的支持;
- 对架构以及性能的影响。
设计中的平衡
-
自由总是相对的。
一个小的创业公司里,
API怎么设计,代码怎么写,几个人一协商,达成共识,并不需要那么多的条条框框,也照样行的通。公司越大,代码协作的人越多,个人的自由就会在设计和实现中产生问题,并导致最终的冲突。所以,很多大公司会制定一些
API的最佳实践,强制要求设计和实现中必须按照某种模式来做。 -
为当前设计,还是为未来设计?
要考虑未来的场景,在设计时留有余地,但永远只实现当前产品真正要用的功能。
-
可维护性和效率(Maintainability v.s. Efficiency)。
设计和实现里常常会有一些封装和抽象的概念。某些特殊情况下,封装再分拆的过程可能会在一定程度上影响
API的响应速度,或者代码质量的优化和性能的优化上有冲突。这个很难一概而论,具体的做法要看代码是否在关键路径上,或者这段代码是不是需要多人协作等等。最终的选择就要具体问题具体分析了。
-
是否采用 AOP。
AOP的理念是从主关注点中分离出横切关注点。分离关注点使得解决特定领域问题的代码从业务逻辑中独立出来,业务逻辑的代码中不再含有针对特定领域问题代码的调用,业务逻辑同特定领域问题的关系通过侧面来封装、维护,这样原本分散在整个应用程序中的变动就可以很好地管理起来。
因为
API的设计和实现中有很多通用的关注点,如日志(Logging)、解析(Parsing)、监控(Monitoring)等等,所以API成了AOP一个很自然的应用领域。- 优势:代码的重用性,规整性,以及程序员可以集中关注于系统的核心业务逻辑等。
- 问题:代码的剖析(
Profiling)和调试(Debugging)困难增加,对程序员的相关经验有更多要求,相互协作的要求也增强了,比如改变某一个功能可能会影响到其它的功能,等等。
是否选择使用
AOP,和你的需求场景,人员技能和设计复杂度息息相关,需要技术决策者根据具体环境做出判断。