Design Patterns 1: Command / Command Bus

This is the first of a few different blog posts related to Design Patterns in PHP. In this post we will explore how to use the Command Bus pattern as well as why you might want to use the pattern. I will briefly touch on a few different implementations and the pro's and con's.

Command Bus

The Command Bus is one of the corner stones of a popular system architectural pattern called CQRS (Hint hint, the C stands for Command). In an application that has multiple different interaction surfaces like a big monolith application, a designer wants to abstract as much business logic from the interaction surface and place that logic inside of the applications domain. This is done to ensure that each type of request that comes into the system is handled in the same way. An example with multiple surfaces would be an application that has both an HTTP API as well as Cron Tasks that need to run.

A more fully concrete example might be a system in which Invoices are being generated. Consider that there would be an HTTP API to create an invoice, and then there will be a nightly cron job that crunches some numbers and creates invoices from that task.

In this system it is very important that both methods of inputting the Invoice be the same as we need to make sure that everything is valid and working via Continuous Integration. An invoice created via Cron should be no different than an Invoice created via HTTP API and furthermore the Cron invoice should be modifiyable/queryable via the HTTP API.

At it's core a command bus is nothing more than a map of Commands to Handlers.

Command

A command is nothing more than a representation of a change to our system. The concept of a Command is to create a Data Transfer Object(DTO) that represents a change to our system and thusly creates a unified way of our system to execute a change. Traditionally a programmer might just simply store an entity inside the "Interaction" layer (IE Controller), however this leads to a problem. It's not unified across the entire system. Of course you may cobble together through sheer creativity the ability for your Cron layer to inject fake HTTP Requests and achieve somewhat of a similar result. Having done this in the past it is very fragile and suffers a lot of code smell.

Instead one can use a simple DTO which represents an action that we wish to take on our system. This command is avaiable via any number of "Interaction" layers and acts as a unified way to complete this action in our system. One does not need to unit test a CRON -> HTTP -> DOING WORK; instead we simply unit test the result of the command, nothing more.

Handler

The handler is the object who receives the command and actually executes the work. The state change of the system is completed in this object. It responds back to the Command Bus with either True or False and in it's execution (should you be using Events) emit events representing the changes of the system that were made.

Putting it all together

  • A command represents a state change
  • A handler completes the state change
  • A command bus routes the command to the handler
  • Commands are useful as they represent a single pathway to completing a state change/unit of work/doing something that modifies your system

Example

We can take a look at an example of when to use a command bus by simply looking at every developers favourite starting point of a project. User Registration :)

In this example we need to create a user. So we can create a command with a name...

CreateUser

Okay, yeah pretty straight forward... so then we need a handler...

HandlesCreateUser

What does this even look like you ask?

//Create User
class CreateUser implements Command
{
    /** @var Uuid */
    private $id;

    /** @var string */
    private $username;

    /** @var string */
    private $password;

    /** @var string */
    private $display_name;

    /**
     * User constructor.
     * @param Uuid $uuid
     * @param string $username
     * @param string $password
     */
    public function __construct(Uuid $uuid, $username, $displayName, $password)
    {
        $this->id = $uuid;
        $this->username = $username;
        $this->display_name = $displayName;
        $this->password = $password
    }

    // ... getters
}

class HandlesCreateUser
{

   public function handle(CreateUser $command) {
      $user = new User(
           $command->getUuid(),
           $command->getUsername(),
           $command->getPassword(),
           $command->getDisplayName()
      );
      
      $this-entityManager->persist($user);

      return true;
   }
}

The command essentially represents the constructor of your Entity class. You are essentially encapsulating the constructor in a DTO thus forcing all aspects of your system to use the User Entity in the same way.

This is especially more important when you start looking to implement other aspects of CQRS in your application.

I hope this article answered some of your questions on why people use Command Buses/Commands.

As always if you have any questions hit me up on twitter!

Shout-Out to https://twitter.com/cbrenton90 for giving me the idea to do a series on architectural patterns

Written by Glenn Eggleton on Monday August 21, 2017
Permalink - Chapter: php