一个“爆款”成功的API,都离不开这8条设计准则

我已经看过很多API设计相关的文章和优秀的REST API设计教程。他们通常讨论的是适当的编码技巧和如何在给定的语言中暴露接口。尽管那些是很有用也是很需要的,但是他们经常忽略了一些能让API工作得更好的想法。

1. 兼容性与跨平台

这里就要求让API设计得是可预测的。按照这种方式写出所有接口和接口所需要的参数。现在就要确保命名是一致的,接口所需的参数顺序也是一致的。你现在应该有products,orders和customers的数据吧?,它们应该都存在含有id和name的表中。那么不要让一个接口仅传ID而另一个仅传name还有的两个都要传。也不要让一个接口按照/product/ID传参而另一个接口按/ID/customer这样传参。因为作为一个API的使用者我希望以相同的方式访问两个不同的资源。

另外一个保证相容性的技巧是观察你的参数值类型。如果一个接口的ID参数求为整型,那么不要让另一个接口的ID参数为字符串型。因为作为一个API的使用者我不想去猜每个接口的每个参数值类型。

除了需要考虑你的接口如何访问数据以外,你也应该好好想一下你的API如何返回数据以及返回数据格式的统一性。目前在我最近使用的API中就存在一个很大的问题。当开发中用到一个返回数据的接口时,我很惊奇的发现返回结果里面的每个元素都本该都含有一个特定的属性。然而结果是一些元素有那个属性而另一些却没有。我宁愿那个属性是一个空值也不愿意看到完全没有那个属性。原因是如果我遍历每个元素来寻找这个属性,我希望至少能找到它,即使它没有值。然而现在就像是从数据库查出几条记录然后发现有几条数据里面没有某个字段而其他几条却有。然后这就开始让你怀疑查询出来的结果并产生了一个疑问“那些消失的属性是被我弄丢的吗?”

2.简单明了

你应该有过打电话给别人让他帮你做一件事时对方很爽快地回复一个“好!”的经历吧?通常这时你会踌躇一下然后去问“你确定会帮我做吧?”。优秀的API不仅会做你想要它执行的操作而且还会额外返回有关它刚执行的操作的相关信息。如果你的某个API是负责创建一个product的,那么就让它执行完创建操作后返回一些有关刚刚创建的product的相关信息,而不是去要求客户端再去发送一个请求来获取你刚刚创建的product的相关信息。因为那样就显得你很没脑子。但是你还是会惊奇地发现有很多API执行完操作后只返回一点像200 OK那样的信息。所以只需要让你的API给客户端返回一些有用而且明显需要的关于刚刚执行的操作的相关信息就可以让它变得直爽。

3. 让API很容易去完成一个请求

你通常是不是更愿意这么做:让别人开车载你去干洗店或者直接让别人开车去干洗店,下车后打开店门走进干洗店,找店员拿完你的衣服然后离开干洗店再开车回到你这儿。所以你的API不要让客户端调用多次只是为了去做一个通常都需要执行的子任务!你可以通过提供默认参数值而且允许客户端可以根据特定请求去覆盖你的任意一个默认参数值来解决这个问题。

我目前一直在用的一个API就让我感到很痛苦而且还很费事时。它本应该设计成只需一个简单的请求就可以创建一个预定产品,而且耗时只需要耗时300-500ms,然而它却设计成需要你去发送7个往返都需要300-500ms的请求。这便使得本来只要300-500ms的进程要花费好几秒!而且这些增加的时间都会被使用这个API预定产品的消费者注意到。

4. 响应迅速

这条建议是建立在前几条之上的。如果请求的操作处理成功了,返回了一个成功像200 OK这样的状态码。如果请求的操作处理失败了,给出适当的像404500等这样的状态码来表明处理失败了。因为我们想要实现的是客户端在使用API时首先能根据返回的状态码来决定接来下如何去处理具体的返回内容。我现在用的一个API确实是会返回给我一个200 OK的状态码但是他紧接的返回内容是一个处理失败的报错信息。以至于,尽管我知道请求成功了但是我不得不去检查我请求的操作是否真的处理成功了。所以请不要像这样设计。你只需要在一开始就返回一个恰当的状态码后接下来就知道该如何处理了。

5. 多考虑性能问题

优秀的API都是能够很快地处理大量的请求。你处理完一个请求后取得的结果可以直接返回给那些完全相同的请求而不需要重复处理。换句话说,你应该尽可能地使用像服务器端缓存那样的技术。如果一个用户请求product1的信息,然后过几秒又有另一个人也请求product1的信息,这时你就可以将返回给第一次请求的结果同样返回给后来的请求。不需要再次查询仅仅是为了返回你刚才已经查出来过的相同数据。同时也要确保给缓存一个过期时间以免让缓存内容变得过时。

Chargify在这方面就做得很好。我向他们请求一个预定产品时他们能够在200ms左右回复我结果。这是相当快的。而且如果我在一分钟之后再次请求这个预定产品时他们会在97ms内返回给我同样的结果。同时要知道并不是所有的接口和查询都可以像那样设计,但是如果你的数据是不变的或者不经常变,那么就要考虑在你的API使用缓存来加速请求的处理。你的客户端将会因为这爱上你。如果客户端将响应结果缓存在它们自己的客户端缓存里那就能让他们更满意了。

