John sits alone behind the computer in the office. The only light is the lamp and laptop on his desk. He feels exhausted, however he knows that he must find the cause of the problem.
After another hour of debugging, John randomly reproduced the bug and he finally got it.In his code he has reused Product Service to retrieve Product from the database.
What he did not knew however, that this code was changing and saving products amount of views, whenever somebody called it. John had bad luck, as his team mate, introduced a bug in this code which stored incorrect value.
How many times you had to debug the code deeply, when function that seems to be obvious in what it does, was actually doing something unexpected?
The CQRS comes to help us in such situations. So we can reason more about the code, as the code becomes more clear and simple.
Enter the Command Query Responsibility Separation (CQRS)
The CQRS in his principles defines distinction between queries and commands.
Queries are way to fetch the data and Commands to modify it.
This simple distinction allows for agreement between developers, that they are safe to use queries as many times as they want without side effects being done.
Queries and Commands are identifiable, which means we know what specific query or command is supposed to do.
This has huge advantage over CRUD, as it allows to catch the intention of the user.
If user wants to change his email address. Then we may ask only for the email and as a result, send him specific notification to confirm his new email address.
From the query side, we can provide queries for specific views. This allow us to know where is it used and what decision it precede. For changing an email, it may be enough to retrieve only the current email, instead of full user details.
CQRS in Practice
To install Ecotone support for Symfony, do following:
composer require ecotone/symfony-bundle
To install Ecotone support for Laravel, do following:
composer require ecotone/laravel
Let’s define our first Command that will change the email address.
The Command Handler is a place where we actually handle the defined command.
This is how we correlate the Command with the Handler. Ecotone is looking at the first type hint in the method declaration to know, which command should this handler use. To send this command, we will use CommandBus, that we will inject into our HTTP Controller.
The Command Bus is automatically registered within your Dependency Container. He is aware of the routing to specific handlers, so all you need to do is to send the command.
Above Controller is pseudo code of course, adjusting it to Symfony or Laravel should be pretty straightforward however.
Let’s register Query that will return Shipping Address of the user.
And now Query Handler that will handle our GetUserShippingAddressQuery.
Ecotone allows for full flexibility, you may define multiple query/command handlers within same class, if you feel a need.This helps in keeping your logic together and avoiding code boilerplate.
As we have registered our Query Handler using #[QueryHandler] annotation, we may now send the query.
Now we are calling the QueryBus and returning the billing address.
Powerful capabilities, yet simple usage
When you will start using Ecotone, you will find yourself doing much less configuration, in result code will become much easier to read and understand.
Ecotone follows new trend in programming, that aims for keeping the business logic clean of framework. In most of the cases, you will be using PHP 8 Attributes only, and Ecotone will handle firing and wiring it all together.
You may read more about Command Handlers and Query Handlers in the official Ecotone’s documentation.