WikiMedia, Clean Architecture, and ADR

tl;dr: Action-Domain-Responder is a natural fit for the HTTP user-interface portions of Clean Architecture (or Hexagonal), especially with Domain Driven Design. Just be sure to remember to separate the HTTP response presentation from the action code.


I.

Jeroen de Dauw has a fantastic post on Implementing the Clean Architecture in PHP, with Domain Driven Design elements. You should read the whole thing, and examine the implementation codebase, for a number of useful insights. Though I might quibble over some elements of the implementation, I think it is a good offering, and serves as a solid reference point.

In his article, Jeroen notes they are using Silex for their HTTP user-interface system, and describes the logic of each route action:

Inside this [Silex action] we construct our framework agnostic request model and invoke the Use case with it. Then we hand over the response model to a presenter to create the appropriate HTML or other such format.

That is a very near paraphrase of Action-Domain-Responder:

  • The Action marshals input from the HTTP request
  • The Action invokes a Domain element with that input and gets back a result
  • The Action passes that result to a Responder to build the HTTP response

In Jeroen’s implementation, each Action is a closure defined in the routes.php file. The Action marshals input from the HTTP request using a “request model” (an input object tailored to the domain) and passes it to a “use case.” Each “use case” is an entry point into the Domain, and returns a “response model” (the domain result).

The only place where Jeroen’s implementation deviates from ADR is that the Action code builds the presentation itself, instead of handing off to a Responder. (This may be a result of adhering to the idioms and expectations specific to Silex.)

Because the rest of the implementation is so well done, refactoring to a separated presentation in the form of a Responder is a straightforward exercise. Let’s see what that might look like.

II.

First, as an example, review the code in the check-iban action. The following reorganization of that action code makes the ADR pattern more obvious:

<?php
$app->get(
    'check-iban',
    function( Request $request ) use ( $app, $ffFactory ) {

        // marshal input
        $input = new Iban( $request->query->get( 'iban', '' ) );

        // invoke domain and get back result
        $result = $ffFactory->newCheckIbanUseCase()->checkIban($input);

        // presentation
        return $app->json(
            $ffFactory->newIbanPresenter()->present( $result )
        );
    }
);
?>

Very clear and straightforward. However, the presentation work is embedded in the action with the $app->json(...) call. (My guess is that’s probably a result of working with existing Silex idioms.)

Another good example is the list-comments.html action. Reorganizing the logic to make the ADR pattern more obvious gives us the following:

<?php
$app->get(
    'list-comments.html',
    function( Request $request ) use ( $app, $ffFactory ) {

        // marshal input
        $input = new CommentListingRequest(
            10,
            (int)$request->query->get( 'page', '1' )
        );

        // invoke domain and get back result
        $result = $ffFactory
            ->newListCommentsUseCase()
            ->listComments( $input );

        // presentation
        return new Response(
            $ffFactory->newCommentListHtmlPresenter()->present(
                $result,
                (int)$request->query->get( 'page', '1' )
            )
        );
    }
);
?>

Again, the presentation work is embedded in the action code.

In general, it is better to completely separate the presentation work from the action code. Remember that in an HTTP context, the presentation is not just the body of the HTTP response. Instead, the presentation is the entire HTTP response, including headers and status. (For more on this, see The Template Is Not The View.)

With the above examples, because they are already so well structured, it would be easy to extract the presentation to a Responder class. For example, the list-comments action could have the presentation work completely removed like so:

<?php
// hypothetical class with the extracted logic
class ListCommentsHtmlResponder
{
    public function buildResponse($request, $result, $ffFactory)
    {
        return new Response(
            $ffFactory->newCommentListHtmlPresenter()->present(
                $result,
                (int)$request->query->get( 'page', '1' )
            )
        );
    }
}