6. 用带有SSL的Basic Auth

你现在有很多种方法来保障API的安全性,例如:Basic Auth(基本认证),Digest Auth(摘要认证 ),OAuth(开放认证),no auth等。当你考虑用哪种方法的时候需要考虑的是认证方法的性能和易用性(像上面的建议5和建议3所说的)。如果你用了SSL的话,我建议你采用Basic Auth方法,因为它很容易部署,而且只需要请求一次而不需要多次(Digest Auth通常都需要至少两次以上的请求才能完成认证)所以性能相对来说也会高些。显然如果你不使用SSL,那么就建议你用Digest Auth或者OAuth等其他的安全的认证方法。

7. 给你的API制定版本

恭喜你!你的API设计的很成功而且在被很多用户使用。现在他们的很多产品和项目开始依赖于你的API。但是你现在需要考虑的是如何在不影响他们使用的情况下去更新你的API。如果你能让不同版本的API相互独立开来,我建议你将版本号作为一个参数或者API命名的一部分。例如:GET /v1/product/id或者 GET /v2/product/id 或者 GET /product/id?v=1。你也可以选择将版本号部署进HTTP请求头,但是无论你采用哪种方法都要确保所有的版本都采用同一种方法。

通过将API用版本号区分开可以让用户一直使用某个版本的API直到恰当的时候再迁移到新版的API。你也可以随时关掉某个版本API而不需要对现有版本的API做任何处理。

8. 使用JSON而不要使用XML

第8条建议是根据我个人偏好提出的。我工作到现在用过很多API,JSON格式和XML格式都有。我会告诉你我觉得JSON格式的更好用。JSON格式通常是更为简洁的(以至于传输的数据量更小),也更容易展现复杂的对象(精确)而且能运行得像其他格式一样好(以至于现在每个人都在用JSON)。XML通常都是很冗余的,还不容易展现复杂的元素而且还需要一个DTD来验证它。所以我将会用JSON格式,如果你想用XML的话那就随便吧。不管怎样,我认为只要你开始用JSON你就会很明显得发现XML的缺点。

总结

API正在改变我们和集成系统的交互方式,所以它的质量就变得尤为重要了。如果你设计API时考虑到了终端用户,那么你就要考虑如何让他们更容易使用,这样你的API才会变得更成功。如果用户用别的API也能完成你的API能完成的事,但是别人的API更容易使用、响应速度更快,用户自然就会去用别人的而不是你的。

所以不要犯这些严重的错误:传参格式不一致,只做简单的响应,对刚刚处理的结果只字不提(不健谈)而且响应得很慢。那将毁了你整个API。

原文发布于微信公众号 - BestSDK(bestsdk)

原文发表时间:2017-08-02

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏向治洪

将studio项目 转换为eclipse项目

总会有些奇怪的事情,比如,有的人就有将studio项目 转换为eclipse项目的需求 首先,不要因为编译原因而放弃。studio项目是完全可以转换成ecli...

1937
来自专栏hotqin888的专栏

EngineerCMS工程师知识管理系统支持项目模板

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hotqin888/article/det...

1293
来自专栏java学习

Java每日一题_关于redirect和forward

(不定项选择题) 下面有关forward和redirect的描述,正确的是() ?

821
来自专栏Ceph对象存储方案

RGW Bucket Shard设计与优化-上

1 bucket index背景简介 bucket index是整个RGW里面一个非常关键的数据结构,用于存储bucket的索引数据,默认情况下单个bucke...

1.1K5
来自专栏北京马哥教育

Linux 软中断机制分析

软中断分析最近工作繁忙,没有时间总结内核相关的一些东西。上次更新博客到了linux内核中断子系统。这次总结一下软中断,也就是softirq。之后还会总结一些ta...

4618
来自专栏我是攻城师

多线程基础知识了解一下

作为一名优秀的攻城师,了解多线程的知识非常有必要,尤其在人工智能和机器学习的热潮下,如何提高程序或者算法的运行效率是非常有价值的一件事情。

1384
来自专栏代码GG之家

只需一个命令,快速定位android的启动耗时

有兴趣合作,帮忙制作公众号的一些宣传图册的伙伴,可以加我微信,商谈具体事宜。 回顾: Android 启动过程框架 这节我们讲一个命令,用来定位android...

1986
来自专栏企鹅号快讯

缓存在高并发场景下的常见问题

丁浪,阿里影业架构师,社区活跃人士。有分布式事务,分布式缓存方面的总结文章获得好评。 本文获作者授权发布。 缓存一致性问题 当数据时效性要求很高时,需要保证缓存...

1978
来自专栏JAVA高级架构开发

Redis 的各项功能解决了哪些问题?

Redis是一个基于BSD开源的项目,是一个把结构化的数据放在内存中的一个存储系统,你可以把它作为数据库,缓存和消息中间件来使用。同时支持strings,lis...

950
来自专栏架构师之路

90行代码,搞定日志监控框架

上一篇《100行代码,搞定http监控框架》介绍了通用+可扩展的http监控平台的架构: 监控平台层:调度监控项,通过后台管理监控项 信息管理层:通过服务和后台...

8097

扫码关注云+社区