Service Classes, Payloads, and Responders

Revath Kumar has a good blog post up about extracting domain logic from controllers and putting that logic in a service class. After reading it, I commented that with a little extra work, it would be easy to modify the example to something closer to the Action-Domain-Responder pattern. In doing so, we would get a better separation of concerns (especially in presentation).

Using the code that Revath gives in his blog post as a basis, we can do the following:

  1. In the service class, instead of sometimes throwing exceptions and sometimes returning arrays, we always return Payload instances. These explicitly state the result of the domain activity (“input not valid”, “order created”, “order not created”, “error”). Making the status information explicit in the Payload means that we don’t need to catch exceptions in the controller action, and that we don’t need to examine the domain objects themselves to interpret what occurred in the domain. The service class can now say explicitly what occurred in a standardized way.

  2. In the controller action, now that we don’t need to catch exceptions, we can concentrate on a much smaller set of logic: get the user input, pass it to the domain, get back the domain payload, and pass the payload to a responder.

  3. Finally, we introduce a Responder, whose job is to build (and in this case send) the response. The responder logic ends up being simplified as well.

The modified code looks like this:

use Aura\Payload\Payload;

class OrdersController extends Controller {
  public function actionCreate() {
    $orderData = Yii::app()->request->getParam('order');
    $order = new OrdersService();
    $payload = $order->create($orderData);
    $responder = new OrdersResponder();
    $responder->sendCreateResponse($payload);
  }
}

class OrdersResponder extends Responder {
  public function sendCreateResponse($payload) {
    $result = array('messages' => $payload->getMessages());
    if ($payload->getStatus() === Payload::CREATED) {
      $this->_sendResponse(200, $result);
    } else {
      $result['status'] = 'error';
      $this->_sendResponse(403, $result);
    }
  }
}

class OrdersService {

  protected function newPayload($status) {
    return new Payload($status);
  }

  public function create($orderData) {
    if(empty($orderData['items'])) {
      return $this->newPayload(Payload::NOT_VALID)
        ->setMessages([
          "Order items can't be empty."
        ]);
    }
    $items = $orderData['items'];
    unset($orderData['items']);
    try {
      $order = new Orders;
      $orderTransaction = $order->dbConnection->beginTransaction();

      $address = Addresses::createIfDidntExist($orderData);
      unset($orderData['address']);
      $orderData['address_id'] = $address->id;
      $amount = 0;
      foreach ($items as $key => $item) {
        $amount += $item['total'];
      }
      $amount += $orderData['extra_charge'];
      $orderData['amount'] = $amount;
      $order->attributes = $orderData;
      if($order->save()) {
        if(OrderItems::batchSave($items, $order->id)) {
          $orderTransaction->commit();
          $this->sendMail($order->id);
          return $this->newPayload(Payload::CREATED)
            ->setMessages([
              "Order placed successfully."
            ]);
        }
        $orderTransaction->rollback();
        return $this->newPayload(Payload::NOT_CREATED)
          ->setMessages([
            "Failed to save the items."
          ]);
      }
      else {
        // handle validation errors
        $orderTransaction->rollback();
        return $this->newPayload(Payload::ERROR)
          ->setMessages($order->getErrors());
      }
    }
    catch(Exception $e) {
      $orderTransaction->rollback();
      return $this->newPayload(Payload::ERROR)
        ->setMessages([
          "Something wrong happened"
        ]);
    }
  }
}

Now, there are still obvious candidates for improvement here. For example, we could begin separating the controller action methods into their own individual action classes. But baby steps are the right way to go when refactoring.

This small set of changes gives us a better separation of concerns, especially in terms of presentation. Remember, the “presentation” in a request/response environment is the entire HTTP response, not just the response body. The above changes make it so that HTTP headers and status code presentation work are no longer mixed in with the controller; they are now handled by a separate Responder object.

A Factory Should Create, Not Retain

In a recent Reddit conversation, some of us went off on a tangent about factories. I maintained then, and do now, that a “factory” always-and-only returns a new instance. If you have a “factory” that returns anything other than a new instance, it’s not a factory alone. In the case of factory methods, it is a factory + accessor; in the case of factory objects, it is a factory + registry.

