A wave of command buses

Posted on by Matthias Noback

Recently many people in the PHP community have been discussing a thing called the "command bus". The Laravel framework nowadays contains an implementation of a command bus and people have been talking about it in several vodcasts.

My interest was sparked too. Last year I experimented with LiteCQRS but in the end I developed a collection of PHP packages known as SimpleBus which supports the use of commands and events in any kind of PHP application (there is a Symfony bridge too, if you like that framework). I also cover the subject of commands, events and their corresponding buses extensively during my Hexagonal Architecture workshop.

Since I consider this topic to be a very important and highly relevant one, I will spend several blog posts on it, explaining the concepts in my own terms, then introducing SimpleBus as a ready-made solution for your everyday PHP projects.

What is a command?

Commands are often used in applications that separate the technical aspects of user input from their meaning inside the application. Commands in object-oriented programming are objects, like everything else. A command is literally some kind of an imperative, indicating what behavior a user, or client, expects from the application.

Commands can be very simple like StartDiscussion, SortList, SignUp, etc. They contain all the information the application needs to fulfill the job. For example, the SignUp command could be a simple class like this:

class SignUp
{
    private $emailAddress;
    private $password;

    public function __construct($emailAddress, $password)
    {
        $this->emailAddress = $emailAddress;
        $this->password = $password;
    }
}

A part of the application which is very close to the user itself creates an instance of this class and populates it based on values that the user provides. For instance, in a web controller, it might look like this:

class UserController
{
    public function signUpAction(Request $request)
    {
        $command = new SignUp(
            $request->request->get('emailAddress'),
            $request->request->get('password')
        );

        ...
    }
}

Of course you could use a form framework to collect and validate the user data in a more orderly manner. Then the controller hands the command over to the part of the application which knows what to do with it (i.e. which is able to actually sign the user up). This thing that accepts commands is traditionally called a "command bus".

...

$this->commandBus()->handle($command);

Advantages of using commands

The user is not being signed up right here and now, at this exact place in the code. Instead, the command bus is trusted to do the actual work. This comes with several advantages:

  1. The command might be created anywhere and by any client; as long as you hand it over to the command bus, it will be handled properly.
  2. Your controller doesn't contain the actual sign up logic anymore.

The first advantage is pretty big. It should be extremely easy to create a console command in whatever way your framework wants you to do that, and achieve the same thing as in the web controller:

class SignUpUserConsoleCommand extends ConsoleCommand
{
    public function execute(Input $input)
    {
        $command = new SignUp(
            $input->getArgument('emailAddress'),
            $input->getArgument('password')
        );

        $this->commandBus()->handle($command);
    }
}

It doesn't matter who creates the command, or when, or even where. It will always trigger the exact same behavior in the application.

The second major advantage is that your controllers don't contain so much logic anymore. They merely translate the actual HTTP request to a corresponding command object, then let the command bus handle it.

Why is that a good thing? Well, first of all, this makes sure that none of the characteristics of the input side of your application (i.e. forms, query parameters, command-line arguments, etc.) leak to the core of your application. The core, or what lies behind the command bus, becomes totally ignorant of the world outside.

Before we introduced commands, the actual work was done in controllers. When you wanted to know what it meant for the business to "sign up a user", you just needed to take a look at the controller which had that particular responsibility. However, by putting the sign-up logic in a controller, you tied this particular responsibility to the actual web UI. To sign up a user is not necessarily a web thing. In fact, it should be possible to do the same thing in a different way, for example from the command-line or from inside a script that does a batch import of users.

By using commands you make this possible: everything can be accomplished from anywhere, not just from controllers. Which is completely true to your business domain. If it would be possible to feed your application post cards, your customer would have wanted you to make it so.

Feeding your application post cards

Who handles a command?

A short summary of what we discussed so far: if you use commands to let the user communicate the application's intended behavior, you make the core of your application completely unaware of the world outside. And on top of that, you separate the intended behavior from the actual implementation of that behavior.

The remaining question is: where do we find the actual implementation for a particular use case? The answer is: inside command handlers, like this one:

class SignUpHandler
{
    public function __construct(UserRepository $userRepository)
    {
        $this->userRepository = $userRepository;
    }

    public function handle($command)
    {
        $user = User::signUp($command->emailAddress, $command->password);

        $this->userRepository->add($user);
    }
}

The command bus has a mechanism, hidden from sight, which finds the right handler for any command it handles.

Commands and handlers have a one-to-one correspondence. A command is always handled by one handler and one handler only.

All the commands inside an application together form a large and insightful catalogue of all the use cases that your application offers. Browsing through a list of the available commands, you should be able to quickly notice what the application is about and in what ways it can be influenced from the outside. Consider for example CreateIssue, PickUpIssue, EstimateRemainingTime, MarkAsDone, etc.

Conclusion

Traditionally, the behavior of a web application would be defined by the controllers (and actions) that it offers. Routing definitions expose this behavior to the world outside. The principal way of talking to such an application is via the web.

