47

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?

Right now I have it layed out like this:

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?

Sam
  • 15,336
  • 25
  • 85
  • 148

3 Answers3

63

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

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:

  • 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.

As for the event handlers. I handle it generally in

  • Application layer if the event triggers modification of another Aggregate in the same bounded context or if the event trigger some infrastructure service.
  • Infrastructure layer if the event need to be split to multiple consumers or integrate other bounded context.

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.

Marc Wittke
  • 2,991
  • 2
  • 30
  • 45
Tomasz Jaskuλa
  • 15,723
  • 5
  • 46
  • 73
  • Great straight forward answer! Regarding the concern of raising events from the aggregate, how do you handle the command/event bus (when using a third party tool like Mediatr) and keeping it out of the domain? – Sam Aug 26 '15 at 17:03
  • I don't know Mediatr but generally what I do is to add raised events into aggregate root's collection `Unpublished` ( I don't fiddle with any middleware in the domain). Then when the aggregate root is ready to be persisted in the Infrastructure, I inspect the collection and publish it on the middleware of your choice. This is the best place. It is what we do in EventSourcing. I've tested many other approaches (static domain event publishers and the so) but these are not great and add always overhead and make the code brittle. – Tomasz Jaskuλa Aug 26 '15 at 17:11
  • So what piece persists the aggregate root? I am so used to n-tier (UI --> Services --> Repository --> Database), this is a little confusing to me still. I totally dig it though, makes a ton of sense. – Sam Aug 26 '15 at 17:34
  • 4
    The repository persists the AR. But the command handler invokes the repository. About publishing events, I wouldn't publish them from the repository, it's not really its responsibility. I also disagree with the command/query handlers are being part of the infrastructure . If you go that way, then pretty much every domain use case and every query is part of the infrastructure. You end up with a huge infrastructure and a domain that has only concepts and no processes/use cases. – MikeSW Aug 26 '15 at 18:48
  • If you use the repository pattern you would typically have an implementation in the infrastructure layer. In the implementation of you repository you would inspect the collection of `Unpublished` events and pass them to your middleware responsible for publishing events. Is this clearer? – Tomasz Jaskuλa Aug 26 '15 at 19:23
  • @MikeSW - So if you put the Handlers into the Domain, would you also have an Interface for a Repository in the Domain that could be implemented in the Infrastructure? And then what about the Event Publishing? You can't use a third party tool, and you write your own bus? Easy enough right? And if I understand you things like Email, etc are the responsibility of the Event Handler. Like OrderCreatedEvent --> Send off an email for instance? The thing I am struggling with the most is how to keep third party tools out of the Domain, but still be able to use them. – Sam Aug 26 '15 at 19:32
  • @MikeSW - Seems like you are tied to an abstraction for every thing. Take for instance an Amazon SQS Queue Message, you have to write a wrapper interface around it in the Domain, and then implement it in the Infrastructure? – Sam Aug 26 '15 at 19:33
  • @TomaszJaskuλa It was clear before. The point is I may publish events without persisting something and a repository's purpose is not making sure the events are published. For me this is a bit smelly. – MikeSW Aug 26 '15 at 20:03
  • @Sam You can use 3rd party tools. Btw, all handlers are technical implementations of some use case. In your example, sending an email when an order is created is still a business use case (why would you send an email otherwise?). However the implementation might be just the preparation of a command like SendEmailToSales and the handler for that will be part of a Notifications component or just infrastructure. – MikeSW Aug 26 '15 at 20:10
  • @Sam Re: the amazon example, the Domain doesn't know about queues. The queue is an implementation detail for something but I can't think of a domain use case that needs to use a queue. In DDD you really need to be clear about the difference between the Domain/Strategic view and the implementation/technical details. Btw, a queue or a db is more than a 3rd party tool, it's an external service. Something like automapper or an Event Sourcing base class are 'just' 3rd party tools that can be used inside the Domain. – MikeSW Aug 26 '15 at 20:16
  • Publishing from inside the repository is the best trade off for me. Repository is in the infrastructure already so you can add another dependency on infrastructure middleware. I've been in publishing through a static domain publisher from the aggregate root and other awkward solutions. It works from the theory but never in practice – Tomasz Jaskuλa Aug 26 '15 at 20:23
  • By the way the command handler semantically replaces the application service. So, no it's not in the domain for me – Tomasz Jaskuλa Aug 26 '15 at 20:29
  • @MikeSW - So you are fine with having dependencies like AutoMapper in your Domain? And if Handlers semantically replace the service layer, then they would be responsible for sending a message to a queue like SQS? In which case you would have to write a wrapper around the queue sending mechanism? I really wish there was some sample code out there that showed some of these concerns being solved. – Sam Aug 26 '15 at 20:43
  • 1
    @TomaszJaskuλa A domain use case can be implemented in a command handler. Otherwise, your domain never has use cases, only concepts and business use cases are using concepts according to business rules. You're basically telling me that your application services contain the business rules of a business transaction. – MikeSW Aug 26 '15 at 21:04
  • 1
    @Sam You're looking for technical solutions but you need to understand the mindset. A domain is coupled to something when a domain object (from a design point of view) is coupled to that something.For ex, your entities depend on a persistence implementation detail or expose behaviour needed by the UI. Automapper and others are generic components. You are using the .Net framework by default everywhere, that's a 3rd party lib right there. The coupling is always a design issue, it's not about what libraries you're using. – MikeSW Aug 26 '15 at 21:09
  • I'm not telling it and you imply it what is wrong. Application layer is a use case so is the command handler. That's why I said it's semantically the same. Anyway I don't think that arguing about details will help @Sam. – Tomasz Jaskuλa Aug 26 '15 at 21:34
  • I've made an update to my response. Some more details. – Tomasz Jaskuλa Aug 26 '15 at 22:20
14

In some implementations, Commands and handlers are in the Application layer. In others, they belong in the domain. I've often seen the former in OO systems, and the latter more in functional implementations, which is also what I do myself, but YMMV.

If by events you mean Domain Events, well... yes I recommend to define them in the Domain layer and emit them from domain objects. Domain events are an essential part of your ubiquitous language and will even be directly coined by domain experts if you practise Event Storming for instance, so it definitely makes sense to put them there.

What I think you should keep in mind though is that no rule about these technical details deserves to be set in stone. There are countless questions about DDD template projects and layering and code "topology" on SO, but frankly I don't think these issues are decisive in making a robust, performant and maintainable application, especially since they are so context dependent. You most likely won't organize the code for a trading system with millions of aggregate changes per minute in the same way that you would a blog publishing platform used by 50 people, even if both are designed with a DDD approach. Sometimes you have to try things for yourself based on your context and learn along the way.

guillaume31
  • 13,738
  • 1
  • 32
  • 51
3

Command and events are DTOs. You can have command handlers and queries in any layer/component. An event is just a notification that something changed. You can have all type of events: Domain, Application etc.

Events can be generated by both handler and aggregate it's up to you. However, regardless where they are generated the command handler should use a service bus to publish the events. I prefer to generate domain events inside the aggregate root.

From a DDD strategic point of view, there are just business concepts and use cases. Domain events, commands, handlers are technical details. However all domain use cases are usually implemented as a command handler, therefore command handlers should be part of the domain as well as the query handlers implementing queries used by the domain. Queries used by the UI can be part of the UI and so on.

The point of CQRS is to have at least 2 models and the Command should be the domain model itself. However you can have a Query model, specialised for domain usage but it's still a read (simplified) model. Consider the command model as being used only for updates, the read model only for queries. But, you can have multiple read models (to be used by a specific layer or component) or just a generic (used for everything query) one.

MikeSW
  • 16,140
  • 3
  • 39
  • 53
  • Sorry, I am a little confused. Commands and Queries are part of the Domain Model while their handlers are not? The part I struggle with is when using a third party component like Mediatr for the Command/Query bus, how do you utilize that without polluting the Domain with it? How would one fir an event from an Aggregate using this component, and also keep it out of the Domain? – Sam Aug 26 '15 at 04:00
  • 1
    @Sam Commands and Events are **domain contracts**. They will be handled or send by the domain. So they must be known by the domain and the other parts, but they are not really part of the domain itself. It is more like a language. You are a domain and you know a language. But the language is not part of you, just a contract to communicate with others. – Sir Rufo Aug 26 '15 at 07:58
  • @MikeSW "regardless where they are generated the command handler should use a service bus to publish the events" - why ? – guillaume31 Aug 26 '15 at 13:17
  • @MikeSW "therefore command handlers should be part of the domain" - they can also be placed in the Application layer https://books.google.com/books?id=0-fGBwAAQBAJ&pg=PA675&lpg=PA675&dq=cqrs+%22command+handler%22+%22application+service%22&source=bl&ots=mp8LcLDZjq&sig=xxH_4wR9fX9oI4MnQQ8p5cySYUE&hl=fr&sa=X&redir_esc=y#v=onepage&q=cqrs%20%22command%20handler%22%20%22application%20service%22&f=false – guillaume31 Aug 26 '15 at 13:19
  • 1
    @guillaume31 Because it's not the service's nor the aggregate's concern to publish the events, publishing is an infrastructural concern, so it's the service bus' job. Command handlers implementing domain use cases _should_ be part of the domain. The application layer might or might not exist, it depends on the app architecture (I prefer the business component approach). And I wish people would stop quoting books to me, they don't contain the single and ultimate holy truth. I should write a DDD book too, so that I can quote myself.. – MikeSW Aug 26 '15 at 14:19
  • 1
    A service bus is a technical option, not a necessity : https://lostechies.com/jimmybogard/2012/08/22/busting-some-cqrs-myths/ http://www.quora.com/Does-CQRS-Require-a-Service-Bus – guillaume31 Aug 26 '15 at 14:22
  • I'm only quoting books because you wrote "events, commands, handlers are technical details", which is very true, but then went on with a series of "shoulds" concerning technical details. I'm quoting books to point out there are alternative technical options. – guillaume31 Aug 26 '15 at 14:25
  • 1
    @MikeSW A command handler is just a handler for commands. A command handler can route a domain command to a domain where there are domain command handlers that will handle the domain commands. Maybe you have to point more on this ;o) – Sir Rufo Aug 26 '15 at 14:26
  • 1
    @Sam Don't confuse the principles of CQRS (separate models) with an CQS implementation, what Mediatr does. You can do CQRS without having command and query handlers, and use those handlers without doing CQRS. The domain is not polluted because these are implementation details and tools, it's a difference between a properly _designed_ model and its actual technical implementation. The design can be good but for the implementation we need to do some small technical compromises. For ex, event sourcing needs methods that are not AR behaviour. It's a small price to pay to get other other benefits – MikeSW Aug 26 '15 at 14:29
  • @guillaume31 CQRS != domain events. The service bus is for the domain events pattern, nothing related to CQRS. And the alternative to a durable service bus is unreliable if the app crashes. Btw, _shoulds_ are not _musts_ . – MikeSW Aug 26 '15 at 14:32
  • @SirRufo Yeah,the problem is sometimes there is a very thin line between the application use cases and the domain use cases. – MikeSW Aug 26 '15 at 14:41
  • @MikeSW The arguments in the first article I linked to remain valid when you add Event Sourcing to the mix. You don't need messaging middleware to do ES, although you could say that some popular event databases do something pretty close to it out of the box. – guillaume31 Aug 26 '15 at 15:13
  • @guillaume31 My ES example wasn't related to publishing events. But you need messaging middleware with Domain Events regardless of ES. – MikeSW Aug 26 '15 at 15:28
  • @MikeSW How exactly is `"the command handler should use a service bus to publish the events"` unrelated to publishing events ? That kind of statement is precisely why newcomers get away obsessed with technical anecdote and ignorant of DDD/CQRS/ES fundamentals. – guillaume31 Aug 26 '15 at 15:41
  • @guillaume31 Do you cherry pick my words out of context to make your point? Where do you see that phrase in my ES example? And that example was given to show that we need to do some compromises. Totally unrelated to Domain events (DE) and their publishing. And for someone learning about ES, DDD etc, I will state: DE and Event Sourcing are _different_ things . ES uses domain events for a specific purpose (state as a stream). The application uses domain events to communicate changes outside a bounded context. They _can_ be used together but they are different concepts. – MikeSW Aug 26 '15 at 15:51
  • Do you guys have any suggestions on a good place to learn more on this? Possibly with code samples? – Sam Aug 26 '15 at 15:51
  • 2
    @Sam DDD can't be learn from code examples because the code is the _result_ of the process. You can only learn it but doing it, failing, doing it again, until things make sense. There is no substitute for experience and the only thing close to the real thing is to read or watch domain modelling examples (code is irrelevant). And probably you already know about the famous books of E.Evans or V.Vernon. – MikeSW Aug 26 '15 at 15:54
  • 1
    @Sam I also have some posts about [DDD modelling](http://blog.sapiensworks.com/topics/#domain-driven-design) – MikeSW Aug 26 '15 at 15:57