Command Handlers
Command handlers are responsible for processing commands. They encapsulate the logic required to handle a command and ensure that the appropriate actions are taken within the domain model.
Command handlers typically reside in the application layer and serve as a bridge between the application's API and the domain model.
Facts
Command handlers are connected to an aggregate.
Command handlers are always connected to a single aggregate. One command handler per aggregate is the norm, with all aggregate commands handled within it.
A Command handler contains multiple handlers.
Each method in a command handler is connected to a specific command to handle and process.
Handlers are single-purpose.
Each handler method is responsible for handling a single type of command. This ensures that the command handling logic is focused and manageable.
Handlers should deal only with the associated aggregate.
Methods in a command handler should only deal with managing the lifecycle of the aggregate associated with it. Any state change beyong an aggregate's boundary should be performed by eventual consistency mechanisms, like raising an event and consuming it in the event handler of the other aggregate.
Command handlers invoke domain logic.
Command handlers do not contain business logic themselves. Instead, they invoke methods on aggregates or domain services to perform the necessary actions.
Command handlers coordinate actions.
Command handlers coordinate multiple actions related to each command. Primarily, this involves hydrating (fetching) the aggregate, invoking methods to perform state changes and persisting changes through a repository.
Handler methdos are enclosed in Unit of Work context.
Each handler method is automatically enclosed within a Unit of Work context. This means that all interactions with the infrastructure is packaged into a single transaction. This makes it all the more important to not mix multiple responsibilities or aggregates when handling a command.
Commands can be handled asynchronously.
While handling commands synchronously is the norm to preserve data integrity, it is possible to configure the domain to handle commands asynchronously for performance reasons.
Best Practices
Ensure idempotency.
Command handling should be idempotent, meaning that handling the same command multiple times should not produce unintended side effects. This can be achieved by checking the current state before applying changes.
Handle exceptions gracefully.
Command handlers should handle exceptions gracefully, ensuring that any necessary rollback actions are performed and that meaningful error messages are returned to the caller.
Validate commands.
Ensure that commands are validated before processing. This can be done in a separate validation layer or within the command handler itself.