Command Bus
originally published December 26th, 2014There has been a lot of talk about the concept of the command bus lately and I discovered that Laravel 5 is likely to ship with a command bus implementation. So, I want to take a moment and discuss this topic as I’ve been using it well over a year now in many projects both green and brown.
At the bottom of this post there are a number of videos that discuss this topic further.
The idea of a command bus is that you create command objects that represent what you want your application to do. Then, you toss it into the bus and the bus makes sure that the command object gets to where it needs to go.
So, the command goes in -> the bus hands it off to a handler -> and then the handler actually does the job. The command essentially represents a method call to your service layer.
Usage
So, imagine you want to register a member to your application. You may start by creating a register member command, something like this:
final class RegisterMember implements Command
{
private $email;
private $password;
public static function withForm(Request $request)
{
return new static(
$request->get('email'),
$request->get('password')
);
}
private function __construct($email, $password)
{
$this->email = $email;
$this->password = $password;
}
public function email()
{
return $this->email;
}
public function password()
{
return $this->password;
}
}
This object is simple a DTO (data-transfer object). It exists only to have a name and to contain data. The name part is very important as we’ll come to later.
Then, your controller method might look something like this:
final class MemberRegistrationController
{
private $bus;
public function __construct(CommandBus $bus)
{
$this->bus = $bus;
}
public function showRegistrationForm()
{
// create and return form html here
}
public function submitRegistration(Request $request)
{
// 1. handle form validation here
// ...
// 2. create command
$command = RegisterMember::withForm($request);
// 3. execute command
$this->bus->execute($command);
// 4. return redirection response
}
}
As you can see, the command only holds information. It’s plenty fine to just use a normal constructor new RegisterMember($request->get('email'), ...)
. I’m simply using
a named constructor to make it more expressive. It’s very nice here that you can see that you’re creating the action of registering a member through the name of the class itself. This
provides what is called ‘explicit meaning’ versus ‘implicit meaning’.
Then, we have only one part left to describe. The part that actually does the work. The command is sent into the command bus and then the bus determines to which handler the command is paired. The bus instantiates an instance of the handler class and passes the command to it. Let’s see what it might look like..
final class RegisterMemberHandler implements Handler
{
private $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
/** @param Command|RegisterMember $request */
public function handle(Command $request)
{
// create the Member
$member = Member::register(
$request->email(),
$request->password()
);
// store the member with Doctrine
$this->em->persist($member);
$this->em->flush();
}
}
Think of a typical controller. Inside, you might find interactions with the model, form validation, and response generation; which includes view template rendering or redirect header generation. Some of these actions are related directly to the web, some of them directly to the core of your application. If you remove all of the aspects that were specific to your application but not specific to the web UI and move that code away, that is what the handler does.
Now, let’s say that I want to register a new member through an alternate mechanism. Perhaps I want to use a command-line utility. I can just generate the RegisterMember command and pass it into the bus. I can use RegisterMember from anywhere in my application and not have duplicated logic all over my app.
Command Pipeline
A command bus is a very simple object. A feature that is both powerful and commonly used is composition of command bus objects into a command pipeline. This is typically done with the decorator pattern. (more on the decorator pattern in the links below)
Imagine that you have an interface CommandBus
with a single public method execute($command)
and a class ExecutionCommandBus
that implements that interface. The role of ExecutionCommandBus
is to actually instantiate and then hand off
the command to the handler. This is considered the ‘default’ implementation of the command bus.
But, what if you wanted to implement an activity log for your site? Perhaps you might like to create a class ActivityLoggingCommandBus
that implements the interface CommandBus
. You could simple create a command pipeline by composing
the ActivityLoggingCommandBus
and the ExecutionCommandBus
. This is generally done in the dependency injection container.
$bus = new ActivityLoggingCommandBus(
new ExecutionCommandBus($containerInstance)
);
In this way, when execute($command)
is called on the ActivityLoggingCommandBus
, it’ll first trigger the storage of the log entry, then it’ll call execute($command)
on the ExecutionCommandBus
which then executes the command.
As you can see, this is a powerful technique that can very much simplify otherwise complex tasks while maintaining a clear separation of concerns.
Advantages
I believe that the command bus is a very strong addition to any app with non-trivial complexity. If you have a single page up and it just has an email gathering form or something like that then I wouldn’t bother with it. With any additional complexity I would use a command bus every single time. I am not telling you what you should do, I am telling you what I do.
The added simplicity, separation of concerns, and dependency management improvement for controllers and other presentation layer code brought by using a command bus is a serious improvement over other attempts that I’ve made to solve for these problems.
The command bus really shines when implementing task-based user-interfaces. I am a huge fan of task-based UIs and I think that you probably are too. If you don’t know much about them, I have linked to an article below. They improve user-experience and simplify client and server-side development.
As a result of these improvements, controllers become incredibly testable. The part of the application that people have traditionally had the roughest time testing becomes trivial. You pass in a mock command bus and just verify that the command was constructed correctly from the HTTP request.. done!
Finally, I feel like I’ve sufficiently made the point about the value of compositional command pipelines; so I won’t bother further.
Challenges
I have seen many people face challenges working with the command bus. There are many things that can be done to complicate this otherwise simple and easy to use pattern. There’s a good chance that if it’s complicated then there’s some concept missing in the implementation.
First and foremost, if your application is a simple CRUD app then it is possible that this pattern won’t provide the value that you might be looking for. Yes, it will make things easier to test, yes it will give you better separation of concerns. However, you’ll likely end up with massive amounts of fields and a tremendous amount of boiler-plate. CRUD apps don’t generally benefit as much from multi-layered architecture and as such you’ll get less value.
It’s also quite possible that an application that was developed in the CRUD style may not actually have been a CRUD app. I wouldn’t bring it up if I didn’t see it so often. CRUD-thinking is probably the most popular anti-pattern in our industry. Read more about CRUD thinking in the linked article at the bottom of this post.
I personally do not like using domain objects (such as value objects; read more at the bottom of the post) in my commands. I like passing in the data as simple as I get it from the web request.
Tactician
Ross Tuck, my friend and an excellent software-engineer is working on what I consider to be the go-to command bus package. He calls it Tactician and it’s in active development. The examples folder shows how you can use it. He and I vary a bit on how we want to interact with fields on the command objects, but he’s a very trustworthy developer to follow. Check out Tactician on GitHub and learn more at RossTuck.com.
More Information
Here are a selection of videos that cover the topics in this article quite thoroughly.
- #Dev-Discussions has a video specifically over this topic. I highly recommend watching a conversation with Ross Tuck, Jesse o Brien, and myself about the Command Bus
- I have given an Architecture Talk that goes over command bus and service layers in more detail and with visual diagrams.
- Ross Tuck has given a talk over models and service layers which helps illuminate the concept of the service layer. This is must-watch.
To really understand the content in this article I highly recommend reading each and every one of these articles.
- Please read about CRUD-thinking.
- Learn more about Value Objects.
- Brief Article on Task-Based Interfaces
Miro, in the comments pointed out that Patterns of Enterprise Application Architecture has a great section on Service Layers which will really help to illuminate the concept.