【思考】前后端交互-一些关于接口设计

0.936字数 3039阅读 2061

前言

最近在工作中和后端童鞋打交道,前后端沟通最为重点的就是接口API,这里整理一下接口设计的一些考虑点并做分析,希望对大家有帮助 。

兵马未动,粮草先行。在一款APP产品的各个版本迭代中,兵马的启动指的是真正开始敲代码的时候,粮草先行则是指前期的需求,交互,UI等评审准备阶段,还有本文要说的接口的设计与评审。虽然很多时候一个api接口的业务,数据逻辑是后端提供的,但真正使用这个接口的是客户端,一个前端功能的实现流程与逻辑,有时候只有客户端的RD才清楚,从某种意义来说,客户端算是接口的需求方。

所以建议在前期接口设计和评审时,客户端的RD应该更多的思考和参与,什么时机调什么接口?每个接口需要哪些字段?数据含义怎么给?只有这些都考虑清楚,且达成一致并产出接口文档后,当项目真正启动时,根据接口协议进行开发,才能尽量避免各种不确定因素对项目整体进度的影响。

接口设计的考虑点

我从下面几个方面考虑接口的设计:

  • 1 接口文档
  • 2 接口安全
  • 3 一些基本原则
  • 4 瘦客户端

1 关于接口文档

1.1 接口设计必须提供接口文档

无论项目团队的大小,在遇到接口问题的时候单纯的从代码出发,而不是从接口文档出发,对于整个项目团队的维护简直就是耍流氓。

1.2 文档也应纳入版本控制

使用markdown,wiki 做文本类型的文档,使用svn,git等做为版本工具 可以很清晰的看到接口文档的改动人和改动时间,同样是方便维护工作。

1.3 文档类型选择markdown,wiki等

使用文本类型的文档(比如markdown, wiki等格式),一则方便比较版本间改动,二则可以生成html, word, pdf等多种美观格式。我见过有好多团队是使用word来写文档的,由于是二进制格式,不利于版本比较,也不专业。

1.4 文档- 简洁

档不应浮于形式,而是力求只写最有价值的内容。做好这一点的关键是作者与读者要有足够的约定,比如蚕茧法就能很好的帮助简化类型定义的描述。

1.5 应有机制保证接口文档与代码的一致

一些团队在文档上应付差事浮于形式,在代码写完后,补一个word文档应付。在更新代码时,文档没有及时更新,导致文档都是错误没法看。好的做法都应先有设计再写代码,比如架构师或主程先设计好接口,然后再开始编程实现,在实现中发现问题再修正接口,更新设计文档,而不应是写完代码再补个设计。而在文档更新的具体做法上,也流行一种做法即文档以注释的方式内嵌于代码中,我称之为“格式化注释”,这样做到设计与代码在一起,更新也就更自然的同步了。之后再通过工具将注释抽出来美化给读者看。

1.6 接口应当包含内容

接口地址、请求方法、请求参数、返回内容、错误代码

  • 以下是一个用户信息接口的文档示例,包含接口描述,请求参数,响应参数,json示例等。

接口描述:用户登陆成功后,或进入个人中心时会获取一次用户信息


    "code":200,
    "msg":"成功",
    "time":"1482213602000",
    "data": {
        "id":"1001",
        "name":"张三",
        "age":"20"
    }
}

2 接口安全

当我们面对很多外部接口的时候,我们需要考虑数据的安全性。为什么要考虑安全性:

  • 包含用户数据
  • 包含交易数据
  • 以及甚至你不想让用户自己知道的数据

所以分为请求参数和响应参数:

  • 请求参数中包含用户隐私的字段参数,如:登陆接口的密码字段,需要进行加密传输,避免被代理捕捉请求后获取明文密码。

  • 响应参数中包含用户隐私的字段数据,需要加*号。如:手机号,身份证,用户邮箱,支付账号,邮寄地址等。

 "phone":"150*****000",
 "idCard":"3500**********0555",  
 "email":"40*****00@qq.com"     
}
  • 客户端和服务器通过约定的算法,对传递的参数值进行签名匹配,防止参数在请求过程中被抓取篡改

保护接口的方式最基本的是SSL/TLS,然后呢:

  • 对称加密的方式
  • 非对称加密的方式
  • 动态秘钥

具体可以看 像架构师一样来思考微服务接口设计


3 接口的一些原则

3.1 一个页面尽量只有一个拉取接口

原先一个页面要通过多个请求获取多种类型数据的情况,最好能通过一个接口全部获取得到。又如:在调用B接口前需要A接口的前置数据的情况,可以让后端支持下,在调用A接口时直接返回B接口的数据,减少类似这种的连续请求。