A “factory” (whether a factory method or factory object) is one way to separate object creation from object use.

Let’s say we need to create an object to do some work in a class method:

class Example
{
    public function __construct($db)
    {
        $this->db = $db;
    }

    public function doSomething($itemId)
    {
        $data = $this->db->fetchOne(
            "SELECT * FROM items WHERE id = :id",
            ['id' => $itemId]
        );
        $item = new Item($data);

        // do some other work with the item,
        // the return the results of that work.
        return $results;
    }
}

The item creation is mixed in with the use of the item. What we want to do is separate the creation from the usage. One way to do that is to use a factory method, or a factory object, to handle object creation for us. Here’s an example of a factory method:

class Example
{
    public function __construct($db)
    {
        $this->db = $db;
    }

    public function doSomething($itemId)
    {
        $data = $this->db->fetchOne(
            "SELECT * FROM items WHERE id = ?",
            ['id' => $id]
        );
        $item = $this->item($itemId);

        // do some other work with the item,
        // the return the results of that work.
        return $results;
    }

    public function item($data) // factory method
    {
        return new Item($data);
    }
}

Here’s an example of an injected factory object:

class Example
{
    public function __construct($db, $factory)
    {
        $this->db = $db;
        $this->factory = $factory;
    }

    public function doSomethingWithItem($id)
    {
        $data = $this->db->fetchOne(
            "SELECT * FROM items WHERE id = ?",
            ['id' => $id]
        );
        $item = $this->factory->item($data);

        // do some other work with the item,
        // the return the results of that work.
        return $results;
    }
}

class Factory // factory object
{
    public function item($data) // factory method
    {
        return new Item($data);
    }
}

There were some folks in the Reddit thread that believe a factory may additionally retain the created instance for reuse. For example, let’s say we create and the reuse a collaborator object of some sort:

class Example
{
    public function doSomething()
    {
        $collab = $this->collab();
        // do stuff, then:
        return $result;
    }

    protected function collab() // factory method?
    {
        if (! $this->collab) {
            $this->collab = new Collab();
        }
        return $this->collab;
    }
}

As far as I can tell, that’s not just a factory. There are three things going on there: initializing a property, creating an object, and accessing a property. To split the concerns, one would need two methods:

class Example
{
    public function doSomething()
    {
        $collab = $this->getCollab();
        // do stuff, then:
        return $result;
    }

    protected function getCollab() // initialize + access
    {
        if (! $this->collab) {
            $this->collab = $this->newCollab();
        }
        return $this->collab;
    }

    protected function newCollab() // factory
    {
        return new Collab();
    }
}

Now the concern of creating the object is represented by newCollab() method, and the concerns of initializing and accessing the property are represented by the getCollab() method. Indeed, splitting out a factory method in this kind of situation is the exact recommendation in the GOF Design Patterns book on page 113; this is the book that defined the term “factory method” in the first place, so it seems authoritative on this point.

What happens when you add retention to what would otherwise be a factory object? For example, is the following only a factory object, or does it do more than just create and return new instances?

class WhatIsThatThing
{
    public function getService()
    {
        if (! $this->service) {
            $this->service = $this->newService();
        }
        return $this->service;
    }

    public function newService()
    {
        return new Service();
    }
}

It both creates objects, and retains the created objects. That makes it more than just a factory; it looks more like a container at this point.

Finally, regarding method names, it seems like it’s best to indicate what to expect as a return result. I default to newInstance() in factory objects that deal with only a single class, and new<Type>() when the factory object creates many different classes. Using get<Type>() indicates that a pre-existing instance (probably memoized in a property) is being returned.

Modernizing Serialized PHP Objects with class_alias()

Several weeks ago, a correspondent presented a legacy situation that I’ve never had to deal with. He was working his way through Modernizing Legacy Applications in PHP, and realized the codebase was storing serialized PHP objects in a database. He couldn’t refactor the class names without seriously breaking the application.

