关于REST API设计的一些小经验
版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明http://phoenixtoday.blogbus.com/logs/45855234.html
最近小组里有一些关于REST API设计的讨论,有些收获,打算在这里写一下。通常来讲设计第一个版本的REST API并不难,难点在于将来你要改变了这些API,而客户那里已经有对应的客户端实现, 那么你怎么保证兼容?或者,至少,你应当让这些东西失效吧,这样客户才能知道。所以基本上就是两个问题。
1,在最初设计时,如何尽量保证向后兼容?(这里不提倡过度设计噢,我们是搞敏捷的,哈哈)
2,如果API发生了改变,该怎么通知已有实现?
对于第一个问题,答案相对而言简单一些:支持必要的,但是最少的东西,而且层次不要太多。为什么?用下面的xml,举个例子来说
<person>
<name>phoenix</name>
<job>softerware developer</job>
<company>ThoughtWorks</company>
</person>
第一层,指的是这个xml具体针对什么,第二层有三个属性,分别是name,job和company,这是一个嵌套层次很好的,而且也没有包含过多的信息。但是如果我们在一开始再加上address属性(假设它并非必要),那么如果客户构建了一个客户端也的确包含了address属性,那么在下一个版本的API中,你把这个属性去掉了。问题是不是出现了?客户的软件无法工作了。反过来,如果最开始的版本不包含address,但是有客户强烈要求下一个版本要支持,那么怎么办?简单!在下一个版本加上就好了,对于已有的客户端,多一行冗余数据而已,也不会导致客户的软件无法工作。好了,这个问题解决了,那么,什么是嵌套层次不要太多。举个反例
<person>
<name>phoenix</name>
<job>softerware developer</job>
<company>
<name>ThoughtWorks</name>
<locations type="array">
<city>beijing</city>
<city>san francisco</city>
</locations>
<products>
<product>
<name>mingle</name>
</product>
<product>
<name>cruise</name>
</product>
<product>
<name>twist</name>
</product>
</products>
</company>
</person>
这叫层次太多!一个company里,包含了太多的嵌套信息,其中location还算说的过去(因为只是一个简单的数组),但是products里包含了子对象就不对了,这就是第三层对象了,具体的解决方案可以利用url来替换掉。世界终于清静啦!
可是我还不能清静,因为要回答第二个问题:API改变了,该怎么通知已有实现?这是一个很头疼的问题,如果能避免回答我绝对会避免,可惜,不能!通常有两种解决方案,但目的都是为了让客户的软件失效(我知道,我知道,这会让客户抓狂,可是我们也没辙啊!所以还是能不动,则不动,打死也不动,打不死嘛......就按如下办)a,使用带有版本号的API URL(这是现在最经常使用的一种方法),例如api/v2/projects/members.xml前面的api不说也明白,v2就是version 2版本2的意思,如果更换了,就变v3,客户的软件不能用了,也就知道了;b,利用HTTP header 里的ACCEPT来解决(别说你写了这么多年程序,连HTTP有HEAD都不知道啊!会被鄙视的!),ACCEPT可以设置接受的文件,你可以将版本信息放在里面。技术细节不多说了,给个链接,供大家参考 http://barelyenough.org/blog/2008/05/versioning-rest-web-services/ 其实我是比较赞成这种方式的,比较优雅,但缺点就是它还不是标准,对方的程序员也可能不知道HTTP有HEAD,所以做起来,对人家可能会有点复杂,这里就不再多说了。
总之昵~~,小初(想必盯我博客很久的人,也都知道我姓甚名谁了,以后我就用真名了)的技术博客在沉寂了,这么久之后,又回来了(我胡XX又回来啦!哈哈),有太多东西要写了,以后会陆续带给大家的,多谢捧场!
PS:为啥Blogbus不支持<pre>标签呢,让我的xml这么丑的出现在博客里?惭愧呀!