CQRS - 允许从写入端调用读取端吗?

Tho*_*len 24 cqrs

我开始阅读有关CQRS的内容,我有点困惑.

是否允许在写入端调用读取端以获取其他信息?

http://cqrs.nu/Faq/command-handlers在这里他们说这是不允许的,但是在cqrs旅程代码中我发现他们称之为服务'IPricingService',它在内部使用DAO服务类.

那么我必须做些什么才能在我的聚合根中获得额外的信息?

Ale*_*rev 25

CQRS之旅不应被视为手册.这只是一个团队为CQRS而奋斗的故事,并且只有使用Microsoft堆栈的所有限制.本身,您不应该在命令处理程序或域逻辑中使用您的读取模型.但是,您可以从客户端查询读取模型,以获取命令所需的数据并验证命令.

由于我得到了一些关于这个答案的downvotes,我需要指出,我写的是模式中的既定实践.读取端不访问写入侧,写入侧也不从读取侧获取数据.

但是,"客户"的定义可能是讨论的主题.例如,我不相信面向公众的JS浏览器应用程序是一个合适的"客户端".相反,我会使用我的REST API层作为CQRS中的"客户端",而Web应用程序将只是该客户端的UI层.在这种情况下,REST API服务调用处理将是合法的读取端读取器,因为它需要验证所有UI层发送以防止伪造和验证某些业务规则.完成此工作后,将形成命令并将其发送到写入端.验证和其他所有内容都是同步的,然后命令处理是异步的.

更新:鉴于下面的一些分歧,我想指出Udi在2009年关于CQRS,特别是命令和验证的文章.

  • (1)你正在歪曲我的评论,我没有说设计模式是硬模板.(2)你在说什么"数据库"?Write模型适用于聚合,它只能通过聚合id从给定的BC中获取一个或模式聚合.(3)设计模式(顺便说一下,CQRS并不是一种设计模式,DDD都不是)都是用血写的,当人们把ORM放在适当的位置,创建数据模型并称之为"域"时,我已经看过太多次了.当我告诉他们他们有一个贫血模型时,他们说DDD不是一成不变的,我可以操纵开发人员的安慰.不用了,谢谢. (7认同)
  • 您的域无法从命令处理程序调用外部服务.命令处理程序应在有界上下文中运行.这甚至超出了最初的问题(和答案). (5认同)
  • 客户应始终真诚地操作它发出的命令将成功.您的命令处理程序不需要调用读取端进行验证.万一你得到两个相互矛盾的命令,其影响可能会发生冲突(例如,两个用户试图创建具有相同电子邮件地址的帐户),你应该让流程管理员发出纠正措施.在您的域名方面,命令效果被抵消的事实可能并不重要; 它首先被发送的事实仍然存在. (3认同)
  • 我上面的评论并不完全正确(或者我可以说 - 不正确)。您_可以_从任何地方调用外部服务,例如使用域服务。“DDD 的模式、原则和实践”一书给出了这种方法的一些很好的例子。通常,这不是命令处理程序的责任,聚合应该负责检查自己的不变量。但它与从写入端访问读取端无关。客户端应该评估读取端。 (3认同)
  • 我不同意.如果您需要命令包含处理程序验证命令所需的数据,那么您永远不能更改处理程序/域中的验证逻辑,也不会影响*client*.这清楚地向客户端暴露了太多的命令验证/领域知识,并且与客户端仅想表达意图相矛盾.恕我直言,更好的解决方案是为您的聚合根提供一个`PricingService`接口(它是无处不在的语言的一部分),然后根据需要实现接口 - 可能包括查询读取端. (2认同)
  • @AlexanderLanger这不是我发明的东西,这就是图案的设计方式.您可能会发现可以从命令处理程序中查询读取方,但这将不是所讨论的模式.如果查看CQRS上的任何图表,您将永远不会看到写入模式查询读取模型.它只能由客户阅读. (2认同)

Ash*_*ken 5

CQRS 常见问题解答 ( http://cqrs.nu/Faq ) 建议:

“如何在有界上下文之间进行通信?

仅限于其公共 API。这可能涉及订阅来自另一个有界上下文的事件。或者一个有界上下文可以像另一个有界上下文的常规客户端一样,发送命令和查询。”

因此,尽管在一个 BC 内不可能从写入端使用读取端,反之亦然,但另一个有界上下文或服务可以。本质上,这就像人类使用用户界面一样。