1. 争取相容性和统一性

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

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

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

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这样的状态码。如果请求的操作处理失败了,给出适当的像404或500等这样的状态码来表明处理失败了。因为我们想要实现的是客户端在使用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的缺点。

总结

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

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

App后台开发运维和架构实践学习总结(3)——RestFul架构下API接口设计注意点的更多相关文章

  1. App后台开发运维和架构实践学习总结(2)——RESTful API设计技巧

    前言 移动互联网时代,RESTful API成为越来越重要的移动端和服务器端交互的形式.尤其是在很多互联网公司或者传统行业拥抱移动互联网的时候,一套设计良好的Restful API能够帮助互联网产品支 ...

  2. App后台开发运维和架构实践学习总结(5)——App产品从需求到研发到开发到上线到产品迭代全过程

    前言 如果没有做过开发,研发过产品的人,很难体会做产品的艰难,刚进公司的人,一般充当的是程序开发,我这里说的是开发,它与研发是有区别的. 一个需求下来,如果不能很好地理解产品需求,如果不能很好的驾驭需 ...

  3. App后台开发运维和架构实践学习总结(4)——APP的注册和登录功能设计

    一.为什么需要注册和登录? 是否需要注册和登录的关键取决于产品形态. 如果用户注册登录对于用户需求.产品功能.商业模式本身带不来任何价值的话,就没必要设计这样的功能.比如一些实用工具类的产品:计算器. ...

  4. App后台开发运维和架构实践学习总结(1)——App后台核心技术之用户验证方案

    对于初学者来说,对Token和Session的使用难免会限于困境,开发过程中知道有这个东西,但却不知道为什么要用他?更不知道其原理,今天我就带大家一起分析分析这东西. 一.使用Token进行身份鉴权 ...

  5. 《App后台开发运维与架构实践》第2章 App后台基础技术

    2.1 從App業務邏輯中提煉API接口 業務邏輯思維導圖 功能-業務邏輯思維導圖 基本功能模塊關系 功能模塊接口UML(設計出API) 在設計稿標注API 編寫API文檔 2.2 設計API的要點 ...

  6. Java生鲜电商平台-API接口设计之token、timestamp、sign 具体架构与实现(APP/小程序,传输安全)

    Java生鲜电商平台-API接口设计之token.timestamp.sign 具体设计与实现 说明:在实际的业务中,难免会跟第三方系统进行数据的交互与传递,那么如何保证数据在传输过程中的安全呢(防窃 ...

  7. API接口设计之token、timestamp、sign 具体架构与实现(APP/小程序,传输安全)

    Java生鲜电商平台-API接口设计之token.timestamp.sign 具体设计与实现 说明:在实际的业务中,难免会跟第三方系统进行数据的交互与传递,那么如何保证数据在传输过程中的安全呢(防窃 ...

  8. php后台对接ios,安卓,API接口设计和实践完全攻略,涨薪必备技能

    2016年12月29日13:45:27    关于接口设计要说的东西很多,可能写一个系列都可以,vsd图都得画很多张,但是由于个人时间和精力有限,所有有些东西后面再补充   说道接口设计第一反应就是r ...

  9. 测开大佬告诉你:如何5分钟快速创建restful风格的API接口-使用django restframework框架

    一.思考❓❔ 1.创建API接口难吗? 软件测试工程师: 只测过API接口, 从没创建过 应该需要掌握一门后端开发语言和后端开发框架吧!? 脑容量有限,想想就可怕 2.如何创建API接口呢? 使用Dj ...

随机推荐

  1. HashMap1

    一.Java并发基础 当一个对象或变量可以被多个线程共享的时候,就有可能使得程序的逻辑出现问题. 在一个对象中有一个变量i=0,有两个线程A,B都想对i加1,这个时候便有问题显现出来,关键就是对i加1 ...

  2. bzoj 2100: [Usaco2010 Dec]Apple Delivery【spfa】

    洛谷数据好强啊,普通spfa开o2都过不了,要加双端队列优化 因为是双向边,所以dis(u,v)=dis(v,u),所以分别以pa1和pa2为起点spfa一遍,表示pb-->pa1-->p ...

  3. [Swift通天遁地]一、超级工具-(10)使用地图视图MKMapView的相机功能实现创建三维地图

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  4. GIT学习之路第三天 文件操作

    本文参考廖雪峰老师的博客进行总结,完整学习请转廖雪峰博客 一.版本回退 1.git log提交日志 在git中可以通过个git log 命令显示从最近到最远的提交日志. $ git log commi ...

  5. 2017杭电多校第五场Rikka with Subset

    Rikka with Subset Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others ...

  6. 创建 pulic dblink 使不同的用户可以访问dblink

    1. system: grant create public database link to ivrsdata; 2.userdate: tnsnames.ora config db connect ...

  7. 401 Binary Watch 二进制手表

    详见:https://leetcode.com/problems/binary-watch/description/ C++: class Solution { public: vector<s ...

  8. python调用chrome ie等浏览器

    chrome: 首先,要安装下谷歌浏览器,查看谷歌浏览器的版本,对应版本下载相应的chromedriver插件,http://blog.csdn.net/huilan_same/article/det ...

  9. Roslyn导致发布网站时报错:编译失败

    最近新升级了Visual Studio 2017,创建的Web项目Bin目录中多了一个叫roslyn的文件夹,该文件夹导致网站在某些服务器上发布出错 从网上搜索了一下,Roslyn是新出的动态编译工具 ...

  10. poj2240 Arbitrage

    思路: 有向图判负环. 实现: (1)spfa #include <iostream> #include <map> #include <string> #incl ...