They aren't really that incompatible. We have these two principles:
- CQRS says that the business logic is enforced inside the command
- DDD says that your domain model handles the business logic
So to keep both happy, you have your Command Handler work with your domain model. And to keep it Event Sourced, the only thing that needs to be altered is how you store changes to the model.
In short the answer is "yes". The Command handler invokes your domain model which enforces the business logic.
Where you may have a slight disconnect in this thinking is in how you work with the data. It's best to think of the events as facts you are storing, which when played back will provide a fully constituted model.
The layer which handles storing changes will be working with the discrete facts (events) that describe what happened. When you retrieve that data, you can use a Projection to reconstitute your domain model.
In Domain Driven Design, you typically separate infrastructure from the domain model using interfaces. For example, you have the concept of a "Repository", and that interface is part of the domain, but the implementation uses your infrastructure.
The idea is that it is less important how the state is stored and more important how to find the domain models to perform work on. So the Repository implementation is free to change the type of data storage you use (database, flat files in a blob store, graph, etc.) because those are implementation details. The core business functionality is still in the domain model.
This leads to easier mocking in your system since you only have to mock the repository, rather than deal with the minutia of how to prep data.
Distinction between Event Sourced and Event Driven:
- Event Sourced means you use your events as the stored state of your model
- Event Driven means you send messages to invoke commands
This distinction can be lost because both use "events". One team I know of that adopted event sourcing changed the name "events" to "facts" to help the team think about it properly.
An event in Event Sourced is typically a past tense fact or record. For example:
The contrast with Event Driven is that the events are typically present tense commands for other services to react to. They are very different things. Examples of event driven names:
There are more than one way to work with event sourcing. For example, you can publish the past tense event on a topic queue so that anyone listening can react to that fact and update their environments. Or, those other services can query for updates to the entities they care about.
You can use both Event Sourcing and Event Driving together, but it can be very confusing if you don't disambiguate your terminology like the team I referred to above.