永不过期的 API 密钥带来的问题
一个多年前签发、从未轮换、至今仍然有效的密钥并不是一种便利。它是一个多年来没有人真正检查过的隐患。
问一问为什么某个 API 返回嵌套的自定义对象模型,而不是简单扁平的 JSON 结构,诚实的答案很少是技术上的。专有结构并不会让查询更快或更准确。它让响应更难被替换,因为您的代码学会处理的每一个字段名、每一层嵌套、每一个自定义状态码,都是一小块内嵌在您应用中的特定供应商知识。
我们认为这是本末倒置。响应格式应该描述数据,而不是描述供应商。坐标、地址、偏移量和海拔,无论由谁来回答请求,都是相同的概念,因此为它们返回的结构应当与这些概念本身一样简单。这也是为什么我们有 17 个主机返回与另一家服务商自家 API 完全相同的响应结构:数据是我们的,但结构是您的代码可能早已理解的那种,因为这本来就不是该由我们去发明的结构。
专有格式还往往会积累各种怪异之处,这些怪异与底层数据毫无关系,而完全源于服务商的内部历史。某个字段因内部迁移而被重命名,旧名称作为一个没人愿意删除的已弃用别名残留下来。某个状态在一个端点中用字符串表示,在另一个端点中却用数字代码表示,因为它们是由不同团队相隔数年构建的。这些都不是出于恶意。这只是当一种格式从未依据外部标准设计、只依据公司自身不断演变的代码库设计时,必然会发生的事情。
解决办法并不复杂:选择一种简单的结构,一次性写好文档,并保持稳定。我们在自己的原生端点上都是这样做的,而在兼容主机上更进一步,完全匹配另一家服务商的结构,这样已经能解析该结构的代码库,除了基础 URL 和密钥之外完全无需任何改动。这个承诺比听起来要重大。这意味着当我们所匹配的结构中有别扭的字段名或不一致的嵌套选择时,我们会保留这些别扭之处,因为兼容主机的全部价值在于忠实还原,而不在于改进。
有人为专有格式辩护,说它让服务商有空间随时间推移添加更丰富的数据。我们不认为丰富的数据需要一种陌生的结构。可选字段(例如海拔或 IP 威胁详情)可以作为附加内容与标准响应并列,而不是取而代之,这样不请求这些字段的调用方永远不必绕开它们来解析,而请求这些字段的调用方无需学习新格式就能获得它们。
这一切其实与把 JSON 格式当作一种技术偏好无关。它关乎由谁来承担结构决策的成本。专有格式把这一成本转嫁给每一位需要读取响应的客户。简单或匹配的格式则把成本留给我们自己,体现在保持一切可预测的设计工作中。这才是成本应该归属的地方。