Using commands you can separate the web-specific parts of your application from its essence. Commands define the use cases of your application and provide an internal API for anyone that might want to do something with your application.

Commands are not handled on the spot, but their behavior is implemented in command handlers. They are called by something called the "command bus". In the next post we will look at what this mysterious command bus looks like and what its responsibilities are.

If you're interested to learn more about these subjects and start using commands and events in your (Symfony) application, check out my Hexagonal Architecture training website.
PHP hexagonal architecture command bus SimpleBus Laravel
Comments
This website uses MailComments: you can send your comments to this post by email. Read more about MailComments, including suggestions for writing your comments (in HTML or Markdown).
Ejaz Karim

Thanks for the nice intro.

Doug

I just thought I'd add that another nice php framework we use https://github.com/szjani/p... - you can use the bits you want. e.g. the CommandBus and EventPublisher all via annotations.
Thanks for the article.

Baldinof

Hi Matthias,

Maybe it's a weird question.

In a Symfony project the "Command" namespace/suffix are used for console tasks, do you have an advice for the namespace of domain commands ?

Matthias Noback

Thanks everyone for asking awesome questions - I'll address them in a new post.

Robert

Hi Matthias, could you possibly explain what are the main differences between a command bus and an even dispatcher?

Marc Morera Merino

BTW, you could use EventDispatcher for this purpose, using Event as the Command, and a Subscriber as the Handler, but IMHO are not the same and should not be considered as such.

Marc Morera Merino

Well, I could try it.

The EventDispatcher purpose is to broadcast an environment. Something like... Hey! This event just happened! And then, in other zones, someone can do something related to this event.

The BusCommand is a simple way to say... Hey! This action needs to be done! Anyone caching that? So, using BusCommand, one call should be cached by one handler.

Another way of seeing this:
EventDispatcher ~ Broadcasting
BusCommand ~ Ping

@matthiasnoback... Agree with that?

Robert

Thank you both for your answers. So the CommandBus would tie together a Command and it's Handler and the relationship will be 1:1, no more, no less. The Event dispatcher will be used to perform pub/sub and a particular Event can be handle for multiple (or none) subscribers.

Isn't it a bit overkill to have a CommandBus for the Commands and an EventBus for secondary tasks? Am I missing some core concepts?

Florian Klein

Even tho it would be possible, it would be semantically incorrect to use events (past facts) instead of commands (wanted actions).

Events should be raised only when something happened. A command is here to make it happen.

mTorres

Hi Matthias, is it great that you state the advantages but can you also post the disadvantages? I'm quite new to this concept and currently exploring the possibility of trying it in a new project, but I'm not sure if that's the way to go.

Quickly I can think of 2 main disadvantages:

1) Increases complexity with another layer of abstraction (but adds flexibility and maybe eases the maintainability? - I'm not quite sure about this one)
2) You must glue each command with its handler somewhere and load that information on every request (speaking of HTTP) like the DI graph

In order to avoid 2 I've read somewhere (sorry can't find the source right now) that you don't need to use the Bus if it doesn't add value to your architecture, so maybe we could create Commands that executes themselves (with the __invoke method)? It will be less flexible but you'll have also less complexity to handle, what do you think?

Daniel S

Interesting concept! But why does the Command Handler not receive the actual commad in the constructor?

class SignUpHandler implements CommandHandler
{
public function __construct(SignUpCommand $command) { /* ... */ }
}

Gabriel Birke

I think registing with the command bus as an event handler is better than sending the command directly to a handler classb because with the command bus there can be other classes that listen to the SignUp command. For example a statistics module that counts signups, a scrape module tries to gahter user information from social networks or a logging module that captures specific commands. You should't cram all these things into one handler.

Matthias Noback

I'm preparing some replies right now. Just a quick note: the extra jobs that you mention are typically not handled by extra command buses, but by event handlers (see the latest post in this series: "From commands to events".

Florian Klein

Matthias explicited the fact that a command has one and only one handler associated.
I guess it avoids debug nightmares, and order of execution problems.

Concerning where to inject the command, I really think it should be pased as an argument of the handle() method. Otherwise, one handler instance = one command.
You wouldn't be able to process 2 differents command instances with the same handler instance.

Florian Klein

nice and well written introduction.

I just noticed a small problem in your code example, even tho it's just meta code, I know :)

$user = User::signUp($this->emailAddress, $this->password);

Where do come from $this->emailAddress and $this->password ?
My guess is that the Command instance would be passed as an argument of the handle() method, no ?

Marc Morera Merino

You mean that?

User::signUp($command->emailAddress, $command->password);

Florian Klein

ha :) I guess Matthias corrected the code, because $command didn't exist before.

Matthias Noback

Hehe, that's right :) Thanks for letting me know!

David de Boer

Still not completely correct, as $emailAddress and $password are private properties; they probably should be public instead. ;)

Xu Ding

Great post Matthias.