// the refactored action code
$app->get(
    'list-comments.html',
    function( Request $request ) use ( $app, $ffFactory ) {

        // marshal input
        $input = new CommentListingRequest(
            10,
            (int)$request->query->get( 'page', '1' )
        );

        // invoke domain and get back result
        $result = $ffFactory->newListCommentsUseCase()->listComments($input);

        // hand result to responder
        return $ffFactory->newListCommentsHtmlResponder()->buildResponse(
            $request,
            $result,
            $ffFactory
        );
    }
);
?>

Now the presentation work of building an HTTP response is cleanly separated from the rest of the action code.

III.

When separating concerns along these lines, you begin to see the similarities in the presentation work, and can start to reduce repetition across the codebase. For example, any Action that delivers a JSON response might use the same base JSON Responder.

Eventually, you may realize that the logic of each action is effectively identical. That is, you always collect input, pass that input through the domain to get back a result, and pass that result to a response builder.

When that realization occurs, you can build a single action handler that coordinates between injected input marshals, domain entry points, and response builders. That’s exactly what the Arbiter ActionHandler does, and Radar uses that in turn to specify the input + domain + responder callables for each route.

At that point, you are out of the business of writing action methods entirely. Then the user-interface code can focus on marshaling inputs going to the domain, and on presenting the results coming out of the domain – which is exactly how things should be.

P.S.

Jeroen’s writeup also reveals that at least some of the elements in his implementation are returning something like Domain Payload objects. Cf. the ValidationResult class, used in the validate-payment-data action among other places.

I’m a big fan of the Domain Payload pattern in ADR, and using a Domain Payload for all returns received by the action code. Doing so simplifies the response-building logic even further; for example, by collecting common “success” and “failure” presentation work across different JSON responders.

Then there’s this bit about containers:

We decided to go with our own top level factory, rather than using the dependency injection mechanism provided by Silex: Pimple. Our factory internally actually uses Pimple, though this is not visible from the outside. With this approach we gain a nicer access to service construction, since we can have a getLogger() method with LoggerInterface return type hint, rather than accessing $app[‘logger’] or some such, which forces us to bind to a string and leaves us without type hint.

This resonates with some other ideas I’ve been toying with, namely that the user-interface container might better be separated from the domain container. They can be wired up separately from each other, making it easier to package the Domain portions independently from the user-interface portions, and enforcing a “physical” boundary between the two.

Overall, congratulations to Jeroen on putting together such a good writeup.

Radar Project Skeleton Now Stable

I am happy to announce that the project skeleton for Radar, an Action-Domain-Responder system for PHP, is now stable and available for use.

One significant difference between this release and the last alpha is that it now uses the standard pds/skeleton names for directories. Existing Radar projects will not need to change directory names, but be aware that starting a new project with the 1.0.0 version will use “public/” instead of “web/”.

Many thanks to everyone who contributed to this release, especially Jake Johns, who put together a post-create-project command to “clean up” the initial installation.

ADR with HTTP Caching

Great conversation with “MatTheCat” on Github today, regarding HTTP caching headers and the ADR pattern.

A quick summary:

  • You want to return a 304 “Not Modified” response if the proper preconditions are met.
  • You can only tell if the resource is unmodified if you touch some form of storage.
  • In ADR, one rule of thumb is “if it touches storage, it probably goes in the Domain.”
  • So you need to do all the precondition-checking in the Domain, not in the Action.
  • The Domain can return a payload indicating “not modified” as appropriate, and the Responder can read that payload status to send back a 304.

You can read the whole thing here. Thanks for the great question Mathieu!

Why Do PHP Developers Think MVC Is An Application Architecture?

I’ve pointed out before that Model-View-Controller is a user interface pattern, not an application architecture. But why would PHP developers get the idea that MVC is an application architecture in the first place? (This may apply to all server-side developers, not just PHP folks.)

I used to think that MVC was an application architecture. Even after reading Fowler’s POEAA and seeing that MVC was for the user interface, I figured that meant I was doing “user interface applications.” But that was not quite right; it would have been more accurate to say that I had been mixing the concerns of user interface with the underlying core application.

