前言
去年的某个时候就想写一篇关于接口的吐槽,当时后端提出了接口方案对于我来说调用起来非常难受,但又说不上为什么,没有论点论据所以也就作罢。最近因为写全栈的缘故,团队内部也遇到了一些关于接口设计的问题,于是开始思考实现接口的最佳实践是什么。在参考了许多资料之后,逐渐对这个问题有了自己的理解。同时回想起过去的经验,终于恍然大悟自己当时的痛点在哪里。
既然是吐槽,那么请原谅我接下来态度的不友善。本文中列举的所有例子都是我个人的亲身经历。
谁应该主导接口的设计
或者更直白一些,应该是接口的消费方还是提供方来决定接口的设计?
当然是接口的消费方
「接口」最吊诡的地方在于提供方大费周章把它实现了,但它自己却(几乎)重来都不使用。于是这极易陷入一种自嗨的境地,因为他更本不知道接口的好坏。就好比一个从来不尝自己做的菜的厨子,你指望他的菜能好到哪里去,他的厨艺能好到哪里去。上面隐含的前提是(我认为)接口是有绝对好坏之分的,坏的接口消费者调用难受,提供者维护难受,还导致产品行为别扭体验变差。
然而接口的好坏与谁来主导设计有什么关系?因为坏接口产生的原因之一是提供方只站在开发者的角度解决问题:
例子一 (Chatty API)
某次需要实现允许用户创建仪表盘页面的功能(如果你对仪表盘页面感到陌生的话,可以想象它是一张集中了不同图表的页面,比如柱状图、折线图、饼图等等。用户可以添加自己想要的图表到页面中,并且手动调整它们的尺寸和位置。仪表盘通常用于总览某个产品或者服务的运行状态)。后端同学的接口初步设计是,当用户填写完基本信息、添加完图表、点击创建按钮之后,我需要连续调用两次接口才能完成一次仪表盘的创建:
- 利用用户填写的基本信息以及图表的尺寸和位置创建一个空的仪表盘
- 再向仪表盘中填充图表的具体信息,比如图表类型,使用的维度和指标等
很明显看出他完全是按照自己后端的存储结构在设计接口,不仅是存储结构,甚至存储过程都一览无余。想象一种极端的情况,那不只提供一些更新数据库表的接口得了,前端自己把通过接口把数据插入库中面对这类底层性质的接口,消费者在集成时需要考虑接口的调用步骤以及理解背后的原理。如果后端的底层结构一旦发生更改,接口很有可能也需要发生更改,前端的调用代码也需要随之更改。后端研发可能会辩解说:后端用了微服务啊,不同类型的数据存储在不同的服务上,所以你需要和不同的服务通信才能实现完整的存储。他们始终没有明白的事情是,后端