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

CQRS - is it allowed to call the read side from the write side?

我是从阅读 CQRS 开始的,但我有点困惑。

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

http://cqrs.nu/Faq/command-handlers 在这里他们说这是不允许的,但是在 cqrs journey 代码中我发现他们调用了一个服务 'IPricingService' 内部使用 DAO 服务 class.

那么我必须做什么才能在我的聚合根中获取更多信息?

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

因为我对这个答案投了反对票,所以我需要指出,我写的是模式中的既定做法。读端不访问写端,写端不从读端获取数据。

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

更新:鉴于下面的一些分歧,我想指出 Udi's article from 2009 谈论一般的 CQRS,特别是命令和验证。

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

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

完全按照他们publicAPI而言。这可能涉及订阅来自另一个限界上下文的事件。或者一个有界上下文可以像另一个有界上下文的常规客户端一样,发送命令和查询。"

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

是的,假设您已接受读取端的最终一致性。现在的问题是在哪里。尽管对此没有硬性规定,但最好将数据传递给命令处理程序,而不是在内部检索数据。据我观察有两种方式:

  • 在域服务上进行

基本上创建一个层,您可以在其中执行必要的查询来构建数据。这与执行 API 调用一样简单。但是,如果您的微服务 运行 在 Lambda/Serverless 上,它可能不太适合,因为我们倾向于避免 lambda 调用另一个 lambda 的情况。

  • 在客户端做

让客户端查询数据,然后将其传递给您。为防止篡改,请对其进行加密。您可以在验证 DTO 并将 DTO 转换为命令的同一位置实施解密。对我来说,这是一个更好的选择,因为它需要更少的移动部件。

我认为这取决于。 如果在您的体系结构中,“命令端”实时(同步)更新投影,您可以调用查询 api。 (虽然这看起来很奇怪)

但是,如果您的预测(查询端)是异步更新的,那么这样做是个坏主意。将有可能获得“不真实”的数据。

也许这种情况表明您应该解决设计问题。

例如:如果您认为您需要来自一个 context/domain 的信息,那么可能是域定义问题。

我假设是这样,因为在命令操作期间从自身(同一域)读取数据没有多大意义。 (在这种情况下可能是 API 设计问题)