Based on that experience, I think the reason MVC is mistaken for an application architecture is because PHP developers generally start with page scripts. In our first page scripts, we combine all the concerns in a single ball of mud: SQL queries are intermingled with HTML, and the business logic is scattered throughout. As far as we are concerned, the page script itself is “the application.” Later, as more functionality is required, we add another page script, and another, and another. We continue to see that collection of page scripts as “the application.”

Then, as we progress in our profession, and begin to learn how to better organize our work, we start separating the different concerns of “the application.” When we begin separating concerns, we separate them out of the page script, which we see as “the application.” Extracting the view concerns from the page script means extracting them from “the application.” Separating the model from the page script into its own layer means separating it from “the application.” Pulling the controller logic out of the page script means pulling it out of “the application.” So of course Model-View-Controller is seen as an application architecture – we separated the concerns of our application according to that pattern, right?

Except, in retrospect, it’s not. One of the big leaps we have to make is to realize that MVC is for the user interface portion of our systems, just like Fowler notes. We on the server side think the user interface is HTML, CSS, and Javascript, but it’s not. Instead, the user interface is the HTTP Request and Response. In other words, the template is not the View.

Once we make that conceptual leap, we begin to realize that the Model layer is the entry point to “the application”. That is where “the application” should live, or at least where it should look like it lives. The Controller should have little to do but take input from the Request and pass it to the Model; likewise, the View should do nothing but put together the Response using the output from the Model.

With that idea of server-side MVC, we then begin to see that a lot of what’s in server-side MVC frameworks is “too much.” Framework functionality that is not related to merely taking input from a Request and presenting output through a Response becomes entirely secondary to, perhaps even actively harmful to, building well-structured applications – applications that are independent of any particular user interface.

Afterword

The server-side MVC pattern, as descended through Sun’s Model 2 architecture, is so distinctive from the client-side MVC pattern as to be a completely different thing. I realized this as I was writing my book on modernizing legacy applications, and further research led me to write up Action-Domain-Responder as a web-specific alternative to MVC. Action-Domain-Responder places a much stronger emphasis on the HTTP Request and Response as the user interface elements. If you are interested in building better applications, you may wish to read the ADR essay, and try it out in your next project.

Command Bus and Action-Domain-Responder

Over the past few weeks, different people have asked me where a Command Bus goes in an Action-Domain-Responder system. While I’m not a DDD expert, after brushing up on the subject a little, my answer is: “In the Domain.”

First, let’s recall the three components in ADR:

  • “Action” is the logic that connects the Domain and Responder. It uses the request input to interact with the Domain, and passes the Domain output to the Responder. (The Action is intentionally “dumb”: it should have no logic at all, aside from perhaps the most minimal of ternaries to allow for default input values. If the Action has a conditional, it is doing too much.)

  • “Domain” is the logic to manipulate the domain, session, application, and environment data, modifying state and persistence as needed. (The word “Domain” here is explicitly intended to remind you of “domain logic” and “domain-driven design.”)

  • “Responder” is the logic to build an HTTP response or response description. It deals with body content, templates and views, headers and cookies, status codes, and so on.

Next, let’s see what Command Bus is. There’s a lot written about it elsewhere …

… so I’ll try to sum up here:

  • A “Command” is a typed or named set of inputs (essentially a data-transfer object) that gets sent to a “Command Bus.”

  • The “Command Bus” then hands off the “Command” to a “Command Handler” specific to that “Command”; the “Command Bus” figures out which “Command Handler” to use from the name or type of the “Command.”

  • The “Command Handler” uses the “Command” inputs to perform some sort of activity.

This series of objects is part of an overarching architectural pattern called Command Query Responsibility Segregation (see here and here). Under CQRS, writes (Commands) are handled separately from reads (Queries). Handling a Command modifies data but does not return a result, while handling a Query returns a result but must not modify data.

This means that a Command Bus does not actually return a result for inspection. You dump a Command into the Bus, and you’re done; there’s no checking for errors at that time. To conform to CQRS properly, you have to perform a separate Query in order to determine the result of the Command.

