【问题标题】:RESTful API Design and CQRSRESTful API 设计和 CQRS
【发布时间】:2020-10-09 20:49:10
【问题描述】:

我在考虑如何让 RESTFul API 更能揭示意图。我在各种博客中看到的一个常见模式是,传统的 REST API 会导致

禁止玩家 -> POST /players.

但是我要换一个更显意图的界面,我可以用

禁止玩家 -> POST /players/{ playerid }/banPlayer

我觉得第二个更暴露意图。

我从团队中得到的普遍反对意见是第二个不符合 start REST 样式。

目前我也无法摆脱 RESTful API。

我想听听您对此的看法。

【问题讨论】:

  • REST 根本不关心 URI 设计,因为它只是一种将客户端与服务器分离的技术,客户端不应尝试从 URI 中提取知识,因为如果服务器更改 URI,这可能会中断在某一点。相反,客户端和 API 都应该使用关系名称并支持表达某些语义的特殊媒体类型。媒体类型只是对语法及其要交换的数据语义的纯文本描述。
  • 怎么样(有点滑稽)BAN /players/{playerid} HTTP/3
  • 除了标签和标题,我想你忘了提到CQRS在这方面有什么作用。

标签: rest cqrs


【解决方案1】:

对于 Restful API 设计,围绕如何将 actions 应用于资源有两种思想流派。

  1. 您在 Uri 中描述要对资源采取的操作:

    请求 Uri:
    POST /players/{id}/ban

    注意:只需使用ban - 我们已经知道资源是一个玩家,它在基础 Uri 中。

  2. 您可以在请求正文中包含操作:

    请求Uri:
    POST /players/{id}

    请求正文:
    { 'action': 'ban' }

您可以选择任何一种方式 - 无论您喜欢哪种方式,都有很多关于两者的讨论,但最终两者都是正确的。

注意:

我在这里的假设是,禁止玩家不仅仅是更新其中的一部分,而是与玩家相关的系统操作(或状态转换)。否则,如果它只是对播放器资源的更新,则应酌情使用 PATCH 或 PUT 进行处理。

一些讨论供参考:

如果你做一些谷歌搜索,还有更多......

【讨论】:

【解决方案2】:

长话短说:不应该强制透露意图,但如果您想添加一些 DDD 来说明此 API 的外观,那么没有什么可以阻止您这样做

根据 RESTful Web API 的 HATEOAS 约束(此约束是 REST 的“统一接口”功能的重要组成部分,如 Roy Fielding 的博士论文中所定义),软件 你的 API 客户端不应该关心 URL。每个可能和允许的操作都应包含在响应中,并带有相应的link relation 和 URI。这样,您只需对链接关系进行硬编码。

但是,此约束不会阻止您使 API 为试图了解整体架构的人类客户端提供更多意图。我建议您选择这条路径,因为人类用户至少与他们编写的软件一样重要。

Roy Fielding 在his blog post 上写了这篇文章。

【讨论】:

    【解决方案3】:

    既然您要求 RESTful 方式不是最好的方式,这是我的想法。

    您的 RESTful URI 选项包括:

    • /players
    • /players/{ playerid }/banPlayer
    • /player-banning
    • /entities?action=ban_player&method=PUT
    • /banana
    • 除此之外,REST 并没有规定您的 URI 应该是什么样子

    RESTful 方式是纯粹通过超文本公开下一个可用状态的知识。要进行 REST,您必须使用超文本作为应用程序状态引擎 (HATEOAS)。依赖客户端的 URI 知识依赖于带外知识,这与 REST 是对立的。

    您的资源不需要直接映射到您的业务对象。如果您选择,您可以将用户意图本身表示为资源,例如被禁止的玩家事件资源。您可以向它发布一些关于要禁止哪个玩家的信息,随后的 GET 将提供有关该事件的信息。

    哦,仅仅因为 REST 不关心你的 URI 是什么,并不意味着你不应该这样做。您只需要使用不同的标准来决定什么是最好的。

    【讨论】:

      【解决方案4】:

      根据 REST API 方法,您需要在 URI 中使用您的实体,因此,banPlayer 不是实体,您不能使用它。 我建议使用 PUT 方法更新您的记录。 Here 你可以阅读更多关于规则的信息。实际上,关于 URIs 的第一部分只是关于您的情况。

      【讨论】:

        【解决方案5】:

        我从团队中得到的普遍反对意见是第二个不符合 start REST 样式。

        简单的答案是:API 中的一致性是有价值的,无论是否是 REST。所以“这不是我们在这里的做法”将胜过“但 REST 说”。

        API 中 URI 的拼写很像代码中方法名称的拼写。对于不同的风格有很多不同的论据,但“本地惯例”本身就是一个强有力的论据。

        也就是说——REST 并不关心你对标识符使用什么拼写。

        这就是Fielding had to say in 2008

        REST API 应该将几乎所有的描述性工作都用于定义用于表示资源和驱动应用程序状态的媒体类型,或定义扩展关系名称和/或现有标准媒体的超文本启用标记类型。描述在感兴趣的 URI 上使用什么方法所花费的任何努力都应该完全在媒体类型的处理规则范围内定义(并且在大多数情况下,已经由现有媒体类型定义)。 [这里的失败意味着带外信息正在推动交互而不是超文本。]

        In band 将把 URI 包含在资源的表示中——将其放入 HTML 文档中的表单描述中。带外是记录 URI,并期望人们用它做正确的事情。

        注意:人类可读的 URI 没有任何问题,或者记录应该使用的 URI。但是请注意,即使编写您的浏览器的人没有阅读 stack overflow's API documentation,您也可以向 stackoverflow 发布问题——这就是 REST。

        【讨论】:

          【解决方案6】:

          这篇 Google Cloud 文章 API design: Understanding gRPC, OpenAPI and REST and when to use them 阐明了 REST 与 RPC 的争论。 REST 与以实体为中心的 API 更相关,而 RPC 与以动作为中心的 API(和 CQRS)更相关。带有超媒体控件的最成熟的REST level 3 仅适用于具有简单状态模型的实体。

          首先了解并评估 REST 对您的案例的好处。许多 API 是 REST-ish 而不是 RESTful。 OpenAPI 实际上是 RPC 映射和 HTTP 端点,但这并不妨碍它被广泛采用。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-02-11
            • 2017-01-02
            • 1970-01-01
            • 1970-01-01
            • 2018-12-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多