I’m not sure if that is really a design pattern. But I find that simple and it helps to make code intent very clear. It goes along with DDD principles.
The Command
The command is only a value object. There should be no logic inside it, only the necessary information that will be used by the command handler to do its job.
It should implement a very simple interface, empty even, just as to to enforce that command handlers deal with value objects rather than a primitive value, such an array. It must be immutable to prevent side effects.
A command should have a descriptive name to reveal intent, such as DeleteUserById, ClearCache, or… well, I hope you got the point for I am running out of ideas right now.
The Command Handler
The command handler is the responsible class for executing (or handling) the command. Think of it as a “action”, or service if you will. As such, it must be immutable.
It also has a very simple interface.
Usage example
Every command should have a respective command handler. The relationship should be one-to-one. Suppose we want to delete a user by id.
We would name our command according to what we want to do. So DeleteUserById
would be a super awesome name.
The handler could be named DeleteUserByIdHandler
, revealing intent. Also
it is supper easy to understand what is the command it handles.
Now, note that the implementation of this command is very simple. But even if the implementation was hell, it would be very simple to understand what that class is about. It deletes user by id! I am not arguing that if should carefully choose a name and not to care about the implementation, but you get the point.
Also, the handler can be easily tested. You can mock dependencies and so on.
One step further
The next step is called CommandBus
. You can think of command bus as the
common handler for all your commands. It will delegate the command to the
correct command handler.
Your dependency container could be something like follows:
Now that you have this set up, you can use the command bus inside your framework. You can easily change framework if you want.
Conclusion
I have not played around much with Command/CommandHandler/CommandBus. But so far I think it is awesome and I can see a few benefits:
- Framework agnostic
- Reusable
- Reveals intent
- Testable
Some people use commands only for writing and not for reading. But it can be
used to read also. You could have a GetProductsByCategoryId
command, for
example.
Resources:
- A wave of command buses - nice article about command buses.
- Dev Discussions - The Command Bus - Discussion on command bus
- Nurse - a very simple dependency injection container.
- Koine\CommandBus - interfaces and helpers for you to craft your command bus
- Command Bus To Awesome Town
I would love to hear your experiences and opinion on this subject.