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.