【发布时间】:2016-03-19 06:03:27
【问题描述】:
我正在学习什么是 CQRS 模式,并且知道还有 CQS 模式。
当我尝试搜索时,我发现了很多关于 CQRS 的图表和信息,但没有找到太多关于 CQS 的信息。
CQRS模式中的关键点
在 CQRS 中有一个模型可以写(命令模型)和一个模型可以读(查询模型),它们是完全分开的。
CQS 与 CQRS 有何不同?
【问题讨论】:
标签: cqrs command-query-separation ncqrs
我正在学习什么是 CQRS 模式,并且知道还有 CQS 模式。
当我尝试搜索时,我发现了很多关于 CQRS 的图表和信息,但没有找到太多关于 CQS 的信息。
在 CQRS 中有一个模型可以写(命令模型)和一个模型可以读(查询模型),它们是完全分开的。
CQS 与 CQRS 有何不同?
【问题讨论】:
标签: cqrs command-query-separation ncqrs
CQS(命令查询分离)和CQRS(命令查询职责分离)非常相关。您可以将 CQS 视为处于类或组件级别,而 CQRS 更多地处于有界上下文级别。
我倾向于认为 CQS 是微观层面的,而 CQRS 是宏观层面的。
CQS 规定了用于查询或写入模型的单独方法:查询不会改变状态,而命令会改变状态但没有返回值。它是由 Bertrand Meyer 设计的,是他在 Eiffel 编程语言方面的开创性工作的一部分。
CQRS 规定了类似的方法,但它更多的是通过您的系统的路径。查询请求采用与命令不同的路径。查询返回数据而不改变底层系统;该命令会更改系统但不返回数据。
Greg Young 汇总了几年前的 CQRS 是什么的pretty thorough write-up,并探讨了 CQRS 如何是 CQS 的演变。这份文件在几年前向我介绍了 CQRS,我觉得它仍然是一个非常有用的参考文件。
【讨论】:
这是一个老问题,但我会尝试回答它。我不经常在 StackOverflow 上回答问题,所以如果我在链接到事物、写长答案等方面做了超出社区范围的事情,请原谅我。
CQRS 和 CQS 之间有很多区别,但是 CQRS 在其定义中使用 CQS!让我们从定义两者开始,然后我们可以讨论差异。
CQS 根据返回值定义了两种类型的消息:无返回值(void)指定这是一个命令;返回值(非 void)指定此方法是 Query。
命令改变状态。查询没有。
现在是 CQRS,它使用与 CQS 相同的定义来表示命令和查询。 CQRS 说的是我们不希望 一个对象 具有 Command 和 Query 方法。相反,我们想要两个对象:一个包含所有命令,一个包含所有查询。
整体思路很简单; 在之后,事情变得有趣。网上有很多讨论,我讨论了一些相关的属性(对不起,在这里输入太多了!)。
【讨论】:
我发现人们经常说他们在有 CQS 时会练习 CQRS。
【讨论】:
最大的不同是 CQRS 对命令和查询使用单独的数据存储。查询存储可以使用不同的技术,例如文档数据库,也可以只是同一数据库中的非规范化模式,这样可以更轻松地查询数据。
数据库之间的数据通常使用服务总线之类的东西异步复制。因此,查询存储中的数据最终是一致的(将在某个时间点存在)。应用程序需要考虑到这一点。虽然可以使用相同的事务(相同的数据库或两阶段提交)在两个存储中写入,但出于可伸缩性的原因,通常不建议这样做。
CQS 架构从相同的数据存储/表中读取和写入。
【讨论】:
阅读发明者 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 配合使用,尽管操作处理程序会位于此边界之外。
【讨论】: