We are implementing an enterprise system that's based on Domain-Driven design, Clean Architecture and CQRS.
However, I'm somehow confused with the concepts and usages of handlers in CQRS. Every example I've seen, the execution of the command is delegated to the corresponding command's handler.
I'd like to know is it possible to execute the Commands (or Queries) without handlers in CQRS? (or we can't have one without the other?).
If so, can we dispatch the commands directly to the underlying Clean Architecture layers (E.g. Use case, Repository,...) in order to proceed them (without interfering handlers)?
And what about the Queries? Do they need Query Handlers or we could just simply call the read model directly in our REST APIs?
Dealing with too many architecture patterns at the same time can have this effect; you are not alone 😊.
Typical examples of commands in CQRS contain a Command
and Command Handler
, but they are to illustrate some important principles:
Command
s and forgetCommand
s don't return any data to the calleeCommand Handler
s pick up the Command
from message queues and process themCommand
s will result in changes that become visible/available at a later point in time, through eventual consistencyYou need not use Command
+ Command Handler
s if your only concern is to separate the Write from the Read layer. You could call simple Application Service methods from the API layer. Just ensure you follow the principles of CQRS, like not sharing code between the write and read sides, not returning data to the callee on write
/changes, and having an event pipeline to construct Query models.
It would also be useful to do the actual change as part of a background worker, instead of the Application Service, to provide an asynchronous working model.
Having said that, following a Command
+ Command Handler
pattern would help you tremendously, though, by making it easier to reason with architecture decisions during development.
Query models, on the other hand, are typically built to address API requests directly. In other words, the same aggregate or concept in your domain may have multiple Query model structures constructed on it, to satisfy different API requirements. You typically return an already constructed Query Model
(without any post-processing) in return to API calls synchronously. Yes, you simply call the read model directly in your REST APIs, or through wrapper methods in Application services.