一窥端倪API设计规范

480 阅读4分钟

前后端通过http协议建立通信后,还需要制定一种规范,让请求具有语义化,这种规范就是API设计规范。本文就介绍前后端通信常用的API规范。

RPC-远程过程调用

RPC(Remote Procedure Call,远程过程调用)常用于后端服务进程之间的通信。“远程”指的是不同服务器上的进程,“过程调用”里的 “过程” 可以理解为“函数”,这种接口设计和函数命名很相似,名称为动宾结构短语,类似下面的样子。

GET /getUsers 
POST /deleteUser 
POST /createUser

可能有的前端工程师对 RPC 比较陌生,但在 Web 开发早期,编写页面逻辑的工作由后端(或全栈)工程师完成,自然而然的,RPC 风格就被移植到了前后端通信中。

从接口命名上不难看出,RPC 风格和我们平常编写模块的思路很像,提供了一个函数作为接口,供其他模块调用。这明显是站在后端工程师的视角而设置的:为了像在本地调用一个函数那样调用远程的代码。

RPC 这种设计规范对前端工程师而言是不够友好的,具体表现在以下 2 个方面。

  • 紧耦合:当前端工程师需要获取或修改某个数据时,他有可能需要先调用接口 A ,再调用接口B,这种调用需要对系统非常熟悉,让前端工程师熟悉后端逻辑和代码显然是难以办到的。

  • 冗余:把执行动作写在 URL 上实际是冗余的,因为 HTTP 的 Method 头部可以表示不同的动作行为。

REST—表现层状态转换

REST(Representational State Transfer),即表现层状态转换 。

什么是“表现层”

在理解 “表现层” 之前,我们先理解另一个概念“资源”。资源指的是一个实体信息,一个文本文件、一段JSON 数据都可以称为资源。

而一个资源可以有不同的呈现形式,比如一份数据可以是 XML 格式,也可以是 JSON 格式,这种呈现形式叫作 “表现层(Representation)”。

什么是“状态转移”

当用户通过浏览器访问网站时,通常会涉及状态的变化,比如登录。

HTTP 本身是无状态的,因此,如果客户端想要操作服务器,则必须通过某种手段让服务器发生 “状态转移(State Transfer)”。而这种转移是建立在表现层之上的,即 “表现层状态转移”。

REST 的核心要点有两个,那就是资源和方法。

REST 的 URL 指向某个或某类资源,所以不再是类似 RPC 的动宾结构,而是名词。比如像下面这些都是REST 的设计风格,通常,当 URL 的路径以 ID 结尾则表示指代某个资源,无 ID 则指向一类资源。路径分隔符表示资源之间的嵌套关系。

/orgs 
/orgs/123asdf12d/
/orgs/ss1212sdf/users
/orgs/ss1212sdf/users/111asdl234l

所以像下面这些 URL 是不符合 REST 规范的。

/createUser
/samples/export

而要进行状态转移的时候,使用的是 HTTP 默认的语义化头部 Method 字段。

GETSELECT):获取资源
POSTCREATE):新建一个资源
PUTUPDATE):更新资源
DELETEDELETE):从服务器删除资源

虽然 REST 的低耦合、高度语义化的设计风格比较适合前后端通信,但也存在 3 个不足,具体如下。

  • 弱约束。 REST 定义请求路径和方法,但对非常重要的请求体和响应体并没有给出规范和约束。这就意味着需要借助工具来重新定义和校验这些内容,而不同工具之间的定义格式和校验方式都不相同,给工程师带来了一定的学习负担。
  • 接口松散。  REST 风格的数据粒度一般都非常小,前端要进行复杂查询的时候可能会涉及多个 API查询,那么会产生多个网络请求,很容易造成性能问题。通常的解决方案是通过类似 API 网关的中转服务器来实现对接口的聚合和缓存。
  • 数据冗余。 前端对网络请求性能是比较敏感的,所以传输的数据量尽可能小,但 REST API 在设计好之后,返回的字段值是固定的。所以很容易出现这样一个场景,对于后端工程师而言,为了减少代码修改,会尽可能地在返回结果中添加更多的字段;对于前端工程师而言,使用数据的场景往往是多变的,即使是调用同一个 API,在不同场景下也只会用到某些特定的字段。所以不可避免地产生数据冗余,从而造成带宽浪费,影响用户体验。

—— 公众号「风度前端」 ——

为每一个有志优秀的「前端er」引路领航,筑梦心声。

Just to be an excellent front end engineer!