At this point, just from having read the literature on the patterns and concepts, we can see that Command Bus and its related components are part of the domain layer, not part of the user interface layer. With that in mind, it seems like Command Bus is a candidate for the “Domain” portion of Action-Domain-Responder, to be used like this in an Action:

class CreateItemAction
{
    public function __construct(
        CommandBus $domain,
        CommandResponder $responder
    ) {
        $this->domain = $domain;
        $this->responder = $responder;
    }

    public function __invoke(Request $request)
    {
        $input = $request->getParsedBody();
        $command = new CreateItemCommand(
            $input['item_name'],
            $input['item_description']
        );
        $this->domain->handle($command);
        return $this->responder->createResponse();
    }
}

So the Action gets constructed with a CommandBus element as an entry point into the Domain, and with a generic Responder to build the response. At invocation time, the user interface code sends along the current HTTP request; the Action pulls data out of it to create Command to send to the Command Bus, then tells the Responder to create an HTTP response. (Because a Command never returns anything, one Responder should suffice for all Commands in this setup.)

This is straightforward as an minimal case, but I think it avoids at least two substantial issues.

  1. Where does input validation go? (Input validation, or form validation, is separate from domain model validation.)

  2. Where does error handling go? (While a Command might not return anything, the various elements related to CQRS might very well throw exceptions or raise errors.)

In what we think of as server-side MVC, those two concerns might well be placed in the Controller somewhere. Translating a Controller method directly to an Action, that might look something like this:

    public function __invoke(Request $request)
    {
        // get the input and validate it
        $input = $request->getParsedBody();
        if (! $this->validate($input)) {
            // create an "invalid input" response
            return $this->responder->invalid($input);
        }

        // create the command
        $command = new CreateItemCommand(
            $input['item_name'],
            $input['item_description']
        );

        // try the command
        try {
            $this->domain->handle($command);
            // succcess!
            return $this->responder->success();
        } catch (Exception $e) {
            // there was some sort of subsequent failure
            return $this->responder->failure($e);
        }
    }

On consideration, that seems like a lot of extraneous activity in the user interface layer. In ADR, the Action is intentionally supposed to be dumb. It should not be doing anything even remotely interesting, and certainly should not be dealing with any conditional logic.

As such, I say that Command-related activity should be taken out of the Action entirely, and relegated to something like an Application Service or some other Domain entry point. That Service is what should perform the Command-related activity.

Further, while a Command may not return a result, a Service certainly can. This means that the Action can call the Domain and get back a Domain Payload as a result, which can then be passed to the Responder for presentation.

Under that way of thinking, we get something more like this:

class CreateItemAction
{
    public function __construct(
        ItemService $domain,
        CreateItemResponder $responder
    ) {
        $this->domain = $domain;
        $this->responder = $responder;
    }

    public function __invoke(Request $request)
    {
        $input = $request->getParsedBody();
        $payload = $this->domain->create($input);
        return $this->responder->createResponse($payload);
    }
}

class ItemService
{
    public function create(array $input)
    {
        if (! $this->validate($input)) {
            // create an "invalid input" response
            return new InvalidInputPayload($input);
        }

        // create the command
        $command = new CreateItemCommand(
            $input['item_name'],
            $input['item_description']
        );

        // try the command
        try {
            $this->domain->handle($command);
            return new CommandAcceptedPayload();
        } catch (Exception $e) {
            return new CommandRejectedPayload($e);
        }
    }
}

Now the Domain is fully separated from the user interface. It can be used with both HTTP and command-line interfaces, and tested separately from them. Per the ADR pattern, the Responder becomes responsible for examining the Payload to see what kind of presentation to deliver to the client. Different Payloads result in different responses being built. Finally, the Action becomes entirely uninteresting; all of the business logic has been pushed down into the Domain, where it belongs.

So, to sum up: Command Bus is a domain layer pattern, and should be used in the Domain, not in the Action. A Command cannot return a result, but a Service can, so the entry point into the Domain is probably better as a Service that returns a Payload. This keeps the HTTP and CLI user interface logic well separated from business logic, and independently testable and reusable.