Command Buses and Simple Redirects

Published: February 23, 2015

I've been busy developing a large application on Laravel. In the middle of this, I've been trying to also be a good PHP developer (oxymoron?) and look into using the Command Bus pattern, specifically using Laravel's implementation. I think I get the idea in theory: Fire a Command, the Handler deals with it, the Command is immutable, and all that. I've looked up tons of tutorials on the subject, and even watched Ross Tuck's talk Models and Service Layers; Hemoglobin and Hobgoblins which mentions the subject.

The one thing these tutorials do not mention is how one might use the data generated in the Handler. For example, say I have a controller method that fires off a command:

// Register the User
public function register(RegisterRequest $request)
{
  $this->dispatch(new CreateRegistrationCommand($request));
}

Now, let's assume this method needs to charge a credit card with Stripe, created the Order in our database, generate some tickets, email the user, notify the admins, and log the whole thing. After the Command is successful, I want to redirect the user to a confirmation page (using a reference number or ID from the Order we created). So our usage of the Command Bus gets a little more hard to figure out.

// Register the User
public function register(RegisterRequest $request)
{
  $this->dispatch(new CreateRegistrationCommand($request));

  $this->dispatch(new CreateOrderCommand($charge));

  // Redirect the user here
}

If I want to use the data from the newly-created charge, and use it to create the Order in our system, how would I do that? Using the Command Pattern means a Handler is not allowed to return anything. It just goes off to do its thing and we can handle any Exception that's thrown, but that's it. Redirecting from there becomes tricky. Here are some of the suggestions I've seen.

1. Return the Data Needed from the Handler Class

Handler classes aren't supposed to return anything and you're not supposed to rely on any of the data they generate. In theory, this is because a Command could take several minutes, hours, or even days to complete. Some people say, "Screw this!" and do it anyways. I see this as creating a lot of extra unneeded Command and Handler classes when I could create a simple RegistrationService class that handles all of this and is not bound to the rules of a Handler.

2. Create a UUID

Using my example, one could reason that my reference_number could be used as a makeshift UUID and be generated by the Controller for use in the creation of the Order. A Controller, in my mind should not need to worry about doing such things. At that point the Controller will know too much about the application and be veering away from its primary duty of handling HTTP requests. But, assuming I'm okay with making that concession, this could be a viable way to handle it, but you lose the purity of the pattern, and by that point it's no better than using a Service class for the same goal.

3. Redirect to a Verifier Method and Redirect After That

This one is the most complex and makes me go, "Dafuq?". This approach suggests something like this:

// Register the User
public function register(RegisterRequest $request)
{
  // Create UUID
  $uuid = uniqid();

  // Dispatch the Commands to the Queue
  $this->dispatch(new CreateRegistrationCommand($request, $uuid));

  $this->dispatch(new CreateOrderCommand($charge, $uuid));

  // Redirect the user to the verify method
  return redirect()->route('register.verify', $uuid);
}

// Show the verification page
public function verify($uuid)
{
  // Have your view listen via AJAX call and redirect when the order is ready
  return view('register.verify');
}

// The AJAX verification route
public function verifyOrder($uuid)
{
  // Verify the Charge and Order

  // Return the Order when all is well
  return $order;
}

Look at all this set up so we can use the "pure" approach of the Command Bus! This is total madness. Essentially, we fire the Commands off to the queue, redirect the user to a holding page that checks via an AJAX route whether the order with a UUID you generate is ready. This is no more simple than using a Service class that shoots these actions off to the queue and does the same actions.

Disclaimer

I'm don't profess to be the best developer in the world. I'm very pragmatic and don't buy into a lot of the overly complex patterns and I don't tend to prematurely optimize. But I'm just not seeing the benefit in the Command Bus pattern for use cases like these. What am I missing?

David Hemphill

About David Hemphill

Builder of web things. Family man. I used to fight. I used to music. I'm an introvert, but I still like you.