I was carefully moving my classes to a PSR-0/4 structure when I found this. The application saves the output of serialize($shoppingCart) in a BLOB column, and unserializes it later to recreate the ShoppingCart object. The serialized object string looks like this:

O:12:"ShoppingCart":17:{s:13:"\00Basket\00items";a:25:{...}; ...}

See how the class name is embedded in the serialized string? If I rename the ShopppingCart class to PSR-0/4 namespace, then the old class won’t be found when the application tries to unserialize() the serialized representation. How can I begin refactoring this without breaking the whole application?

Before I was able to reply, my correspondent ended up changing the serialization strategy to use JSON, which was a rather large change. It ended up well, but it turns out there is a less intrusive solution: class_alias().

If you’re in a serialized situation, and you need to change a class name, you can use a class_alias() to point the old class name to the new one. (Call class_alias() early in execution, probably before you register your autoloader.) You can then rename and move the class according to PSR-0/4 rules, and PHP will handle the rest for you.

For example, if you renamed ShoppingCart to Domain\Orders\Cart, you might do this:

class_alias('ShoppingCart', 'Domain\Orders\Cart');

Now when you call unserialize($shoppingCart) to create an object, PHP will create it as an instance of Domain\Orders\Cart instead of ShoppingCart. Re-serialized representations of the recreated object will retain the new class name, not the old one: O:18:"Domain\Orders\Cart":....

As soon as there are no more serialized representations using the old class name, you can remove the class_alias() call entirely.

MLAPHP Boot Camp!

You may have seen my introductory talk on steps toward modernizing a legacy application at Nashville PHP or at php[world]. That was the presentation that formed the first few chapters of Modernizing Legacy Applications in PHP.

The MLAPHP book has been a great help to a lot of people. But there are a lot of other developers who learn best by watching-and-listening first, instead of reading. They know it can be a great help to have someone talk them through the whole moderizing process, and see the steps being performed.

Usually you have to go to a conference for that sort of thing. You have to pay for the ticket, and for the hotel, and for travel, and meals, and everything else. Even if your employer helps with the money, there’s still the time involved: you have to be away for several days at a time.

Well, now you can have a conference-level training experience in the comfort of your own home, without the travel hassle and hotel expense. I have put together an online weekend “boot camp” where we go through the entire modernization process, from basic prerequisities at the beginning to setting up a DI container at the end. After that end-to-end study of the steps involved, you should be able to jump-start your own modernizing project much more easily.

The 8-hour camp will combine lecture and “live” coding with examples. In particular, there will be plenty of opportunity for you to get answers specific to your own modernizing situation, and to chat with other attendees.

The two-day camp will be on Sat 11 July and Sun 12 July. Each day will run from 12 noon to 4pm (US Central Daylight), with time for breaks built in. That makes it 10am-2pm for Pacific time zone attendees, and 1-5pm for Eastern, which should be convenient for almost everyone.

With your ticket to attend the boot camp, you get:

  • Two days of online boot camp, four hours each
  • A review of the entire modernization process from beginning to end
  • A bonus recording of the camp
  • For $399

This might be the only time I lead this kind of boot camp, so get your ticket while there are still seats available!

Relay: A PSR-7 Middleware Dispatcher

UPDATE (2015-06-09): Due to a conflict with the “pipeline” design pattern name, which this project does not implement, the project name has been changed from Pipeline to Relay. Links and naming have been updated inline, with the original text block quoted beneath.

In a fit of inspiration over the weekend, I extracted the middleware dispatcher from the Radar ADR core into its own standalone library: Relay. If you need to execute a queue of middleware, Relay is for you.

Relay uses a common PSR-7 middleware signature: function ($request, $response, $next) and return $response. That is what Slim 3 uses, along with Stratigility and Radar, and is modeled on Sencha Connect. Any callable/invokable with that signature will work with Relay.

As a standalone library, Relay is framework-independent, so you can use it anywhere. You could even build your own framework around it, picking a dotenv-loader of your choice, a DI container of your choice, and a middleware queue of your choice.

