purpose
Divide user interface interactions between the web client and the web application into three well-defined roles.

Prerequisites
The term MVC is experiencing some
semantic blurring of its original meaning, especially in the context of the web (see the
video by Stefan Pribsh for more detailed consideration of the issue). As a means of eliminating this blurring, I offer you a description of the
Action-Domain-Responder pattern, which is a refinement of the MVC concept to meet the needs of solving web-specific tasks.
')
I believe that ADR is much better suited to what we actually implement in the web development process day after day. For example, the creation of this pattern was partly inspired by the way we solve the problems of routing and dispatching, because in the case of routing and dispatching we turn
not to the controller class per se, but to a specific action method in this controller class.
Another problem uncovered is that we often view the
View as a template, although in the context of the web it would probably be more appropriate to say that the
View is an HTTP response. Based on the foregoing, I believe that ADR is able to provide better than MVC, the separation of concepts for web applications.
Components
An Action is the logic that binds the
Domain and the
Responder . It uses input data to interact with the
Domain and transmits the
Domain output to the
Responder .
Domain (Domain) contains the logic to control the session, application and environment data, state changes and data management, if necessary.
The Responder is the logic required to create an HTTP response or description of the response. It operates with the main content (body content), templates and views, headers, cookies, status codes and so on.
Interactions
- The web handler receives the request from the client and sends it to Action .
- The action interacts with the Domain .
- The action sends data to the Responder (this data may include the results of interaction with the Domain , data from a client request, etc.)
- The responder generates a response using the data received from the Action .
- The web handler sends the response to the client.
Comparison with MVC (Model-View-Controller)
The most popular pattern describing interactions within the web is the
Model-View-Controller . Is the
Action-Domain-Responder really just a
Model-View-Controller disguise? You may notice that the elements of ADR are reflected in the MVC elements:
Model <--> Domain View <--> Responder Controller <--> Action
The two patterns look very similar. What are the differences?
In general, from Fowler's
GUI Architecture essay [translation
here ] we can see that “you have more than one view and one controller, you have to create a separate view controller pair for each block on the page, each control and for the page as a whole. " This is the main element of semantic blur that occurs when MVC is used in web applications.
And let's compare the individual components of MVC and ADR in more detail.
Model and Domain
I do not see any radical differences in them, except that in ADR the
Respondent does not interact with the
Domain in any significant way.
The responder may use
Domain objects as entities and collections, but only for the purpose of rendering;
The defendant does not modify the
Domain and does not send him any information as provided for by MVC.
Controller and Action
In general, most
Controller classes in a system designed according to the principles of MVC contain several methods, each of which corresponds to a separate action. Since all these methods reside in one
Controller , additional “wrapper” logic is also added to it to work with each of these methods, for example, hooks that are triggered immediately before or after the action itself. A significant exception to this rule is microframes, in which each
controller is a separate closure or called object, which is more appropriate for the
Action (for example,
Slim ).
Within the framework of the same ADR,
Actions are seen as separate classes or closures. In other words, each
Action must be rendered into its own separate class or closure.
The action interacts with the
Domain in the same way that the
Controller interacts with the
Model , but does not interact with the
View or the template system.
The action simply transfers the data to the
Respondent and gives the volume to dispose of them.
Submission and Responder
In the MVC system, the
Controller method typically generates a response body using a
View (for example, through the
Template View or
Two Step View ). The
Controller then integrates the generated response body into the response itself. The
Controller Method, which is the action, directly controls the response to set the necessary headers.
Sometimes, some
Controller methods may provide different response formats for the same data. Since this variability is often not supported by absolutely all methods, the logic of data presentation somehow changes from method to method, with its own conditions in each specific case.
In ADR, each
Action has a corresponding
Responder . When an
Action finishes its interaction with the
Domain , it transfers from the
Domain to the Respondent both all the necessary data and control over this data.
The defendant fully controls the setting of headers, the choice of content types, template rendering and so on.
Note that a
Responder can include a
Template Engine ,
Two-Step Template System , a
Transform View, or any other view system. Also note that a generic
Responder can be used by more than one
Activity . The main thing is that the
Action leaves all the work on the headers and content to the
Respondent , and not that it is necessary to create its
Responder for each individual
View .
Comparison with other patterns
There are other patterns that are considered as refinement, replacement, or addition of the MVC concept. You can read
this review of patterns from Derek Greer .
EBI (Entity-Boundary-Interactor)
The term
EBI has several synonyms: ports and adapters, hexagonal architecture,
ECB (Entity-Control-Boundary). He is described as part of Robert Martin's
Pure Architecture .
EBI is a partial alternative to MVC, in which the main elements and behaviors represented by
Interactor objects and
Entities are separated from incoming and outgoing data using
Boundary . The main consequence of this approach is a clear distinction between the application itself and the intricacies of input and output mechanisms, so that key behaviors never depend on any private system for receiving a request or sending a response.
I admit, I am not very familiar with the concept of EBI, so this description may not be entirely correct in general or in particular. After my incomplete research in this area, I came to the conclusion that the EBI architecture probably describes interactions within the application better than MVC. If the description above is true, then ADR fits pretty well with the EBI structure:
- ADR Action and Responder may serve as a web-specific Limiter
- An ADR Domain can serve as an analogue of Interactor , encapsulating or otherwise hiding elements of EBI Entities from ADR Action.
Alternatively, within the terminology of ports and adapters or a hexagonal architecture, it may be more reasonable to consider the
Action as a “port” through which the EBI
Limiter is invoked (invoke) as part of the ADR
Domain . Finally, the
Respondent can be viewed as an “adapter” through which the application returns data to the client.
However, ADR does not seem to be a direct replacement for EBI. Rather, the two approaches complement each other.
DCI (Data-Context-Interaction)
DCI is described as an addition to MVC , not a replacement. I think it would be fair to call him the ADR supplement to the same extent.
MVP (Model-View-Presenter)
MVP was dismissed by the Supervising Controller and
Passive View patterns. At first glance, it looks very similar to ADR, especially in that the
Passive View and
Model have no dependencies on each other. From the text of Fowler:
The Controller uses the controller both to process the input data and to control the view, allowing you to organize more complex display logic ...
Passive View achieves this by reducing the number of behaviors of UI elements to the absolute minimum by using a controller that not only processes the reaction to user events, but also takes all the work of updating the views. This approach allows you to focus efforts on testing the controller, without worrying about any problems in the views.
Let's take a closer look:
- Model and Domain are quite similar to each other, as is the case with MVC.
- Passive Representation does not fully correspond to the Action or the Respondent ; rather, it can be viewed as a response that is returned to the client.
- The managing controller recalls the Respondent in terms of "managing the view to allow for more complex display logic". On the other hand, the Respondent does not interact with the Domain and does not receive input from the client, so it does not seem to fit the role of the Controller .
- Alternatively, the Controller could be represented as an Action , but the Action is not responsible for managing the views (i.e., the response).
In general, close, but not the same.
MVVM (Model-View-ViewModel)
MVVM is only partially similar to ADR.
The model in MVVM is practically the same as the
Model in MVC and
Domain in ADR. Similarly, MVVM
View is very similar to MVC
View and
Responder in ADR.
However, the
View Model (ViewModel) is not similar to the
Controller in MVC, nor to the
Action in ADR. Since ADR is a refinement of MVC, it is reasonable to assume that a comparison of MVVM with MVC will be similar to that of ADR.
For a detailed description of these differences, I advise you to read the articles by
Joel Venzel ,
Avtar Sing Soha ,
Rachel Appel and
Niraj Bhatt .
(I had an interesting email discussion where I was told that MVVM is very similar to MVC, to which the
View Model was added for interactions between
View and
Model . If this is true, then
View Model can be used in ADRs with same success as MVC).
PAC (Presentation-Abstraction-Control)
From Wikipedia :
PAC is a hierarchical structure of agents, each of which is a triad of representation, abstraction, and control part. Agents (triads) communicate with each other only through the control part of each of them. Another difference from MVC is that in each triad, representation and abstraction (a model in MVC terms) are completely isolated. This approach allows you to process models and views in parallel in different threads, which leaves the user with the impression of a very fast start, since the interface (views) can be displayed before the abstractions are fully initialized.
Not too much like ADR.
RMR (Resource-Method-Representation)
I did not hear about
RMR until
ircmaxell pointed it at Reddite .
ADR and RMR are very similar to each other, and their elements correspond to each other very precisely.
Resource <--> Domain Method <--> Action Representation <--> Responder
However, some of the nuances of RMR make me stay with the opinion that these two approaches are still different from each other. For example:
Thus, within the framework of an object-oriented language, we can consider http-resources (Resource) as objects with private properties and a specific set of public methods (Method), each of which corresponds to the standard HTTP method. In MVC terms, a resource can be represented as a model with a small piece of the controller inside.
To me personally, this just seems like too much mixing of concepts. I prefer to see a clearer separation of the models from the actions performed on the application.
Representation is very similar to Representation in MVC, we give it a resource object and give the command to serialize it into the required output format.
Obviously, this is not true for a number of HTTP responses, such as, for example, “Not Found”. Such an answer is definitely not a representation of the requested resource.
In general, it is likely that ADR can be viewed as an augmented and extended variation of RMR, in which the
resources and actions that can be performed on them, are clearly divided into
Domains and
Actions , and where the
Representation (i.e. response generation) is controlled
The defendant .
Models-Operations-Views-Events (MOVE)
From the
original site :
Models encapsulate everything your application knows.
Operations encapsulate everything your application does.
Views are the link between your application and the user.
Events are used to safely connect all of these elements.
This is a very interesting pattern in itself. The idea of
Models and
Operations seems to be very appropriate within the framework of the Domain-Driven Design approach.
However, I do not think that MOVE is similar to ADR, especially at this point:
Events are exactly what gives MOVE (and MVC) the inversion of control necessary for models to be able to update views without getting information about what kind of view they are updating.
In ADR,
Domain and
Responder do not “update each other.” The work of the
Domain is completed, and the result is transferred to the
Respondent for further display to the client.
Separated Presentation
You can find several indications for ADR, especially
Respondent , in
Separate Views . The article itself is worth reading, but Separate Views are more of a meta-pattern describing general approaches to separating data from their presentation, rather than specific ways to achieve this separation.
Comparison of MVC and ADR with examples
Starting point in MVC
In MVC, the directory structure for a banal blogging system might look something like this. Note that
index and
read provide as an alternative the output in JSON, and the comment template is “partial” (partial) and also allows the output of JSON as an alternative.
controllers/ BlogController.php
And here is another type of directory structure for MVC:
Blog/ BlogController.php
The standard
Controller class in MVC looks something like this. Note that in this
controller class there are different actions, and the methods of these actions set the response headers.
<?php use Framework\Controller; class BlogController extends Controller { public function create() {
The logic of the
create () method can be reduced in some way by making most of the interactions with the model at the
Service Layer , but the essence remains the same - the
Controller is usually responsible for the response headers and content.
Take a look at ADR
For comparison, the folder structure for ADR can be organized as follows. Note that each
Action has a corresponding
Respondent .
Blog/ Action/ BlogIndexAction.php BlogCreateAction.php BlogReadAction.php BlogUpdateAction.php BlogDeleteAction.php Domain/
A pair of the
Action and the
Responder , corresponding to the
create () method described above, could look like this:
<?php use Framework\Action; class BlogCreateAction extends Action { public function __invoke() {
<?php use Framework\Responder; class BlogCreateResponder extends Responder {
Again, you can find opportunities for refactoring in this code, especially with regard to working with the
Domain . The main thing is that the
Action does not do any work for the
Respondent ; all necessary work is done directly by the logic of the
Respondent itself.
You can view the advanced sample ADR code
here .
Comments
Not considered requests
I received quite a lot of criticism for not including the element corresponding to the "HTTP request" in the pattern. An early version of this publication contained such an element and was called the "Request-Action-Domain-Response". However, in further studying MVC and similar architectural patterns, I noticed that none of them define an input element. In order not to stand out from the general row, ADR does not consider this element either.
Not considered Front Controller
The pattern was created to improve the
Model-Application-Controller approach, and not web applications in general. Thus, it deliberately does not consider some of the elements inherent in many web applications, and in particular this applies to the
Front Controller .
The ADR does not describe the element of routing or dispatch, and it also does not describe how
Action and
Responder are associated with dispatch. Routing and scheduling are most often the
Front Controller's responsibility area, and there are many ways to establish interaction between the
Action , the
Respondent and the
Front Controller :
- The action can directly call the Responder , which returns a response to the request;
- The responder and the response can be accessed by the front controller calling them directly;
- An action can return a Responder , which is then called and returns a response, which is called and sends itself;
- and so on.
The ADR pattern does not describe any elements of pre-filtering or request validation, as they may be part of the
Front Controller . Note that, depending on the pre-filtering logic and the validation of the request, the
Action may call the
Responder , or it may return its own response, or cause some additional
Action as a result of its logic, and so on. Similarly, a triggered
Action may have its own set of checks, resulting in a
Responder calling without interacting with the
Domain . The reasons for such “shortened” call chains can be:
- Inconsistency of HTTP methods. If the routing system does not find a match between the HTTP method used and the requested Action , the Front Controller may return an error with an error instead of redirecting the request to the Action .
- Authentication. The presence or absence of client access rights (and their validity) may influence the need to call an Action or interact with a Domain during this Action .
- Authorization The access control system may reject the client's request for a specific Action , or cause the Action to be executed without interacting with the Domain and, possibly, return the response on its own.
- Content mismatch. Front Controller , Action, or other elements involved in processing a request can check Accept- headers of a client request. / .
- . - , .
An ADR can be called a variation on the Controller and Presentation theme in the Model-View-Controller pattern , rather than an independent pattern.Then it turns out that the Action is a variation, similar to the Page Controller , and in this context its more accurate name might be Action Controller . In this case, it will correspond to the controller from MVC. (Moreover, the formal description of a Page Controller is that it represents a “page or action”).Similarly, the Respondent can be consideredas a variation similar to the Template View or Transform View , and then it would be wiser to call it a Response View . Thus, the Responder fits perfectly into the view element of MVC.Notwithstanding the foregoing, I believe that these alternative formulations are not as good and accurate as the description of the approach within the framework of a separate ADR pattern. For the most part, due to internal interactions between the Model and the View : in MVC, the View updates the Model , in ADR the Responder does not updateDomain .Unclear Domain
The domain covers a lot: not only the application class set, but also its state and environment state. It could probably be called a Model , but that would only add further confusion.In addition, it is possible that the Action should transfer to the Respondent not the data received from the Domain , but the Presentation Model . But in this case, it is possible that the Domain called by the Action should return the Model View that encapsulates the state of the application.In any case, ADR is offered as a revision of MVC. On this basis, we can say aboutThe domain in ADR is all the same, what can be said about the Model in MVC.Explaining Actions
One of the commentators noted that the Action can be organized in such a way that different logic works in it, depending on the incoming request. For example, he suggested that readers can extend the Action and add functionality to work with different HTTP methods by placing the logic for different HTTP methods in the same Action .Although in my opinion, the pattern itself expresses the idea that each Action should perform only one function, and this clearly follows from the Controller and Action comparisons and the ADR and RMR patterns, I will clarify once again, more explicitly: the meaning is that every action must perform one and only one action in response to any incoming request.Replacement, not revision of MVC
Nate Eibel objects that ADR should be considered a substitute for MVC used for server applications:I will say that the more I learn about the MVC pattern, the less it seems to me suitable for the server part of web applications. <...> I think the main breakthrough of your ADR idea is to get rid of what seems to me a bad abstraction. I would advise you to avoid describing ADR in MVC terms except where absolutely necessary.
Full comment .Other comments
The original blog post describing this idea is here .Stefan Hochdurfer responded to my idea in this post ; further discussion continued here and on reddit .John Layton wrote about the Focused Controller (Focused Controller), which is very similar to Action from ADR, here .The subsequent post comparing the Submission and the Respondent is here , and the comments on it are read here and here .Akihito Coritama offers his comments here .Advantages and disadvantages
One complex advantage is that the pattern more accurately describes the most typical interaction scenarios on the web. The request comes in and is redirected to the action; the action interacts with the domain, and then the response is built. The work of the response — including the headlines and the content — is entirely separate from the work of the action.One complex disadvantage is that we have to deal with the increased number of classes in the application. Not only each Action will receive its own class , but also each Responder .But this drawback is probably not so terrible in the long run. The need to create separate classes can lead to a clearer and less deep inheritance hierarchy. Separation Actionsand Responder promotes better testability. In different systems, these features may manifest themselves in different ways. Someone noticed that it is more convenient to handle “many classes” in different code editors and IDEs than “fewer classes, but more methods”, since class overview is usually simpler than method overview.Thanks
I express my gratitude to everyone who with their questions, comments, criticism or recommendations helped to work on this proposal. Separately, I would like to thank the following people listed without any order:- Matthew Weier O'Phinney
- Hari KT
- Stephan hochdörfer
- Adam Culp
- Dan horrigan
- Josh lockhart
- Beau simensen