Search code examples
domain-driven-designcqrsclean-architecture

Executing Commands and Queries without Handlers in CQRS?


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?


Solution

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

    • APIs fire Commands and forget
    • APIs for Commands don't return any data to the callee
    • Command Handlers pick up the Command from message queues and process them
    • Commands will result in changes that become visible/available at a later point in time, through eventual consistency

    You need not use Command + Command Handlers 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.