原文:medium.com/@aldesantis… 作者:Alessandro Desantis
好的API设计,就犹如是在创作艺术。当我们用到它的时候,就能感觉到。就如一个漂亮的界面,优秀的API不单单看上去“漂亮”,在好用之于还节省了每个人的时间。正是这种想法,才让人觉得API就犹如UI。API不仅仅用于跟程序交互,由于开发者使用这些程序,所以设计一个让人感觉友好的API才是一个明知的选择,也确实应该如此。
市面上有很多关于视觉UI设计的法则,还有很多优秀的案例可以激发设计灵感。谈及API,另一方面来说,有很多文档解释API实现所用的不同的协议、语言和框架,但几乎没有资料来说明如何让API变得好用.
经验自然是最好,并且每个开发团队都以他们的规则来建立API,只需要按照一些基本原则来建立API,就能让我们能从中获益。这非常抽象并且可以通过多种方式来实现,但是这些原则要贯穿研发的始终。
一致性
一致性意味着类似的接口应该有类似的表现,包括一些边际场景。在整个项目中,你应该努力保持API用词、URL结构、请求/响应和错误处理的格式一致。
这会带来一下好处:
- 使得操作你的API会更简单,因为你的用户能够的到其预期的返回,而不需要每次在调用新接口时都去翻阅文档。
- 使得在编写客户端库的时候,并不需要确切地了解API的模式,只需要遵循你定义的规则即可。Stripe API就是一个很好的例子,因为请求和返回的结构总是相同的,这可以动态地构建对象,并且仅在其API规则改变时作更新即可。
- 当你为API实现一些新功能时,你可以遵循一组经得起考验的方法步骤,而不需要纠结是否使用数字ID还是UUID,因为你已经搞定了。
一致性也许是你能在你设计的API中实现的最具影响力的特性,并且你的用户也会因此对你刮目相看。
性能
在HTTP API中,性能是一个较为棘手的事情。因为API并不直接被最终用户使用,很容易在性能问题上被忽视很长时间,特别是在服务与服务之间的上下文操作上。不幸的事,因为软件是为人而创造,所有类型的性能问题还是会影响到最终用户身上。
我强烈建议反对早期优化,通常理由是:它将减缓开发进度并且你在没有一个合适的衡量标准下不知道你产品哪一部分需要被优化。你应该基于数据去优化,而不是直觉。
照那样来说,你要在第一时间开始开始收集数据,这极为重要。设置一个APM(应用监控)工具,现如今已经是分分钟的事情,并且这将提供给你大量有关于API真实情况的有用的信息。
文档
不论你的API一致性好与不好,用户始终需要一个让他们可以获得API的某些方面或者其他详细信息。
此外,API文档应该不仅是呈现请求和响应的模板。推荐添加一些用户也许感到有帮助的信息是很实用的做法,例如解释当调用某些API后,会造成其的背后所发生的逻辑,又或者是用户还需要哪些其他接口来完成业务。
文档的准确和保持最新,对于你的API来说非常重要。这要将文档工作集成到开发过程的工作流中去,使之一并完成。在版本控制软件中检查文档并要求开发者随着API的改变而及时更新文档也不失为一个好的方法。
让开发者来边写文档似乎是在浪费时间,但是花费在文档上的时间更多意味着在处理疑问和调查有问题的bug上的时间就越少。
最后,确保文档不仅仅是可用,而是可以解决问题。因为这意味着它面向人类,给予文档在阅读过程中的UI和UX(用户交互和用户体验)更多的关心。你可以采用一个诸如stoplight来存储和展现标准格式内容,而不是非得亲自去写。
可用性
如果你的API资源是映射一个一一对应的数据表,当然这没有任何问题,但你应该知道,这不是唯一构建API但方法。把API搞得复杂的实际上也不是最好的方法,因为它将所一系列操作按特定的顺序放在一起,最终一并让用户承担。
如果你可以简化业务过程,只需要调用一个API而不是两个,那就去做。对于一个视觉UI需要用户每一步操作都要输入这会不可想像的,但是,出于偷懒,我们也正要求用户如此去做。
有个关于此的例子是:让用户添加一个新的支付方式并且设置这个支付方式为默认支付方式。如果我们期望的情况是用户需要添加一个新的方式,并且立即设置为默认,我们可以添加一个默认标签属性给支付方式的创建接口,并且把所有事情放在一个业务中而不是两次调用API。这节省了开发的时间和带宽。
这个类型的简化并不总是可行的:当你无法决定确切的API用例时(例如某个公开的API),你应该保持经可能的灵活(在上述案例中,这意味着增加一个字段,并同时维护一个独立的接口来设置默认支付方式)。
经验法则是将你的API各方面视为达到目的方法,即完成一整套业务流程。你如何帮你的用户完成目标?一旦你考虑到这一点,设计的选择就见得多了。
朴素/简化
基于简单为主导的思想去构建给你的API,普遍接受标准和工具。不要用小众的封装、模式、API路由或者其他的方案,除非你有必须的理由去选择它们。
HTTP RFC已经提供几乎所有你需要的工具,来构建一个Web服务,所以去好好的读一读(对,它很长,但是我保证值得这么做)
贴近基础,并将其做的足够好。简化意味着不要过头地为人或机器开销,以及更少的出错可能。例如,这里有信用卡收费的API:
curl https://api.stripe.com/v1/charges \
-u your_api_key: \
-d amount=999 \
-d currency=usd \
-d description="Example charge" \
-d source=tok_visa
这已经足够简单来,以至于不需要去查看文档,并且很难弄错。这种类型的简化就是你努力的方向。(顺便说一下,StripeAPI是一个接触的API设计案例,所以如果有时间的话去看看)
演进
传统网页应用程序一直在升级:新功能被设计和添加,改进和简化收欢迎的功能,启用和删除不实用的功能。用户习惯于不断变化的环境中,环境会发生巨大变化。
大多数时候,产品在吸引用户采用新功能方面做得非常好:新闻通讯,应用内教学和良好的设计实践可确保用户体验不会因最新的更新而打扰。
另一方面对于API来说,这看上去似乎有两个选择:要么不改变接口以避免破坏已经实现的代码,或者悄悄地改变,但你大多数用户的程序就会因此挂掉。这通常是因为API团队脱离了用户基础,因为它们并不直接与用户互动。
但是有一个C选项:用合适但基础架构和工具,你可以让API的变更可控。你可以先量化,然后发出通知关于接口公开的通知:接口使用频率如何?哪些用户在过去半年使用了特定的API接口?确认你回答这类问题,否则你改进API会给他们带来噩梦。
最后
你有什么关于API设计的理念?或者看到非常棒的设计案例?期待与你讨论。
译者
关于“可用性”部分,并不完全赞同。从业务解偶的角度出发,应该是一个API(或者一个函数)仅完成一个(单一的)工作。如果是包含多个步骤的话,那么应该有业务发起方来决定需要组合部分和组合顺序。但是原作者所举的例子,我是赞同的。再扩展一下那个例子:如果有一个接口,添加支付方式和收货地址(订单的要件),那么支付方式是一个接口,收货地址是另一个。