3.2 打破第一条规则,当请求需要缓存并且有需要及时更新的情况

为了更好的打开速度,对于不经常变化的数据,往往需要做数据缓存以及请求缓存。但有些信息,比如预约时间,又需要做到及时,则应该分多个请求。

3.3 如果返回数据中某个字段的数据没有,返回该字段比不返回该字段要好。

JSON格式的好处在于灵活性,但没有校验机制。所以定义协议时规定了有哪些字段,最好这些字段都返回。我的意思是比如返回一个列表,大多数场景是返回一个数组,但如果没有数据,返回一个空数组比不返回该字段要好。当然前端也有必要做自己的容错考虑。

比较常见的返回数据的格式:


3.4 命名规范

统一命名:与后端约定好即可(php和js在命名时一般采用下划线风格,而Java中一般采用的是驼峰法),无绝对标准,不要同时存在驼峰”userName”,下划线”phone_number”两种形式就可以了。

避免冗余字段:每次在新增接口字段时,注意是否已经存在同一个含义的字段,保持命名一致,不要同时存在”userName”,”username”,”uName”多种同义字段。

注释清晰(重要):每个接口/字段都需要有详细的描述信息,很多时候接口体现业务逻辑,是团队中很重要的文档沉淀,同时,详细的接口文档,可以帮助新人快速熟悉业务。

3.5 将APP接收数据的类型定义为容错能力更强的String(推荐)

容错性强,规避因脏数据引起的数据解析失败。


4 瘦客户端

众所周知,客户端任何的修改都是需要发版的,特别是IOS需要走AppStore的审核流程。为了修一个bug,仅仅改几行代码,而重新走一轮发版流程,是很劳民伤财的。所以在接口设计的时候,也需要适当考虑这点,将业务重心交由后端,客户端保持逻辑简单。后端一天可以发n个版,客户端一个版本却只能发一次,有些团队一开始并没意识到这点,总觉后端就是重度业务逻辑的所在,管那么多前端的展示,真正到了出问题(bug或需求变更)需要发版的时候,虽然70%的锅是客户端背,但是,剩余30%也会对当初重客户端的选择而后悔,不过重点不是谁背锅,而是产品不出问题。so,为了大局,后端的RD们,我们得聊聊。

4.1 客户端尽量只负责展示逻辑,不处理业务逻辑

例如:客户端有个TextView,后端只给个status字段,status=1时,展示文案1;status=2时,展示文案2;这样设计的缺点是,如果以后要修改status=3时,展示文案1,那么这个status判断逻辑时写死在客户端,就没办法支持这种修改,且这种设计限定死了TextView只能展示2种文案。推荐方案是后端直接将TextView需要展示的文案下发,这样不管是status的判断,还是文案的展示,后期都是可变的。

4.2 客户端不处理金额的计算

例如:外卖APP,用户在下单的时候,需要选择收货地址,支付类型,优惠券等,任何一个选项的修改,都可能影响用户最后需要支付的金额。所以这里比较常见的接口设计是在每次选择完回到订单支付页面后,再发送一次请求,后端根据当前选项重新计算金额。金额永远是一款产品最重要,最敏感的信息,如果交由客户端计算,万一出错,即使少1分,都是毁灭性的,所以,关于金额,展示就好。

4.3 客户端少处理请求参数的校验与约束提示

例如:修改密码功能,密码规则”6-12字母,数字,下划线”,有3种做法:

  • 1 在发送请求前,客户端校验密码规则,如果不符合,则不发送请求。优点:规则不满足时,可以减少不必要的请求。缺点:客户端写死校验逻辑,密码规则变化时,客户端需要发版。

  • 2 客户端只判断null,和最短位数限制,其他校验规则交由后端处理。优点:灵活性最好。缺点:后端压力大,校验请求多。

  • 3 后端在通用配置的接口返回正则表达式,客户端获取后进行正则校验。优点:具有一定灵活性。缺点:开发,调试成本较高。(推荐:即使出问题,也可以清除配置,回退到第2个方案)

参考资料

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
  • 百战程序员_ Java1573题 QQ群:561832648489034603 掌握80%年薪20万掌握50%年薪...
  • 作者:虞伯武 这是一个最平常不过的秋晚 经过一天劳顿,我躺在床上小憩 看见窗外黑暗无声无息的铺散开来 看不见人语和...
  • 遇到过很多已经工作的人,如果你问他们是否喜欢现在的工作,几乎所有人都不会表现出对工作的喜爱,有的可能是无尽的吐槽,...
  • 2012年3月21日 心情犹如早春的天气,变幻无常,是自己感情丰富容易情绪化?可是人是高级动物总得对外界的刺激...