Frameworks Are Not Tools

A friend of mine, a long time ago, asked me why it is that “gun guys” are so interested in firearms in the first place. “They’re just tools,” he said. “I have a detached interest in my tools, like the knives I use for cooking, or the tools I use in my garden, but they’re not objects of endless comparison and discussion for me.”

My response was that a pistol, or a rifle, or any other modern firearm, is not merely a tool. It is a machine. It has interrelated interdependent moving parts that all work in concert. (Additionally, it is powered by explosives, which makes it even more interesting.)

My friend got the point after that. Tools are not especially interesting because they are not especially complex. But machines are fascinating because they are complex.

With that in mind, we have to realize that frameworks are not tools. Frameworks are machines. Each one has the code equivalent of interrelated interdependent moving parts. Frameworks are fascinating for the same reasons that machines are fascinating.

So the next time someone says “use the right tool for the job” and then mentions a framework, consider that the person making the framework suggestion might not be thinking about frameworks in the right way. Indeed, they might be thinking about something else entirely, and using “the framework” as a shorthand for whatever concept they really have in mind.

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.