【问题标题】:Difference between CQRS and CQSCQRS和CQS之间的区别
【发布时间】:2016-03-19 06:03:27
【问题描述】:

我正在学习什么是 CQRS 模式,并且知道还有 CQS 模式。

当我尝试搜索时,我发现了很多关于 CQRS 的图表和信息,但没有找到太多关于 CQS 的信息。

CQRS模式中的关键点

在 CQRS 中有一个模型可以写(命令模型)和一个模型可以读(查询模型),它们是完全分开的。

CQS 与 CQRS 有何不同?

【问题讨论】:

    标签: cqrs command-query-separation ncqrs


    【解决方案1】:

    CQS(命令查询分离)和CQRS(命令查询职责分离)非常相关。您可以将 CQS 视为处于类或组件级别,而 CQRS 更多地处于有界上下文级别。

    我倾向于认为 CQS 是微观层面的,而 CQRS 是宏观层面的。

    CQS 规定了用于查询或写入模型的单独方法:查询不会改变状态,而命令会改变状态但没有返回值。它是由 Bertrand Meyer 设计的,是他在 Eiffel 编程语言方面的开创性工作的一部分。

    CQRS 规定了类似的方法,但它更多的是通过您的系统的路径。查询请求采用与命令不同的路径。查询返回数据而不改变底层系统;该命令会更改系统但不返回数据。

    Greg Young 汇总了几年前的 CQRS 是什么的pretty thorough write-up,并探讨了 CQRS 如何是 CQS 的演变。这份文件在几年前向我介绍了 CQRS,我觉得它仍然是一个非常有用的参考文件。

    【讨论】:

      【解决方案2】:

      这是一个老问题,但我会尝试回答它。我不经常在 StackOverflow 上回答问题,所以如果我在链接到事物、写长答案等方面做了超出社区范围的事情,请原谅我。

      CQRS 和 CQS 之间有很多区别,但是 CQRS 在其定义中使用 CQS!让我们从定义两者开始,然后我们可以讨论差异。

      CQS 根据返回值定义了两种类型的消息:无返回值(void)指定这是一个命令;返回值(非 void)指定此方法是 Query。

      • 命令更改信息
      • 查询返回信息

      命令改变状态。查询没有。

      现在是 CQRS,它使用与 CQS 相同的定义来表示命令和查询。 CQRS 说的是我们不希望 一个对象 具有 Command 和 Query 方法。相反,我们想要两个对象:一个包含所有命令,一个包含所有查询。

      整体思路很简单; 之后,事情变得有趣。网上有很多讨论,我讨论了一些相关的属性(对不起,在这里输入太多了!)。

      【讨论】:

        【解决方案3】:
        • CQS 是关于命令和查询的。它不关心模型。您以某种方式分离了用于读取数据的服务和用于写入数据的其他服务。
        • CQRS 是关于用于写入和读取的单独模型。当然,写模型的使用通常需要读一些东西来完成业务逻辑,但你只能在读模型上做读。单独的数据库是最先进的。但是想象一下单个数据库,在 ORM 中建模具有单独的读写模型。这通常已经足够好了。

        我发现人们经常说他们在有 CQS 时会练习 CQRS。

        【讨论】:

          【解决方案4】:

          最大的不同是 CQRS 对命令和查询使用单独的数据存储。查询存储可以使用不同的技术,例如文档数据库,也可以只是同一数据库中的非规范化模式,这样可以更轻松地查询数据。

          数据库之间的数据通常使用服务总线之类的东西异步复制。因此,查询存储中的数据最终是一致的(将在某个时间点存在)。应用程序需要考虑到这一点。虽然可以使用相同的事务(相同的数据库或两阶段提交)在两个存储中写入,但出于可伸缩性的原因,通常不建议这样做。

          CQS 架构从相同的数据存储/表中读取和写入。

          【讨论】:

          • 为免生疑问 - 应用 CQRS 时,允许您使用单独的数据存储,但这不是必需的。您仍然可以使用一个数据存储“执行 CQRS”。
          • Greg Young 不止一次提到了最终一致性,但它似乎总是被排除在 SO 的答案之外(我已经看到了。)
          【解决方案5】:

          阅读发明者 Greg Young 的回答

          我认为,就像“依赖注入”一样,这些概念是如此简单且被认为是理所当然的,以至于它们具有花哨的名称这一事实似乎驱使人们认为它们比实际更重要,尤其是 CQRS 经常与它们一起被引用事件溯源。

          • CQS 是读取到更改状态的方法的分离;不要在一个方法中同时做这两个。这是微观层面。

          • CQRS 将此概念扩展到更高级别的机器-机器 API、消息模型和处理路径的分离。

          所以 CQRS 是您应用于 API 或外观中的代码的原则。

          我发现 CQRS 本质上是 SOLID 中非常强大的 S,将这种分离深深地推入了开发人员的心中,以产生更易于维护的代码。

          我认为 Web 应用程序不适合 CQRS,因为通过表示传输改变状态意味着命令和查询是同一请求-响应的两个方面。表示是命令,响应是查询。

          例如,您发送订单并接收所有订单的视图。

          想象一下,如果网站的代码被分解为命令端和查询端。路由操作处理代码需要落入其中一方,但两者兼而有之。

          想象一个更强大的隔离,如果将代码移动到两个不同的可编译代码库中,那么网站将接受表单的 POST,但用户必须浏览到另一个网站 URL 才能查看操作的影响。这显然是疯了。一种解决方法是始终重定向,但这并不是真正的 RESTful,因为理想的 REST 应用程序是下一个表示包含超文本以驱动下一个状态转换等等。

          鉴于网站是人与机器(或机器与机器)之间的 REST API,这也包括 REST API,尽管其他类型的 HTTP 消息传递 API 可能非常适合 CQRS。

          网站范围内的服务或外观显然可以很好地与 CQRS 配合使用,尽管操作处理程序会位于此边界之外。

          CQS on Wikipedia

          【讨论】:

          • 我只是偶然发现了这个,想补充一点。您提到“我认为 Web 应用程序不适合 CQRS,因为通过表示传输的状态突变意味着命令和查询是同一请求 - 响应的两个方面。表示是命令,响应是查询。”这其实是一种常见的说法!不过让我问一下,你有没有看过原子提要是如何工作的?可以表示多少条数据类似于说一个原子提要?
          • 嗨,格雷格,我开始写作,然后我停下来,认为如果你回答了 OP 的问题,我们都会得到更好的服务。我希望其他当局能尽快解决这些问题。我经常不确定。我经常无法从第五手意见或合理的解释中分辨出什么是正确的,我经常学习困难的方法。我客户的 15 位开发人员使用 CQRS 代码结构构建了许多 API,这与我的理解相矛盾,因为与网站一样,命令端的 POST 处理程序也执行许多查询以构建丰富的返回视图和有效的下一步操作链接。
          • 这里已经有一两个链接链接我关于这个主题的材料,这就是为什么我没有[不得不剪断]“想象一个更强大的隔离,如果代码被移动到两个不同的可编译代码库..” 这更像是一个 REST 问题,而不是 CQRS。没有什么可以说明数据是如何处理的。 POST 可用于创建事件 /streams/{stream} 似乎是一个可能的目标(您同意吗?)。 GET 可能会转到 /streams/{stream} 以获取信息。没有规定所有对该资源的请求必须由同一个服务等处理。
          • 如果不清楚(对不起,简短的 cmets),POST 也很常见,它会返回一个 URI,然后客户端应该针对最新状态 发出 GET通知(想想异步进程)
          • 谢谢格雷格。我同意。我确实了解您在发布事件和使用提要方面的目的,但认为最好在可以写更多内容的答案中进行解释。将 303 返回到每个突变通常不是 RESTful,其中状态转换通常会遇到包含一个或多个进一步链接或表单的响应,因此这属于“其他类型的 HTTP 消息传递 API 可能非常适合 CQRS “我想。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-12-25
          • 2020-05-10
          • 2014-09-20
          • 2010-10-28
          • 2015-10-04
          • 2012-08-12
          • 2011-02-18
          相关资源
          最近更新 更多