This post is part of The Software Architecture Chronicles, a series of posts about Software Architecture. In them, I write about what I’ve learned about Software Architecture, how I think of it, and how I use that knowledge. The contents of this post might make more sense if you read the previous posts in this series.
MVC was created in 1979, in a context of desktop applications with CLI user interfaces and it implied that the UI would be changed automatically if there were changes in the database, caused by some factor external to the user. The same pattern was perfectly usable later on desktop applications with a GUI.
However, its usage in web applications has always been an adaptation because most web applications don’t change the UI as a consequence of changes that happen in the server side, there is always a call from the UI asking the server side for an update of the screen.
I have talked about variants of the MVC pattern before, this post is about another variant: Action-Domain-Responder, created by Paul M. Jones.
2014 – Action-Domain-Responder
The ADR pattern was created by Paul M. Jones back in 2014 and the idea is, as RMR, to adjust MVC to the context of web REST APIs. The original explanation of ADR is quite simple and clear, I can’t really rephrase it much better, so I will just copy/paste parts of it here, and add just a few more comments.
Is the logic to connect the Domain and Responder. It invokes the Domain with inputs collected from the HTTP request, then invokes the Responder with the data it needs to build an HTTP response.
You can see an example action here.
Is an entry point to the domain logic forming the core of the application, modifying state and persistence as needed. This may be a Transaction Script, Service Layer, Application Service, or something similar.
You can see an example of a domain entry point here.
Is the presentation logic to build an HTTP response from the data it receives from the Action. It deals with status codes, headers and cookies, content, formatting and transformation, templates and views, and so on.
You can see an example responder here.
How it works
- The web handler receives an HTTP request and dispatches it to an Action;
- The Action invokes the Domain, collecting any required inputs to the Domain from the HTTP request;
- The Action then invokes the Responder with the data it needs to build an HTTP response (typically the HTTP request and the Domain results, if any);
- The Responder builds an HTTP response using the data fed to it by the Action;
- The Action returns the HTTP response to the web handler sends the HTTP response.
The HTTP response is built by the Responder by parsing and understanding the domain response, which in turn depends on the use case of the action method. This means that each action method needs a specific Responder. If we would put all of the resource methods in the same controller, we would need to instantiate and inject all the Responders but we would only use one in during an HTTP request, which is obviously not optimal. The solution is then to have only one method in each controller. This controller and its only action method are what ADR refers to as Action.
Since the Action only has one method, the method name can be something generic like
execute, or in the case of PHP
__invoke making the class a callable. However, because the idea is to adapt the MVC pattern to the context of an HTTP REST API, the Action (Controller) names are mapped to the HTTP request methods so we will have Actions with names as
Delete, …, making explicit what controller is called for each HTTP request type. As an organization pattern, all Actions on a resource should be grouped under a folder named after the resource.
Misconception of ADR
I disagree. I actually think Anthony Ferrara understood it wrong (he seems quite smart and knowledgeable, but it happens to all of us):
In RMR the Resource is not the Domain, it is a domain object, it is a domain entity, while Domain in ADR relates to the whole of the domain objects, all the entities and their relations as a whole;
In RMR the Representation is the response sent back to the client, in ADR a Responder is an object whose responsibility is to create the response, given some content and some template.
- “it shares RMRs coupling to HTTP that it becomes difficult to make a non-HTTP interface”
Since ADR sees the Domain as a whole and not as an Entity, the Action is not inside a domain object, it simply asks the domain objects to perform some business logic. So the Domain is not coupled to the UI, we can create a CLI command that uses domain objects to execute some task.
My take on this pattern
It seems to me that, at the moment of this writing, ADR is the best adaptation of MVC for the HTTP request/response paradigm because it clearly adapts the HTTP requests and responses to the Domain requests and responses while still keeping the Domain completely decoupled from the presentation layer.
The HTTP requests methods (desired actions on the resource) are explicitly connected to the code receiving the HTTP request because each HTTP method maps directly to a controller method name. This has the added benefit of resulting in clear, explicit and predictable code organization as opposed to controllers with plenty of actions, often unrelated, often poorly named and therefore unpredictable, often doing extremely similar things. In other words, it prevents a muddy spaghetti of controllers and actions.
Furthermore, it also does a great job at decoupling the code that is about the interaction itself (invoking the domain) from the code that is about understanding the interaction result (the domain response) and translating it to the client.
Nevertheless, there are some points to take into consideration:
- This pattern was thought of specifically for REST APIs, so in this form it is not refined enough to be used in web applications with an HTML interface (ie. what would be the name of the action to show a form, prior to creating a resource?);
- Having only one method per controller makes this pattern more verbose, because, for example, instead of having one controller (class) with 4 actions (public methods) we will have four controllers and four actions;
- Creating Responders for each action also adds verbosity to the pattern. If the logic to translate the domain response into an HTTP response is simple we should consider if it is worth using a Responder. Not using Responders would mean that we would be able to have several methods in each controller, each of them still mapping to an HTTP method.
Considering points 2 and 3, Paul M. Jones acknowledges them himself and agrees that in some cases it can be acceptable to use a simplification of the pattern that, although not as elegant, can be enough for the context at hand.
Regarding point 1, I think the pattern can easily be extended so that it is fully usable with an HTML interface: We can emulate some extra HTTP methods specifically to handle the HTML requests that a REST API does not have. For example, in a REST API we can use a
PUT or a
POST to create and/or update a resource and that is all it is needed, however with an HTML interface we need to show a form prior to sending a
PUT request, but there are no HTTP methods that specify that the client requests a form to create a resource, nor a form to edit a resource. Nevertheless, we can emulate this by using a
GET request with a header of
edit which the front controller can interpret and forward the request to the corresponding Action named
Edit which would then reply with the corresponding HTML form. We would need, however, to be very careful and minimalistic about the extra custom HTTP methods we create… otherwise it might lead us to a plethora of custom HTTP methods and a mess of custom HTTP methods tied to actions spaghetti!! So, proceed with care regarding this last suggestion of mine.
2014 – Paul M. Jones – Action Domain Responder
2014 – Paul M. Jones – Action-Domain-Responder (Vimeo)
2014 – Paul M. Jones – The Template Is Not The View: A Brief Introduction to ADR (Youtube)
2014 – Paul M. Jones – Action-Domain-Responder: A Refinement of MVC (slides)
2014 – Anthony Ferrara – Alternatives To MVC
2018 – Paul M. Jones – Model View Controller and “Model 2”
2018 – Paul M. Jones – Comparing “Model 2” MVC to ADR
2018 – Paul M. Jones – Tradeoffs in ADR
2018 – Paul M. Jones – Objections to ADR