Responsibilities of the command bus

Posted on by Matthias Noback

In the previous post we looked at commands and how you can use them to separate technical aspects of the input, from the actual behavior of your application. Commands are simple objects, handed over to the command bus, which performs the change that is needed.

As we learned, the command bus eventually calls the command handler which corresponds to the given command object. For example when a SignUp command is provided, the SignUpHandler will be asked to handle the command. So the command bus contains some kind of a lookup mechanism to match commands with their handlers. Some command bus libraries use a naming convention here (e.g. handler name = command name + "Handler"), some use a kind of service locator, etc.

Responsibilities of the command bus

The command bus doesn't merely hand over commands to their handlers. Usually it does all kinds of things. For instance a command bus may validate command data, wrap the command handler in a database transaction, provide queueing options for a command, etc.

How does it do all these things without becoming one big inarticulate unmaintainable class?

There are several options. Usually the Decorator pattern is used to wrap command buses and add behavior. This is particularly easy since command buses generally only have one public method:

interface CommandBus
{
    public function handle($command);
}

We should introduce a type for the $command parameter, but for now this suffices.

If you want to decorate an existing command bus (i.e. you want to add behavior to it), you can do this easily, like this:

class CommandBusWithAddedBehavior implements CommandBus
{
    public function __construct(CommandBus $originalCommandBus)
    {
        $this->originalCommandBus = $originalCommandBus;
    }

    public function handle($command)
    {
        // do anything you want

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

        // do even more
    }
}

The major advantage of this approach is that none of the specialized command bus implementations needs to know about any of the other command buses. It only takes care of its own business and then hands the command over to the next command bus. Each of the command buses can now easily adhere to the Single responsibility principle. The command bus object is also open for extension, and closed for modification.

An example: database transactions

If you want one command bus to wrap the next one in a database transaction, you could do it like this:

class TransactionalCommandBus implements CommandBus
{
    public function __construct(CommandBus $innerCommandBus)
    {
        $this->innerCommandBus = $innerCommandBus;
    }

    public function handle($command)
    {
        try {
            // start transaction
            $this->innerCommandBus->handle($command);
            // commit transaction
        } catch (Exception $exception) {
            // rollback transaction
        }
    }
}

What we thought was one command bus actually consists of many command buses, but hidden from sight. The command bus is the one that is not wrapped by another command bus. Of course it's still an instance of the CommandBus interface, so you just need to call its handle() method and all the magic unfolds itself in the background.

Another example: protecting the original order of commands

Let's say you let the command bus handle a command. The command bus finds the proper handler for the given command and wraps its execution in a database transaction. Now the handler creates a new command and lets the command bus handle that one:

class Handler
{
    public function __construct(CommandBus $commandBus)
    {
        $this->commandBus = $commandBus;
    }

    public function handle($command)
    {
        ...

        $newCommand = ...;

        // we are still handling $command, but now we start handling $newCommand
        $this->commandBus->handle($newCommand);
    }
}

The first command wasn't fully handled yet. In fact, the database transaction hasn't even been closed yet, so now both commands are being handled within the same transaction. Which is totally undesirable since the second command may fail, and take the first command down in its fall.

What we need is a command bus which recognizes the fact that it's already handling a command. If it is, and someone asks it to handle a new command, it just puts the new command on some internal stack:

class ProtectOrderOfCommands implements CommandBus
{
    private $queue = array();
    private $isHandling = false;

    public function handle(Command $command)
    {
        $this->queue[] = $command;

        if (!$this->isHandling) {
            $this->isHandling = true;

            while ($command = array_shift($this->queue)) {
                $this->innerCommandBus->handle($command);
            }

            $this->isHandling = false;
        }
    }
}

About SimpleBus/CommandBus

Everything we have discussed so far (commands, command buses, protecting the order of commands, wrapping command handling in transactions, etc.) has been covered already for you by the SimpleBus packages. The central package is simple-bus/command-bus. It contains the interfaces Command, CommandBus and CommandHandler. It comes with default implementations for:

  • A command bus that delegates command handling to specialized command handlers (as discussed above)
  • A command bus that finishes a command before it handles the next (idem)

It also offers extension points for implementing a command handler resolver which either:

  • Immediately returns the right handler for a given command
  • Loads the handler using some kind of a service locator

This package makes (almost) no assumptions about how you are going to use the command bus in your projects. The only assumptions are:

  1. A command should have at least a name to be able to refer to it. This name doesn't need to be exactly the same as the class name, since a class name is another level of abstraction than a command name. Hence, the Command interface contains only a name() method.
  2. A command bus never handles a command itself, so it always delegates to a command handler. This delegation process always requires some sort of resolving, to find the right handler for the given command. Hence, we have a DelegatesToCommandHandlers command bus which uses a CommandHandlerResolver to resolve the correct instance of CommandHandler.

Chain of responsibility

Instead of decorating command buses as described in the examples in this post, the command buses in SimpleBus/CommandBus follow the Chain of responsibility pattern. The "inner" or "next" command bus is being injected from the outside:

