Design RESTfulAPI —— 从领域建模到 API

2018-12-03  本文已影响0人  zcfelix

REST简介

RESTful,是目前非常流行的一种互联网软件架构,由于其结构清晰、易于理解、便于扩展,正得到越来越多开发者的青睐。

什么是REST

REST(REpresentational State Transfer),首次出现是在2000年Roy Thomas Fielding的博士论文中,它值得是一组架构约束条件和原则。满足这些约束条件和原则的应用程序和设计就是RSETful的。为了理解什么是REST,我们首先需要理解下面几个概念。

综合上面的解释,我们可以对RESTful架构做一个简单总结:

  1. 每一个URI代表一种资源
  2. 客户端和服务器之间,资源以某种形式进行传递,即传递资源的表现层
  3. 客户端通过不同的HTTP动词(POST、PUT/PATCH、GET、DELETE、HEAD、OPTIONS)对资源进行操作,从而达到“表现层状态转化”的目的。

REST成熟度模型

在Roy Thomas Fielding的论文中,对REST架构风格做了以下几点约束。

严格来说,符合所有这些约束的服务才能被称为 RESTful,但是在实际开发中,这需要付出较为高昂的成本,可能我们常见的服务都不是完全 RESTful 的,那么如何去判断一个服务有多么 RESTful 呢?Richardson 提出的 REST 成熟度模型可以帮助我们分析。模型对于REST服务的成熟划分了如下四个等级。

glory-of-rest.png

API设计方法原则

API设计详细步骤

梳理业务流程

业务流程的梳理,是我们工作的起点。Event Storming是一种有效的帮助我们梳理业务的方法,Event Storming的具体步骤可以参考这篇文档,本文不再赘述。

建立系统模型

完成业务模型的梳理之后,下一步就是建立系统业务模型了,笔者采用的方法是四色建模,InfoQ上的这篇文章已经做了详细介绍。简单总结如下:

  1. 以满足业务运行为前提,寻找需要追溯的事件。
  2. 根据需要追溯的事件,寻找事件相关的时标性对象。所谓时标性对象,一般与时间有紧密相关关系。
  3. 寻找时标对象周围的人、事、物,并分析它们之间的关系。
  4. 从人、事、物中抽象角色。
  5. 用描述性对象补充说明系统中的人、事、物。

那么,我们如何判断我们通过上述方法建立的模型是可用的呢?答案便在于业务数据流。我们可以在建立的业务系统模型上,模拟业务事件的发生,分析业务数据流是否能够在模型上流通,从而判断我们建立的模型能否支撑我们的业务。

以笔者参与的一个实际项目为例:某公司技术人员管理许多数字资产,业务部门的人员需要通过一定的策略对数字资产的状态进行检查,并产生对应的报表。业务建模过程如下:

time-interval.png object-beside-time-interval.png relationships-of-objects.png aggregation-root.png

识别资源及设计URI

根据业务模型,我们分析其中的资源和聚合根,并以每个聚合根为起点,开始设计 URI。在上面的例子中,我们的聚合根为 User 和 policy,因此URI设计如下表。

编号 URI
1 /users
2 /users/{uid}
3 /users/{uid}/tasks
4 /users/{uid}/tasks/{tid}
5 /users/{uid}/tasks/{tid}/reports
6 /users/{uid}/tasks/{tid}/reports/{rid}
7 /users/{uid}/assets
8 /users/{uid}/assets/{aid}
9 /policies
10 /policies/{pid}

结合HTTP动词定义RESTful API

结合第一部分说明的在 REST 语义下各 HTTP 动词的含义,分析每个 URI (资源)在这些动词下是否有业务含义,分析如下表。

POST GET DELETE PATCH PUT HEAD OPTIONS
1
2
3
4
5
6
7
8
9
10

结合具体的业务场景和操作者,可以分析每个 API 应该返回的状态码。下表给出了部分(有关 user 和 asset ) API 的使用场景与返回状态码的结果。

WHO URI METHOD SCENE RESPONSE
Any /users POST 创建用户 成功创建201
Any /users POST 创建用户 信息有误400
Admin /users GET 查询所有用户信息 成功获取200
!Admin /users GET 查询所有用户信息 非法获取403
Admin or Uid /users/{uid} GET 查询某个用户信息 成功获取200
Admin or Uid /users/{uid} GET 查询某个用户信息 用户不存在404
!{Admin or Uid} /users/{uid} GET 查询某个用户信息 非法获取403
Uid /users/{uid} PATCH 修改某用户个人信息 成功修改204
Uid /users/{uid} PATCH 修改某用户个人信息 修改有误400
!Uid /users/{uid} PATCH 修改某用户个人信息 非法修改403
Admin or Uid /users/{uid}/assets POST 创建资产 成功创建201
Admin or Uid /users/{uid}/assets POST 创建资产 信息有误400
!{Admin or Uid} /users/{uid}/assets POST 创建资产 非法创建403
Admin or Uid /users/{uid}/assets GET 查询某用户所有资产信息 成功获取200
!{Admin or Uid} /users/{uid}/assets GET 查询某用户所有资产信息 非法获取403
Admin or Uid /users/{uid}/assets DELETE 批量删除某用户的某些资产 成功删除204
Admin or Uid /users/{uid}/assets DELETE 批量删除某用户的某些资产 信息有误400
!{Admin or Uid} /users/{uid}/assets DELETE 批量删除某用户的某些资产 非法删除403
Admin or Uid /users/{uid}/assets/{aid} GET 查询某资产详情 成功获取200
Admin or Uid /users/{uid}/assets/{aid} GET 查询某资产详情 找不到资产信息404
!{Admin or Uid} /users/{uid}/assets/{aid} GET 查询某资产详情 非法获取403
Admin or Uid /users/{uid}/assets/{aid} PATCH 修改某资产信息 成功修改204
Admin or Uid /users/{uid}/assets/{aid} PATCH 修改某资产信息 修改有误400
Admin or Uid /users/{uid}/assets/{aid} PATCH 修改某资产信息 找不到资产信息404
!{Admin or Uid} /users/{uid}/assets/{aid} PATCH 修改某资产信息 非法修改403

分析资源关系实现HATEOAS

通过上面的分析,我们得到了每个 API 的返回 Http 状态码,而对于其返回体的设计,可以根据资源及其相关资源的关系来确定。例如 user 和 asset 有关联关系,那么对于GET /users/{uid} 而言,示例返回的 body 体如下:

{
  "data": {
      "url": "/users/1",
      "attributes": {
          "id": 1,
          "name": "felix",
          "email": "felix@example.com"
      },
      "relationships": {
          "assets": {
              "url": "/users/1/assets"
          }
      }
  }
}

用户通过该 API 可以得到用户的详细信息,而通过返回体可以拿到获取该用户下 assets 的API 而无需事先知道这个 API 的存在。理想情况下,资源与资源见的关系组成一张有向关系图,用户从任何一个资源入手,均可以遍历他有权限访问的所有资源。

自动化Doc (Swagger)

设计好的 RESTful API 可以借助 Swagger 形成文档,从而指导开发。最新的 Swagger 支持 Open API 3.0 规范,文档更新方便,并且支持文档的执行,具备较为完善的生态圈,推荐用其发布我们的 API 文档。

参考链接

Richardson Maturity Model

运用四色建模法进行领域分析

上一篇下一篇

猜你喜欢

热点阅读