2022年,学点技术管理(十八)

140 阅读5分钟

每个工程师都应该了解的:API 的设计和实现。

API 的签名(Signature)

API 的签名,或者叫协议,是指 API请求(Request)和响应(Response)支持哪些格式和什么样的参数。

API 签名的设计初期,一定要经过反复推敲,尽量避免上线后的改动。

除了一些基本的 RESTful 原则外,签名的定义很多时候是对业务逻辑的抽象过程。一个系统的业务逻辑可能错综复杂,因此 API 设计的时候,就应该做到用最简洁直观的格式去支持所有的需求。

这往往是 API 设计中相对立的两面,我们需要找到平衡:

  • 有时候为了支持某一个功能,似乎不得不增加一个很违反设计的接口;
  • 有时候我们为了保证 API 绝对规范,又不得不放弃对某一些功能的直接支持,这些功能就只能通过迭代调用或客户端预处理的方式来实现。

这种设计上的取舍,通常会列出所有可行的方案,从简单的设计到繁杂的设计;然后通过分析各种使用实例的频率和使用某种设计时的复杂度,从实际的系统需求入手,尽可能让常用的功能得到最简单直接的支持;还要一定程度上 “牺牲” 一些极少用到的功能,反复考虑系统使用场景,尽可能获得一个合理的折衷方案。

API 设计原则

  1. 保证 API 100% RESTful

    RESTful 的核心是:所有行为(Action)和接口,都应该是相应 Resource 上的增删改查(CRUD)操作。

  2. 在请求和响应中,应该尽可能地保持参数的结构化。

    如果是一个哈希(hash),就传一个哈希(不要传 hash.to_string)。API 的序列化和反序列化机制(Serialization / Deserialization)会将其自动序列化成字符串。

  3. 认证(Authentication)和安全(Security)的考虑。

    安全的考虑始终应该放在首位,保证对特定的用户永远只暴露相关的接口和权限。可以使用证书和白名单,也可以通过用户登陆的证书(Credentials)生成的验证票据(Token),或者 Session / Cookie 等方式来处理。此外,所有的 API 层的日志(Logging),要保证不记录任何敏感的信息。

  4. API 本身应该是客户端无关的。

    一个 API 对请求的处理尽可能避免对客户端是移动端还是网页端的考虑。客户端相关的响应格式,不应该在 API 中实现。所有的客户端无关的计算和处理,要尽可能在服务器(Server)端统一处理,以提高性能和一致性。

  5. 尽可能让 API 是幂等(Idempotent)的。

    同一个请求发一遍和发两遍是不是能够保证结果相同?请求失败后重发和第一次发是不是能保证相同结果?

    当然,要不要做成幂等,具体的实现还要看具体的应用场景。

使用现有编程语言的 API 框架

每个语言都已经提供了很好的 API 框架,你需要在设计前先多了解这些框架。

  1. 对访问权限的统一控制;
  2. 自动测试的支持;
  3. 对请求和响应的格式,以及序列化和反序列化的支持;
  4. 对日志和日志过滤(Logging Filtering)的支持;
  5. 对自动文档生成的支持;
  6. 对架构以及性能的影响。

设计中的平衡

  1. 自由总是相对的。

    一个小的创业公司里,API 怎么设计,代码怎么写,几个人一协商,达成共识,并不需要那么多的条条框框,也照样行的通。

    公司越大,代码协作的人越多,个人的自由就会在设计和实现中产生问题,并导致最终的冲突。所以,很多大公司会制定一些 API 的最佳实践,强制要求设计和实现中必须按照某种模式来做。

  2. 为当前设计,还是为未来设计?

    要考虑未来的场景,在设计时留有余地,但永远只实现当前产品真正要用的功能。

  3. 可维护性和效率(Maintainability v.s. Efficiency)。

    设计和实现里常常会有一些封装和抽象的概念。某些特殊情况下,封装再分拆的过程可能会在一定程度上影响 API 的响应速度,或者代码质量的优化和性能的优化上有冲突。

    这个很难一概而论,具体的做法要看代码是否在关键路径上,或者这段代码是不是需要多人协作等等。最终的选择就要具体问题具体分析了。

  4. 是否采用 AOP。

    AOP 的理念是从主关注点中分离出横切关注点。

    分离关注点使得解决特定领域问题的代码从业务逻辑中独立出来,业务逻辑的代码中不再含有针对特定领域问题代码的调用,业务逻辑同特定领域问题的关系通过侧面来封装、维护,这样原本分散在整个应用程序中的变动就可以很好地管理起来。

    因为 API 的设计和实现中有很多通用的关注点,如日志(Logging)、解析(Parsing)、监控(Monitoring)等等,所以 API 成了 AOP 一个很自然的应用领域。

    • 优势:代码的重用性,规整性,以及程序员可以集中关注于系统的核心业务逻辑等。
    • 问题:代码的剖析(Profiling)和调试(Debugging)困难增加,对程序员的相关经验有更多要求,相互协作的要求也增强了,比如改变某一个功能可能会影响到其它的功能,等等。

    是否选择使用 AOP,和你的需求场景,人员技能和设计复杂度息息相关,需要技术决策者根据具体环境做出判断。