$commandBus1 = ...;
$commandBus2 = ...;

$commandBus1->setNext($commandBus2);
...

Instead of being forced to accept the next command bus as a constructor argument, this allows you to have your own constructors. The downside is that the next command bus may or may not be injected (since your command bus may be the last one). SimpleBus/CommandBus comes with a trait that relieves you from the duty to verify this manually all the time:

class YourCommandBus implements CommandBus
{
    use RemembersNext;

    public function handle(Command $command)
    {
        // ...

        // delegate to the next command bus, if applicable
        $this->next($command);

        // ...
    }
}

SimpleBus comes with other useful tools for event handling, Symfony integration, Doctrine integration, etc. so if you want to start using it in your projects, don't forget to take a look at the project homepage.

Conclusion

We discussed the command bus which actually consists of several command buses, wrapped using object composition. Each of them has separate responsibilities. Because none of them knows about the other, it's easy to extend the command bus and add your own functionality to it. The SimpleBus/Command package provides the code that you need in every project. The other SimpleBus packages offer extended functionality for the command bus.

In the next post we'll take a look at events and the event bus.

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
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).
Dave Hulbert

My main concern with setNext() is the mutability of the buses, which smells like temporal coupling (even if the trait deals with that for you). IMO either the next bus is a dependency of the bus, or the next bus is part of the handling request.

If the next bus is a dependency of the whole object (from instantiation) then it should always be in the constructor and can't be part of any interface. This is where I think decoration should be preferred over CoR. The request to handle is then just "handle this command".

Alternatively, what may make more sense for a command bus is making the next bus be part of the handling request. I'm not sure how the last command bus would work; perhaps $nextCommandBus should be optional.

class CommandBus {
public function handle(Command $command, CommandBus $nextCommandBus);
}

This means you're saying "handle this command and pass it to this handler".

Having a setNext() method is in between these 2. The next handler is almost a dependency and almost part of the handling request. This doesn't feel quite right to me. Either you've got an "optional dependency" (which is an oxymoron) or you have to call 2 methods to make it do 1 thing.

Matthias Noback

Thanks for mentioning this. Yes, this is (I think) the only concern I have with my own code ;)

I wanted to make the constructor ownership of the author of the command bus. But I didn't think of passing the next bus as the second argument of the handle method until I saw it done like this somewhere else. However, you can't pass in the *actual* next command bus, because you don't know what will be the next command bus after that. So it'd better be a simple callable with one argument, the Command object itself.

Matthias Noback

In version 2.0 this issue is solved: the "next" callable is provided as the second argument of the handle() method of command/event bus middleware.

Matthias Noback

See also: http://simplebus.github.io/... ("Implementing your own command bus middleware")

Matthias Noback

Same here: thanks for asking awesome questions - I'll address them in a new post.

codeBetyar

In the beginning of the article, when declaring the CommandBus interface, Matthias mentions "We should introduce a type for the $command parameter, but for now this suffices."

In the example in the article I think it's difficult to specify the type of the $command parameter without changing the interface. One way to solve this is to put the $command parameter into the constructor of the Handler instead of the handle() method. Then all handlers could share the same CommandBus interface, having a parameterless handle() method, which is very beneficial for executing clients. But in that case a new handler object has to be created for each command object, which is not optimal.

Does anyone know a better idea how to tackle this problem?

Conall O'Reilly

I don't see the issue with the bus having an interface containing $command->handle(Command $command) . The issue would be the handler interface having such an interface, as it is within the handle method of the handler, not the bus, that we actually want to access the specific methods the concrete command value object provides.

codeBetyar

Conall, you're completely right - my lapsus. I wanted to mention a potential issue when the actual handlers implemented a common interface (having a single handle() method), not the buses.

Dave Hulbert

Simplest solutions are to either make handlers callable (either as anonymous functions or objects with __invoke()) or do what Tactician (https://github.com/rosstuck... does and give the CommandBus an inflector to resolve method names (eg MethodNameInflector).

Daniel S

In my opinion, it's a bit odd to IMPLEMENT a CommandBus Interface AND receive an CommandBus in the constructor. That means, translated: "Handler Class XYZ is an CommandBus and needs a CommandBus to work".

Why not EXTEND an BaseCommandBusHandler and work in the ChildCommandBusHandler with parent::?

like

public function handle($command) {

try {
// start transaction
parent::handle($command);
// commit transaction
} catch (Exception $exception) {
// rollback transaction
}

}

vcryan

And because extending any class is typically a bad idea.

Christophe Coevoet

Because you are now hardcoding the chain of command buses (in depends of your inheritance hierarchy), which is far less flexible.
It also mixes all responsibilities in the same class.

"Handler Class XYZ is an CommandBus and needs a CommandBus to work" is perfectly fine. this is how composition works, and it is far more powerful than inheritance

Matthias Noback

This explains it very well, thanks.

The SimpleBus Symfony integration actually offers a way to decorate command buses using service tags and they allow you to define a priority, which means you can easily move them around in the hierarchy of specialized command buses.