CQRS命令和查询-它们是否属于域? [英] CQRS Commands and Queries - Do they belong in the domain?

查看:102
本文介绍了CQRS命令和查询-它们是否属于域?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在CQRS中,命令和查询是否属于域中?

In CQRS, do they Commands and Queries belong in the Domain?

事件是否也属于域中吗?

Do the Events also belong in the Domain?

如果是这种情况,那么命令/查询处理程序仅仅是基础架构中的实现?

If that is the case are the Command/Query Handlers just implementations in the infrastructure?

现在我将其布局如下:

Application.Common
Application.Domain
  - Model
    - Aggregate
  - Commands
  - Queries
Application.Infrastructure
  - Command/Query Handlers
  - ...
Application.WebApi
  - Controllers that utilize Commands and Queries

另一个问题,您从哪里提出事件?是命令处理程序还是域集合?

Another question, where do you raise events from? The Command Handler or the Domain Aggregate?

推荐答案

命令事件可能有非常不同的关注点。它们可能是技术方面的问题,集成方面的问题,领域方面的问题...

Commands and Events can be of very different concerns. They can be technical concerns, integration concerns, domain concerns...

我假设如果您询问领域,那么您正在实现领域模型(甚至使用Domain驱动设计)。

I assume that if you ask about domain, you're implementing a domain model (maybe even with Domain Driven Design).

如果是这种情况,我会尽力为您提供一个非常简化的响应,因此您可以有一个起点:

If this is the case I'll try to give you a really simplified response, so you can have a starting point:


  • 命令:是一种商业目的,您希望系统执行此操作。将命令的定义保留在域中。从技术上讲,它只是纯DTO。该命令的名称必须始终是命令性的 PlaceOrder ApplyDiscount 。一个命令只能由一个命令处理程序处理,如果无效,则可以将其丢弃(但是您可以应该在将命令发送到您的域之前使所有验证成为可能,这样它就不会失败)

  • 事件:这是过去发生的事情。对于企业来说,不可改变的事实是不可改变的。将域事件的定义保留在域中。从技术上讲,它也是DTO对象。但是,事件的名称应始终为过去的 OrderPlaced DiscountApplied 。活动通常是发布/订阅。一个发布者有许多处理程序。

  • Command: is a business intention, something you want a system to do. Keep the definition of the commands in the domain. Technically it is just a pure DTO. The name of the command should always be imperative "PlaceOrder", "ApplyDiscount" One command is handled only by one command handler and it can be discarded if not valid (however you should make all the validation possible before sending the command to your domain so it cannot fail)
  • Event: this is something that has happened in the past. For the business it is the immutable fact that cannot be changed. Keep the definition of the domain event it in the domain. Technicaly it's also a DTO object. However the name of the event should always be in the past "OrderPlaced", "DiscountApplied". Events generally are pub/sub. One publisher many handlers.

如果是这种情况,则命令/查询处理程序只是

If that is the case are the Command/Query Handlers just implementations in the infrastructure?

命令处理程序在语义上类似于应用程序服务层。通常,应用程序服务层负责协调域。它通常围绕业务用例构建,例如下订单。在这些用例中,通过聚合根,查询等调用业务逻辑(应始终封装在域中)。这也是处理横切关注点,例如事务,验证,安全性等。

Command Handlers are semantically similar to the application service layer. Generally application service layer is responsible for orchestrating the domain. It's often build around business use cases like for example "Placing an Order". In those use cases invoke business logic (which should be always encapsulated in the domain) through aggregate roots, querying, etc. It's also a good place to handle cross cutting concerns like transactions, validation, security, etc.

但是,应用层不是强制性的。它取决于功能和技术要求以及已做出的体系结构选择。
您的安排似乎正确。我最好将命令处理程序保留在系统的边界。如果没有适当的应用程序层,则命令处理程序可以充当用例编排器。如果将其放置在域中,将无法轻松处理交叉问题。这是一个权衡。您应该了解解决方案的优缺点。

However, application layer is not mandatory. It depends on the functional and technical requirements and the choices of architecture that has been made. Your layring seems correct. I would better keep command handlers at the boundary of the system. If there is not a proper application layer, a command handler can play a role of the use case orchestrator. If you place it in the Domain, you won't be able to handle cross cutting concerns very easily. It's a tradeoff. You should be aware of the pro and cons of your solution. It may work in one case and not in another.

关于事件处理程序。如果事件在相同的有界上下文中触发了另一个Aggregate的修改,或者事件触发了某些基础结构服务,我通常在

As for the event handlers. I handle it generally in


  • 应用程序层中进行处理

  • 基础设施层,如果事件需要拆分为多个使用者或整合其他有界上下文。

无论如何,您都不应盲目遵守规则。总是存在折衷,可以找到不同的方法。

Anyway you should not blindly follow the rules. There are always tradeoffs and different approaches can be found.


另一个问题是,您从何处引发事件?是命令处理程序还是域集合?

Another question, where do you raise events from? The Command Handler or the Domain Aggregate?

我是从域集合根执行此操作的。因为该域负责引发事件。
一直以来都有一个技术规则,如果在汇总中仍然存在更改问题,则不应发布事件,反之亦然,我采用了事件采购中使用的方法,这很实用。我的聚合根有一个未发布事件的集合。在我的存储库的实现中,我将检查未发布的事件的集合,并将它们传递给负责发布事件的中间件。易于控制的是,如果有例外情况持久化了聚合根,则不会发布事件。有人说这不是存储库的责任,我同意,但是谁在乎。有什么选择。是否具有用于事件发布的笨拙代码,其中涉及所有基础架构问题(事务,异常处理等),还是在基础架构层处理所有问题时都​​采用实用的代码?我都做到了,并且相信我,我更愿意务实。

I'm doing it from the domain aggregate root. Because the domain is responsible for raising events. As there is always a technical rule, that you should not publish events if there was a problem persisting the changes in the aggregate and vice-versa I took the approach used in Event Sourcing and that is pragmatic. My aggregate root has a collection of Unpublished events. In the implementation of my repository I would inspect the collection of Unpublished events and pass them to the middleware responsible for publishing events. It's easy to control that if there is an exception persisting an aggregate root, events are not published. Some says that it's not the responsibility of the repository, and I agree, but who cares. What's the choice. Having awkward code for event publishing that creeps into your domain with all the infrastructure concerns (transaction, exception handling, etc) or being pragmatic and handle all in the Infrastructure layer? I've done both and believe me, I prefer to be pragmatic.

总而言之,没有单一的做事方法。始终了解您的业务需求和技术要求(可伸缩性,性能等)。而不是基于此做出选择。我已经描述了在大多数情况下通常可以完成的工作,并且可以奏效。只是我的意见。

To sum up, there is no a single way of doing things. Always know your business needs and technical requirements (scalability, performance, etc.). Than make your choices based on that. I've describe what generally I've done in the most of cases and that worked. It's just my opinion.

这篇关于CQRS命令和查询-它们是否属于域?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