Speaking of DI containers, Relay is also container-independent. You can use any dependency-injection system you like to build your middleware queue and pass it to Relay. All you need to do is pass in a callable that converts each queue entry to an object or callable. Try it with PHP-DI, Pimple, Auryn, or even Aura.Di.

I have converted Radar to use Relay at its core, and soon I’ll be extracting two of the basic Radar middleware classes to standalone packages. When I do, they’ll be listed on the Relay wiki.

ORIGINAL RELEASE:

In a fit of inspiration over the weekend, I extracted the middleware dispatcher from the Radar ADR core into its own standalone library: Pipeline. If you need to execute a queue of middleware, Pipeline is for you.

Pipeline uses a common PSR-7 middleware signature: function ($request, $response, $next) and return $response. That is what Slim 3 uses, along with Stratigility and Radar, and is modeled on Sencha Connect. Any callable/invokable with that signature will work with Pipeline.

As a standalone library, Pipeline is framework-independent, so you can use it anywhere. You could even build your own framework around it, picking a dotenv-loader of your choice, a DI container of your choice, and a middleware queue of your choice.

Speaking of DI containers, Pipeline is also container-independent. You can use any dependency-injection system you like to build your middleware queue and pass it to Pipeline. All you need to do is pass in a callable that converts each queue entry to an object or callable. Try it with PHP-DI, Pimple, Auryn, or even Aura.Di.

I have converted Radar to use Pipeline at its core, and soon I’ll be extracting two of the basic Radar middleware classes to standalone packages. When I do, they’ll be listed on the Pipeline wiki.

Semantic Versioning and Public Interfaces

Adherence to Semantic Versioning is just The Right Thing To Do, but it turns out you have to be extra-careful when modifying public interfaces to maintain backwards compatibility. This is obvious on reflection, but I never thought about it beforehand. Thanks to Hari KT for pointing it out.

Why do you have to be extra-careful with interfaces and SemVer? To see it more clearly, let’s use a concrete class as an example.

class Foo
{
    public function bar() { ... }
    public function baz() { ... }
}

If we remove a public method, that’s clearly a BC break. If we add a non-optional parameter to an existing public method, that’s also clearly a BC break. Those kinds of changes will break any code already using the Foo class; that code will have to be modified to accommodate the changes in Foo.

However, if we add a new public method to the concrete class, that is not a BC break. Likewise, changing the signature of an existing method to add an optional parameter is not a BC break either. (UPDATE: See note below.) Code using the Foo class does not have to change to accommodate the new method or the new optional parameter.

But what happens with an interface?

interface FooInterface
{
    public function bar();
    public function baz();
}

Removing a method, or adding a non-optional parameter to an existing method, is the same as with a concrete class: it’s BC break.

However, unlike with a concrete class, adding methods is also a BC break. So is changing an existing method sigature to add an optional parameter. Existing code that implements FooInterface will no longer comply with the interface; that code will have to change to accommodate the new method or the new optional parameter.

Thus, interfaces are more susceptible to BC breaks than concrete classes. Once an interface is published as “stable”, I don’t see how it can be changed at all per the rules of SemVer (that is, unless you bump the major version). The only thing you can do to maintain BC is add an entirely new interface to the package while leaving the old one in place, perhaps even extending the old one if needed.

Again, it’s obvious in hindsight, but I did not have the foresight to anticipate it. Perhaps this realization will save you some trouble in the future.

p.s. On further examination, the interface constraints apply to abstract classes, too. Changes to an abstract mean that child classes will have to be modified as well, otherwise they won’t comply with the modified abstract.

UPDATE: Dave Marshall notes on Twitter that in the concrete class case, if you add an optional parameter to a method, and a user has extended and overridden that method, the extended class will break under PHP E_STRICT. He links to Symfony policy on the subject, which I will now have to read.

Radar: Answering Questions, and New Middleware

Last week’s announcement of Radar, an implementation of Action-Domain-Responder using PSR-7, was a resounding success. The feedback has been mostly positive, with some confusion and misunderstanding, and with one particular question being raised more than once.

