用产品思维设计API(三)——版本控制,没有你想的这么简单

用产品思维设计API(三)——版本控制,没有你想的这么简单

前言

最近公司内部在重构项目代码,包括API方向的重构,期间遇到了很多的问题,不由得让我重新思考了下。

- 一个优雅的API该如何设计?

- 前后端分离之后,API真的解耦分离了吗?

- 不断的版本迭代,API的兼容性该如何做?

ps.这里所说的API仅为Web API,提供APP\WEB开发使用。

年前,我司内部的接口已经进入了一个完全的重构阶段,参考了市面上各大平台的API和文档,自己也总结出了很多的心得。这里向大家分享一下,接下来一个月,我们向从下面几个方面向大家介绍一个优雅的API(至少我认为挺优雅)该如何设计。

  1. RESTful就是个骗局 (http://blog.csdn.net/yzzst/article/details/53775319)
  2. 数据解耦,才是前后分离的本质(http://blog.csdn.net/yzzst/article/details/53844590)
  3. 版本控制,没有你想的这么简单(http://blog.csdn.net/yzzst/article/details/54755077
  4. 随意定义错误码,你还在这样干?
  5. 安全,就只能用HTTPS?

ps. 打一个广告,公司内部现在在招聘各种技术岗位,Java、Android、前端等,待遇保证能让你涨30%,有兴趣的朋友可以加韬哥的微信(微信号:stchou_zst),二维码在文章最后。


业界目前常用的做法有哪些?

在RESTful API领域,关于如何做版本控制,目前业界比较主流的有3种做法:

URI版本控制

即在URI中直接标记使用的是哪个版本,无版本号URI默认使用最新版本。如下:

http://xianlinbox/api/customers/1234
http://xianlinbox/api/v3.0/customers/1234  
  • 好处:

    直接可以在URI中直观的看到API版本,

    可以直接在浏览器的查看各个版本API的结果

  • 坏处:

    版本号在URI中破坏了REST的HATEOAS(hypermedia as the engine of application state)规则。版本号和资源之间并无直接关系。

URL参数控制

即在每个请求后添加一个version参数,表示请求的是哪个版本。如下:

http://server:port/api/customer/123?version=2  

这种做法其实就是URI方式的变种,好坏处也都一样。

Mdedia Type控制

即在HTTP请求的header中使用Media Type标记该请求想获取的资源, 同样的可以不设置或设置通用的Media Type表示最新版本的API。

GET /customer/123 HTTP/1.1
Accept: application/vnd.xianlinbox.customer-v3+json  

HTTP/1.1 200 OK
Content-Type: application/vnd.xianlinbox.customer-v3+json  

{"customer":
  {"name":"Xianlinbox"}
}  
  • 好处:

    遵循了REST的设计风格(tencent的基本都是这个风格)

  • 坏处:

    版本不直观,需要能设置header的client才能调用查看该API的效果。

这么多API版本控制的方式,其实看起来都差别不太多,用起来都区别不大。选择这么多并不是好事,我们要选择哪种呢?


等等,我们做版本控制要解决什么问题?

APP版本迭代之中,需求更变,API接口洗发的逻辑发生了改变,为了兼容不同版本的APP使用,才能需要对API进行版本控制。

如:

/getUserInfo (获取用户信息)接口

返回信息

{
    nikeName : "诚壹小主",
    sex : 0,
    email : "[email protected]"
}

现在需求有变,这个接口的下发信息有变,需要增加一个头像字段,在APP上显示用户的头像。

{
    nikeName : "诚壹小主",
    sex : 0,
    email : "[email protected]",
    avatar : "http://www.test.com/pig.png"
}

只是增加一个avatar字段,对于客户端解析JSON来说,并没有影响。困难就困难在,很多情况下,我们并不是要增加一个字段,而是改变一个现有的字段返回的信息。

如,这里需要将sex的内容从”0”改为”female”

{
    nikeName : "诚壹小主",
    sex : "female",
    email : "[email protected]"
}

映射的Bean属性变了,没法继续使用这个接口了,必须升级。我们可以用上述的三种形式的任意一种。如:

/v2/getUserInfo

问题是解决了,但是,又引入了新的问题。我们的更变需求仅仅有修改这么一个接口而已。其他的接奥口内容并没有发生变化,路径和版本号都不需要修改。这么一来,经过几次迭代就会出现下面几种问题:

  1. 客户端请求的版本号混乱,冗余
异步更新版本号:
/getOrder
/getAppList
/getProductList
/v2/getUserInfo      (与上面的是不是一套API,能不能混用,搞不清楚)

同步更新版本号:
/v2/getOrder         (没更新)
/v2/getAppList       (没更新)
/v2/getProductList   (没更新)
/v2/getUserInfo      (更新了sex字段)
  1. 老版本接口暴露,存在安全隐患
遍历请求
/v1/getUserInfo
/v2/getUserInfo
/v3/getUserInfo
/v4/getUserInfo
.............
  1. 后端逻辑代码兼容性冗余
api/
    common/
        controllers/
            UserController.php
            PostController.php
        models/
            User.php
            Post.php
    modules/
        v1/
            controllers/
                UserController.php
                PostController.php
            models/
                User.php
                Post.php
        v2/
            controllers/
                UserController.php
                PostController.php
            models/
                User.php
                Post.php

众多的问题,让我们一起想到,仅仅靠一个version做版本号判断,是不够的。不能让客户端来选择使用哪个版本的API。API的控制权,必须是客户端透明,服务端主导的


如何主导API的下发不同内容?

如何主导呢?服务端必须知道客户端的所有的信息,如,版本号、设备名称、设备尺寸、渠道号、定位信息等等,就能够做到根据不同版本的APP,不同设备的APP,不同区域的APP下发不同的内容。(之前以为只做统计用)

具体怎么操作,我们看一下今日头条的API请求:

POST http://is.snssdk.com/article/category/get_subscribed/v1/?iid=7692187251&device_id=25714927584&ac=wifi&channel=xiaomi&aid=13&app_name=news_article&version_code=600&version_name=6.0.0&device_platform=android&ab_version=100436%2C103308%2C101786%2C101533%2C103122%2C100193%2C97143%2C103497%2C103545%2C103104%2C101558%2C102627%2C103524%2C94045%2C92439%2C103679%2C103557%2C103215%2C102771%2C98046%2C101405%2C95564%2C103630%2C103435&ab_client=a1%2Cc4%2Ce1%2Cf2%2Cg2%2Cf7&ab_feature=94563&abflag=3&ssmix=a&device_type=MI+5&device_brand=Xiaomi&language=zh&os_api=23&os_version=6.0.1&uuid=862155031730905&openudid=3037046a77716479&manifest_version_code=600&resolution=1080*1920&dpi=480&update_version_code=6001&_rticket=1485485393465 HTTP/1.1
Accept-Encoding: gzip
User-Agent: Dalvik/2.1.0 (Linux; U; Android 6.0.1; MI 5 MIUI/V8.1.3.0.MAACNDI) NewsArticle/6.0.0 okhttp/3.4.1
Cookie: _ba=BA0.2-20161220-51e32-AdUP8aMwlxczAIfA41LV; login_flag=c462a98391e078f9487d2fae9969466e; sid_tt=d934f60b0d1fd46efd4580d08ca19575; sid_guard="d934f60b0d1fd46efd4580d08ca19575|1484070881|2592000|Thu\054 09-Feb-2017 17:54:41 GMT"; qh[360]=1; alert_coverage=68; _ga=GA1.2.1091613933.1472312132; install_id=7692187251; ttreq=1$4426684a5aa688958281215ccf4d3922eafab5a1; sessionid=d934f60b0d1fd46efd4580d08ca19575
X-SS-REQ-TICKET: 1485485396229
Content-Type: application/x-www-form-urlencoded
Content-Length: 1250
Host: is.snssdk.com
Connection: Keep-Alive

city=%E5%8C%97%E4%BA%AC%E5%B8%82&latitude=39.984465&longitude=116.343119&loc_time=1471575017&categories=%5B%22__all__%22%2C%22news_finance%22%2C%22news_hot%22%2C%22news_local%22%2C%22video%22%2C%22news_society%22%2C%22question_and_answer%22%2C%22subscription%22%2C%22news_entertainment%22%2C%22%E7%BB%84%E5%9B%BE%22%2C%22news_tech%22%2C%22news_car%22%2C%22news_sports%22%2C%22news_military%22%2C%22news_world%22%2C%22essay_joke%22%2C%22image_funny%22%2C%22image_ppmm%22%2C%22news_health%22%2C%22positive%22%2C%22jinritemai%22%2C%22hotsoon%22%5D&version=4222937564%7C12%7C1485184142&iid=7692187251&device_id=25714927584&ac=wifi&channel=xiaomi&aid=13&app_name=news_article&version_code=600&version_name=6.0.0&device_platform=android&ab_version=100436%2C103308%2C101786%2C101533%2C103122%2C100193%2C97143%2C103497%2C103545%2C103104%2C101558%2C102627%2C103524%2C94045%2C92439%2C103679%2C103557%2C103215%2C102771%2C98046%2C101405%2C95564%2C103630%2C103435&ab_client=a1%2Cc4%2Ce1%2Cf2%2Cg2%2Cf7&ab_feature=94563&abflag=3&ssmix=a&device_type=MI%205&device_brand=Xiaomi&language=zh&os_api=23&os_version=6.0.1&uuid=862155031730905&openudid=3037046a77716479&manifest_version_code=600&resolution=1080*1920&dpi=480&update_version_code=6001&_rticket=1485485393465

其实,头条的做法很简单,把需要操作的所有数据都在API请求的时候带给了后端,既能做统计需求又能够有针对性的下发不同内容,灰度测试、个性化推荐常用这个套路。

反过来看看我们本文之前的demo,就能重新勾画出我们的API结构,如下图所示:

那么,我们什么时候修改API的Version呢?

其实,抓了很多家APP的包,发现这个改版比较少。对于我们而言,应该是API的协议方式变了,整个API的体系架构变了,这种较大的改动且还需要兼容我们才会同时部署多套API给予客户端调用。



写在后面,最近快过年了,公司业务繁忙,重构任务重大,更新博客也慢了。希望大家多多包涵。

@author zhoushengtao(周圣韬)

@since 2017年1月27日 12:39

@weixin stchou_zst

@blog http://blog.csdn.net/yzzst

时间: 2024-12-24 17:33:11

用产品思维设计API(三)——版本控制,没有你想的这么简单的相关文章

用产品思维设计API(二)——数据解耦,才是前后分离的本质

用产品思维设计API(二)--数据解耦,才是前后分离的本质 前言 最近公司内部在重构项目代码,包括API方向的重构,期间遇到了很多的问题,不由得让我重新思考了下. - 一个优雅的API该如何设计? - 前后端分离之后,API真的解耦分离了吗? - 不断的版本迭代,API的兼容性该如何做? ps.这里所说的API仅为Web API,提供APP\WEB开发使用. 年前,我司内部的接口已经进入了一个完全的重构阶段,参考了市面上各大平台的API和文档,自己也总结出了很多的心得.这里向大家分享一下,接下来

用产品思维设计API(一)——RESTful就是个骗局

用产品思维设计API(一)--RESTful就是个骗局 前言 最近公司内部在重构项目代码,包括API方向的重构,期间遇到了很多的问题,不由得让我重新思考了下. - 一个优雅的API该如何设计? - 前后端分离之后,API真的解耦分离了吗? - 不断的版本迭代,API的兼容性该如何做? 年前,我司内部的接口已经进入了一个完全的重构阶段,参考了市面上各大平台的API和文档,自己也总结出了很多的心得.这里向大家分享一下,接下来一个月,我们向从下面几个方面向大家介绍一个优雅的API(至少我认为挺优雅)该

设计师如何提高产品思维 | 设计思考

作为一个互联网公司的设计师,经常会被产品或者资深设计师说:"你们怎么没有产品思维!"那么一些设计师本人也发现,工作了几年后,自己的作用很有限,设计能力也遇到了瓶颈,很难再提升.那么带来的比较直接的结果就是:晋升慢,提薪少,话语权少,越来越被忽视. 这些设计师自己也非常希望提高自己的产品思维,可是要怎样做呢? 设计师如何提高产品思维 我本人从事的是交互设计师岗位,但在不同的项目时期也曾经担任过一段时间的产品经理,目前在项目组也算是带"产品"性质的设计师.在我看来产品思

UI的必修课——产品原型设计

想要做好ui设计,为什么要学习产品原型设计?下面小编就给大家简单分析一下其中的原因,希望对大家后期的学习有所帮助. 为了能够更好地实现自己的职业价值,设计师需要掌握更多其他方面的技能,其中产品原型设计就是比较典型的,具体有哪些呢? 一.快速入行需要 其实很多设计师一开始并不明白自己到哪一个程度,才算是真正的入门.当前市场上比较流行的产品原型设计工具很多,因此ui设计师需要掌握的技能还有很多,如果你想快速入行ui设计,可以考虑专业学习产品原型设计相关技能. 二.提高设计质量 掌握更多的知识,考虑问

产品思维学习(三)--产品设计的五个层面

今天的读书会很碰巧有一位同学分享<用户体验要素-以用户为中心的产品设计>这本书.里面讲述了用户体验要素的五个层面:战略层,范围层,结构层,框架层,表现层.也是产品设计的五个层面,所以学习记录下.首先附上这五个层次的图: 首先介绍下用户体验要素这本书,这本书主要以web网页作为例子进行5个层次的论述.看起来已经不符合现在移动互联网的的时代需求了.其实不是,正所谓"心中有剑,折根树枝都能杀人",即使书中的例子没有涉及到移动的端的APP应用.但是仍然试用于相关产品的设计. 战略层

【笔记】得到-《梁宁&#183;产品思维三十讲》

ps:偶然从[得到]上听到梁宁的<产品思维三十讲],感觉很棒,抽时间听完了所有的课程,特整理笔记如下. 01发刊词|产品能力是每个人的底层能力 产品能力就是训练一个人:判断信息,抓住要点,整合有限的资源,把自己的价值打包成一个产品向世界交付,并且获得回报. 通过这30讲,希望拥有三个东西: 1.一双眼睛.发现痛点.找到破局点的敏锐之眼: 2.一双手.动手优化,着手改变的行动之手: 3.一颗心.洞察人性的同理心,懂得自己与用户,懂得产品上每个细节给到人的满足感.确认感和依赖感. 02案例:用户体验

产品经理到底要不要懂技术?(要拥有的是框架思维:产品分层与模块化设计,使用路径设计,良好的商业思维设计。人生时间有限,不需要将编程技术吃透)

前段时间,我面试了一个国内一线门户客户端的产品经理,她是学计算机出身的PM,但是由于编程能力比较弱,所以做了产品经理.后来在工作中,有时和技术同学打交道比较费劲,所以自己吭哧吭哧开始学习SQL和PHP. 我不太认可这种直接去学习编程的方式,因为产品经理应该是很忙的,你的宝贵时间不该花在学习编程这件小事上.(多说一句,我也是学计算机出身,毕业于国内某最好的大学之一的计算机系.我并无贬低编程之意,恰好相反,我身边很多优秀的产品经理都是学计算机专业出身.) 所以,结合自己的工作和创业经历,以及后来与诸

产品经理如何设计API接口

原则上API接口设计一般出现在开发的详细设计中,但是随着诸多公司建立开放平台,产品经理也逐渐需要能理解API接口,尤其是做平台性的产品,还要学会定义接口.本文就关于产品经理在设计接口中需要定义什么.需要注意什么来展开陈述. 一.了解API的常识 在做接口设计时,如果是新手,建议多参考并了解不同开放平台的接口样式,比如百度.旷视.腾讯等,从中可以发现一些共识: 1. 常用的通信协议 调用第三方平台接口需要进行系统间的通信,目前常用的协议是http和https:简单理解https是http的加密版,

做一个有产品思维的研发:逻辑设计

每天10分钟,解决一个研发问题. 如果你想了解我在做什么,请看<做一个有产品思维的研发:课程大纲>传送门:https://www.cnblogs.com/hunttown/p/10490965.html 今天我们说一下逻辑设计问题: 对于逻辑设计的形式和它的出场顺序有很大的争议. 1.先出一下它的设计形式 在很多人的印象中,逻辑设计应该以“E-R”图或“UML”图出场,所以很多人在进行逻辑设计的时候,都会按教材上所写的一板一眼的做. 我想说的是:完全没有必要 为什么? 一是画得费劲,浪费太多时