Did not notice you do DDD training too.

But sadly it is not in the country I am staying now yet.

Gabriel Birke

Interesting concept. How would the controller know that the signup was successful or not and display the correct message?
I'm imagining the controller registering for handling the UserSignedUp event (and another UserSignupFailed) event which set the relevant data to controller instance variables. Then after the Controller dispatches the SignUp command the data will be set and can be rendered.

In a standard CRUD application that would mean an explosion of actions - 9-12 per model (4 to indicate that a create, read, update, delete action must be taken, 4 to indicate that the action finished successfully, 1-4 to indicate failure). How do you organize these actions in apllications with many models? Sure, you can probably reduce the number of actions by choosing more high-level events, but still, there will be an awful lot of actions, right? Or am I going in the wrong direction here?

Florian Klein

In this kind of architecture, you shouldn't send a command and get its result synchronously as a return value of the call. It would break Command Query Separation (separate reads from writes).

Typically, to resolve this problem of feedback, people came with "feedback loops", where errors (or feedback) are sent to a stack, and the display regularly checks if new feedback has to be displayed.
With this approach, the chance to see the error at the right place at the right time depends on the latency of this loop. Most of the time it's negligable, so no problem :)

You also should take the latency of asynchronous command buses (queue, message broker, or something).
In that case, It's even not possible to get a return value, because the whole thing happens in another process.

Another approach is to stay silent on errors :) No kidding. On non-critical commands, people usually see if something went wrong (record not saved or something).

Conclusion: try to apply CQS, and don't try to write (command) AND read (display errors) with the same method call.

Marcelo Jacobus

Hi Florian. Could you share any example of the approaches you suggested?

Florian Klein

Hey .) I don't have IRL examples to show unfortunatly. I'm just badly repeating theory and/or articles I read.

Mirco Babin

The commandbus could return a Promise. And the promise would contain the actual result.

A commandbus seems over the top to me, because it introduces another level of unneeded complexity. The commandbus needs configuration somewhere that a SignupCommand is to be handled by a SignupHandler (or by a TestSignupHandler or ...). Configuration is also complexity, although it is not really code.

I think the question of Daniel S. is the right one, why not use:

class SignUpHandler implements CommandHandler
{
public function __construct(SignUpCommand $command) { /* ... */ }
}

Conall O'Reilly

The important question here is, how and where would you construct this handler?

It would probably be in the controller. So you would have to invoke" new SignUpHandler(new SignUp($email, $password))", directly from the controller action. In this case, while the logic of signing up has been moved to another class, the controller is just as coupled to that logic, the handler cannot be constructed and injected to the controller as it depends on the (yet to be defined) command itself.

The issue with this gets clearer when you realize that the SignUpHandler will often rely on other dependencies to accomplish its goal. For the sake of example, lets say it needs a UserRepository and a UniqueEmailValidator. The controller invocation would look something like this: "new SignUpHandler($signUpCommand, $this->userRepository, $this->uniqueEmailValidator)".

The problem here is that the controller knows way too much about what is needed for a command to be handled, when really all it should care about is "what needs to be done". By way of analogy, when my electricity is out and I call my landlord and tell him to fix my electricity, I don't expect to have to tell him what tools to use to fix it, I just want it done.

You can avoid this by passing the UserRepository and UniqueEmailValidator to the Handler on construct, and having a separate handle method.

class SignUpHandler implements CommandHandler
{
public function __construct(UserRepository $repository, UniqueEmailValidator $validator) { /* ... */ }

public function handle(SignUpCommand $command) {/*..*/}
}

If you don't want to use a bus, you can now simply inject the SignUpHandler into the controller, and use via; $this->signUpHandler->handle($signUpCommand);

This is better, although for more complicated controllers it can be annoying to have to pass multiple handlers into the constructors to be used in different actions. And while the controller now does not know about what tools the handler uses to accomplish its task, it nevertheless still needs to know that this concrete handler actually exists. Again, when I call my landlord and ask him to fix my electricity, I don't really need to know that the name of the electrician he always uses is "John". I just want it done.

And so we have the bus:

$this->bus->handle($signUpCommand);

Xu Ding

Probably Form validations should be handled before you call the CommandBus.

My two cents

webDEVILopers

Another interesting link about form validation and command bus:
http://verraes.net/2013/04/...
http://verraes.net/2015/02/...

My favorite by @cakper:
https://kacper.gunia.me/blo...

Tim Strijdhorst

Thank you very much for these references. I really like the form generation on basis of Command DTOs.

Marcelo Jacobus

I was wondering that too. Anybody would disagree here?

clemherreman

It feels a lot like the command bus+handler is like the routing+controller we can see in a HTTP context, but in a DDD way, doesn't it?

Matthias Noback

Yes, right. The DDD-aspect of it being that the command and handler are part of the domain, while the controller is a typical web (i.e. infrastructure) thing.

Marcelo Jacobus

Should the command handler replace services or make use of them?