This Reddit thread is typical of the various questions and comments I’ve received so far:

[“ADR” is just] the hipster slang for ‘c’, ‘m’ and ‘v’.

In other words, “Why ADR in the first place, and not just MVC?” This is answered by the ADR white paper, and again by some commentary here. In short, ADR is a refinement of “web” MVC to more accurately describe how we actually work in a request/response environment. The renaming of the components is intended to break the association with “real” MVC. (Special thanks to “lordofworms” for his patient and civil responses to the questioner.)

Why [is the project called] “Radar”?

As noted in the Reddit thread by others, “Radar” is a sound-alike from the ADR acronym. (An early version of the ADR paper was titled Request-Action-Domain-Response, the acronym for which lends itself even more to “Radar”, and I had that in mind too.)

why use classes at all? If most of your classes contain a single __invoke method, could they not just be substituted with namespaced functions?

The questioner was answered quite thoroughly on Twitter. I will add only that there’s nothing about ADR that says you must use classes. If you can implement ADR using all functions all the time, go for it. ADR is a pattern, not an implementation; Radar is an implementation, not a pattern.

Finally, we have this very good criticism referring to the middleware implementation:

Passing arguments by reference will confuse users.

Variations on this theme came up elsewhere as well. As a result, I have re-worked the middleware implementation completely.

Previously, Radar used a “filter” style of middleware, where an iterator calls each middleware handler in turn at different points in the execution path. This is the style used by Slim 2 and Silex, and works well with globally mutable request and response objects.

However, PSR-7 requests and response are immutable. I have not previously used immutables very much, and I tried to subvert the immutability by allowing middleware to use reference parameters. The references would make the request and response objects appear globally mutable, even though the objects were in fact immutable.

The critics who noted that this was potentially confusing, as well as a subversion of the immutable intent, turned out to be worth listening to. I experimented a bit with a wrapper-style (or chain-style) of middleware, and I’m much happier with it.

In the new implementation, each middleware calls the next one in turn, instead of an external iterator looping over them. (There is a Dispatcher object that “holds” the queue of handlers, and that it what gets passed to each handler for its $next call.) I got the idea from reading MWOP’s Conduit code, although this is greatly pared down from that. You can read more about the new implementation here.

Radar: A PSR-7 Action-Domain-Responder Framework

Radar is a PSR-7 compliant Action-Domain-Responder (ADR) system. While it may look like a micro-framework, it is more like a wrapper around the real core of your application domain. Its architecture makes it an excellent complement to Domain Driven Design.


Radar is superficially similar to a micro-framework. It has a routing system to point URLs to actions, a filter-style middleware system to modify the incoming HTTP request and outgoing HTTP response, and a dependency injection container and configuration system to wire everything together.

However, with Radar, you don’t specify “controllers” or “closures” for your routes. Instead, you specify up to three callables per route, all of which are optional:

  1. A Domain callable to be invoked with the user input. (If you don’t specify a Domain callable, the Responder will be invoked directly; this is unusual but sometimes convenient.)

  2. An Input callable to extract user input from the incoming HTTP ServerRequest. The default Radar Input callable will naively merge the route path attributes (path-info parameters), the query parameters ($_GET), the parsed body parameters ($_POST), and the uploaded files array ($_FILES) into a single associative array of user input.

  3. A Responder callable to convert the Domain output to an HTTP response. The default Radar Responder expects a Payload object from the Domain; it delivers JSON output and sets proper HTTP status codes for a wide range of scenarios.

These three callables are invoked within a standardized ActionHandler. As a result, the Action logic in Radar is always the same for every route. The only variations are in how input is collected, how output is presented, and of course in how your core application domain operates.

So, don’t think of Radar as a micro-framework. Think of it more like a wrapper around the core of your real application domain. Its only purpose is to guide input from the user into the domain, and to present output from the domain back to the user.

You can read the documentation for it here.

A PSR-7 Web Router Implementation, and Bookdown Documentation

From the Aura blog:

Our first 3.x package is now available for review, a PSR-7 implementation of Aura.Router. It includes some feature upgrades such as custom rules and more powerful route definitions.

On a side note, the package documentation uses Bookdown for its documentation. You can see the generated documentation here. Bookdown allows us to keep documentation sources in each library repository. We can then collect them all into a single “book” on the Aura site using a bookdown.json file with remote “content” elements.

Read the rest at the Aura blog.

Separate The User Interface Repository From The Core Application Repository

tl;dr: Keep the core application (“model”, “domain”) code repository separate from the user interface (“controller/view”, “action/responder”) code repository; use a dependency manager in the user-interface repo to bring in the core-application repo.


Nihal Sahu asked on Twitter, “How do you ‘personally’ go about building an application? What Structure?” This post is my longer-than-140-characters response.

Obviously I’m a fan of Action-Domain-Responder as a pattern for web-based user interfaces. (ADR treats the request/response cycle itself as a user interface. The HTML/CSS/JS/etc that goes into the HTTP body is just one part of the presentation half of the user interface; ADR reminds us that the HTTP headers are part of the presentation, too.)

But ADR, and MVC, and the other user-interface patterns – they are not an application architecture in and of themselves. The “Domain” in ADR and the “Model” in MVC are just entry points into the underlying core of the overall application architecture. In a way, the “Action/Responder” and “Controller/View” portions of the UI are not the big deal in the application; the big deal is the underlying core. That’s where the real work happens.

With that in mind, one first thinks the right approach would be to separate the User Interface from the Core Application. This is obvious and uncontroversial; separation of concerns is a central tenet of good architecture.

What might be controversial is my extended advice regarding that approach. I don’t suggest a merely “logical” separation of concerns so that Action/Controller classes don’t have Domain/Model code in them. I suggest a “physical” separation. In other words:

Separate the User Interface repository from the Core Application repository.

Yes, I mean that you should have two code repositories for your application. Let’s explore that idea for a minute.

The first repository, the Core Application one, contains no user-interface code at all. No HTTP, no standard input/output, nothing. It expects to receive input in an interface-independent way, and it delivers output in an interface-independent way. Note that it receives the input. It has to be sent to the Core Application in some way, not read from the interface (no superglobals!). The injected input could be via method parameters, a plain old PHP array, an input object provided by the Core Application, a Command object provided by the Core application, etc. Likewise, the output could be via anything provided by the Core Application, such as a Model object, a Domain Payload, or something else. It is completely independent from any user interface code and can be tested on its own.

The other repository, the User Interface one, contains your “Action/Responder” or “Controller/View” (or “Command/Stdout”) code. There is no business logic at all. All it does it reformat the user input to something the Core Application will recognize, pass it to the Core Application, and receive back some output from the Core Application, which it reformats for presentation to the user.

But if the two repositores are “physically” separated, how can the User Interface get access to the Core Application? Composer becomes your best friend in this case. In the User Interface codebase, add "require": { "project-name/core-application": "dev-develop" } to composer.json. Issue composer update and voila: your Core Application is now available to the User Interface. The User Interface depends on the Core Applicatiion, but the Core Application has no dependency on the User Interface.

What’s great about keeping the repositories fully separated from each other is that it enforces developer discipline. It becomes difficult to put Core Application code in the User Interface code. Any attempts to do so are immediately obvious, and everyone watching can see it happening. It becomes harder to justify to yourself “I’ll add it just this one time” (and thus keeping off that particular slippery slope).

The tradeoff is that you now have to coordinate changes across two code repos. Breaks in the Core Application will break the User Interface. The disconnection can be a positive overall, since you can version the Core Application separately from the User Interface, but in practice it does mean you have to be more attentive to change management.

One more thing about keeping the User Interface “physically” separate from the User Interface in this way is that you start thinking differently about frameworks. I have begun to think that our vocabulary for describing frameworks in PHP land is insufficiently varied. MVC and ADR do not describe “application frameworks” – they might describe User Interface frameworks, but there’s no word for Core Application frameworks. Maybe they need their own separate framework term.