Action-Domain-Response: A Tentative MVC Refinement

By | May 5, 2014

UPDATE: This article has been turned into a working draft, with PHP-based example code, at https://github.com/pmjones/mvc-refinement.


(This post is an offering of a first draft, not a final version. I feel very much like I am slowly feeling my way toward something, rather than declaring a completed definition out-of-hand. It may end up being a dead end, or it may already exist in some form with which I am not familiar. Even so, I want to present it for thoughtful, considerate commentary.

The term MVC has experienced some semantic diffusion from its original meaning, especially in a web context. Because of this diffusion, the Action-Domain-Response pattern description is intended as a web-specific refinement of the MVC pattern.

I think ADR more closely fits what we actually do in web development on a daily basis. For example, this pattern is partly revealed by how we generally do web routing and dispatch. We generally route and dispatch not to a controller class per se, but to a particular action method within a controller class.

It is also partly revealed by the fact that we commonly think of the template as the View, when in a web context it may be more accurate to say that the HTTP response is the View. As such, I think ADR may represent a better separation of concerns than MVC does in a web context.

Action-Domain-Response

Organizes a single interaction between a web client and a web application into three distinct roles.

    Action ---> Response
      ||
    Domain 

Terms

Action (taken from <form action="...">) is the logic that connects the Domain and Response.

Domain is the domain logic. It manipulates the domain, session, application, and environment data, modifying state and persistence as needed.

Response is 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.

Narrative

Operational Description

  1. The web handler dispatches the incoming request to an Action.

  2. The Action interacts with the Domain and gets back Domain data.

  3. The Action feeds the Domain data to the Response logic, and then gives control to the Reponse.

  4. The web handler sends the response back to the client.

Compare and Contrast With MVC

The dominant pattern describing web interactions is Model-View-Controller. Is Action-Domain-Response really just Model-View-Controller in drag? We can see that the ADR terms map very neatly to MVC terms:

Model      <--> Domain
View       <--> Response
Controller <--> Action

The two seem very similar. How are they different?

Typically, the View does not consider response headers, only the response body. Also typically, a Controller has more than one action method in it, and managing the different preconditions for these action methods carries its own overhead.

Model vs Domain

I can think of no significant differences here, other than that the Response does not interact with the Domain in meaningful ways. The Response might use Domain objects like entities and collections, but only for presentation purposes; it does not modify the Domain or feed information back to the Domain as described under MVC.

Controller vs Action

In common usage, most Controller classes in an MVC architecture contain several methods corresponding to different actions. Because these differing action methods reside in the same Controller, the Controller ends up needing additional wrapper logic to deal with each method properly, such as pre- and post-action hooks. A notable exception here is in micro-frameworks, where each Controller is an individual closure or invokable object, mapping more closely to a single Action (cf. Slim).

In an ADR architecture, a single Action is the main purpose of a class or closure. Multiple Actions would be represented by multiple classes.

The Action interacts with the Domain in the same way a Controller interacts with a Model, but does not interact with a View or template system. It sets data on the Response and hands over control to it.

View vs Response

In an MVC architecture, a Controller method will usually generate body content via a View (e.g. a Template View or a Two Step View). The Controller then injects the generated body content into the response. The Controller action method will manipulate the response directly to set any needed headers.

Some Controller action methods may present alternative content-types for the same domain data. Because these alternatives may not be consistent over all the different methods, this leads to the presentation logic being somewhat different in each method, each with its own preconditions.

In an ADR architecture, each Action has a separate corresponding Response. When the Action is done with the Domain, it delivers any needed Domain data to the Response and then hands off to the Response completely. The Response is entirely in charge of setting headers, picking content types, rendering a View for the body content, and so on.

Other MVC Pattern Alternatives

How does ADR compare to other MVC alternatives?

DCI (Data-Context-Interaction)

DCI is described as a complement to MVC, not a replacement for MVC. I think it is fair to call it a complement to ADR as well.

MVP (Model-View-Presenter)

MVP has been retired in favor of Supervising Controller and Passive View, neither of which seem to fit the ADR description very closely.

PAC (Presentation-Abstraction-Control)

From Wikipedia:

PAC is used as a hierarchical structure of agents, each consisting of a triad of presentation, abstraction and control parts. The agents (or triads) communicate with each other only through the control part of each triad. It also differs from MVC in that within each triad, it completely insulates the presentation (view in MVC) and the abstraction (model in MVC). This provides the option to separately multithread the model and view which can give the user experience of very short program start times, as the user interface (presentation) can be shown before the abstraction has fully initialized.

This does not seem to fit the description of ADR very well.

Model-View-ViewModel

MVVM seems more suited to desktop applications than web interactions. (Recall that ADR is specifically intended for web interactions.)

Examples of MVC vs ADR

MVC Starting Point

An MVC directory structure for a naive blogging system might look like the following. Note that the index and read views present an alternative JSON type, and the comments template is a “partial” that also presents an alternative JSON type.

controllers/
    BlogController.php # index(), create(), read(), update(), delete()
models/
    BlogModel.php
views/
    blog/
        index.html.php
        index.json.php
        create.html.php
        read.html.php
        read.json.php
        update.html.php
        delete.html.php
        _comments.html.php
        _comments.json.php

Here’s another type of MVC directory structure:

Blog/
    BlogController.php  # index(), create(), read(), update(), delete()
    BlogModel.php
    views/
        index.html.php
        index.json.php
        create.html.php
        read.html.php
        read.json.php
        update.html.php
        delete.html.php
        _comments.html.php
        _comments.json.php

A typical Controller class in MVC might looks something like the following. Note that there are multiple actions within the Controller class, and that the action method deals with the response headers.

<?php
use Framework\Controller;

class BlogController extends Controller
{
    public function create()
    {
        // is this a POST request?
        if ($this->request->isPost()) {

            // retain incoming data
            $data = $this->request->getPost('blog');

            // create a blog post instance
            $blog = $this->blog_model->newInstance($data);

            // is the new instance valid?
            if ($blog->isValid()) {
                // yes, save and redirect to editing
                $blog->save();
                $this->response->redirect('/blog/edit/{$blog->id}');
                return;
            } else {
                // no, show the "create" form with the blog instance
                $this->response->setContent($this->view->render(
                    'create.html.php',
                    array('blog' => $blog),
                ));
                return;
            }
        } else {
            // not a POST request, show the "create" form with defaults
            $this->response->setContent($this->view->render(
                'create.html.php',
                array('blog' => $this->blog_model->getDefault())
            ));
        }
    }

    public function index()
    {
        // ...
    }

    public function read($id)
    {
        // ...
    }

    public function update($id)
    {
        // ...
    }

    public function delete($id)
    {
        // ...
    }
}
?>

The create() logic could be reduced somewhat by moving even more of the model interactions into a Service Layer, but the point remains that the Controller typically sets the response headers and content.

ADR Comparison

In comparison, an ADR directory structure might instead look like this. Note how each Action has a corresponding Response.

Blog/
    Action/
        BlogIndexAction.php
        BlogCreateAction.php
        BlogReadAction.php
        BlogUpdateAction.php
        BlogDeleteAction.php
    Domain/
        # Model, Gateway, Mapper, Entity, Collection, Service, etc.
    Response/
        BlogIndexResponse.php
        BlogCreateResponse.php
        BlogReadResponse.php
        BlogUpdateResponse.php
        BlogDeleteResponse.php
        html/
            index.html.php
            create.html.php
            read.html.php
            update.html.php
            delete.html.php
            _comments.html.php
        json/
            index.json.php
            read.json.php
            _comments.json.php

The Action and Response class pair corresponding to the above Controller create() example might look like this:

<?php
use Framework\Action;

class BlogCreateAction extends Action
{
    public function __invoke()
    {
        // is this a POST request?
        if ($this->request->isPost()) {

            // yes, retain incoming data
            $data = $this->request->getPost('blog');

            // create a blog post instance
            $blog = $this->blog_model->newInstance($data);

            // is the new instance valid?
            if ($blog->isValid()) {
                $blog->save();
            }

        } else {
            // not a POST request, use default values
            $blog = $this->blog_model->getDefault();
        }

        // set data into the response
        $this->response->setData(array('blog' => $blog));
        $this->response->__invoke();
    }
}
?>
<?php
use Framework\Response;

class BlogCreateResponse extends Response
{
    public function __invoke()
    {
        // is there an ID on the blog instance?
        if ($this->data->blog->id) {
            // yes, which means it was saved already.
            // redirect to editing.
            $this->setRedirect('/blog/edit/{$blog->id}');
        } else {
            // no, which means it has not been saved yet.
            // show the creation form with the current response data.
            $this->setContent($this->view->render(
                'create.html.php',
                $this->data
            ));
        }
    }
}
?>

Again, we can see numerous refactoring opportunities here, especially in the domain model work. The point is that the Action does not perform any Response work at all. That work is handled entirely by the Response logic.

Benefits and Drawbacks

One benefit overall is that the pattern more closely describes the day-to-day work of web interactions. A request comes in and gets dispatched to an action; the action interacts with the domain, and then builds a response. The response work, including both headers and content, is cleanly separated from the action work.

One drawback is that we end up with more classes in the application. Not only does each Action go in its own class, each Response also goes in its own class.

This drawback may not be so terrible in the longer term. Invididual classes may lead cleaner or less-deep inheritance hierachies. It may also lead to better testability of the Action separate from the Response. These will play themselves out differently in different systems.

39 thoughts on “Action-Domain-Response: A Tentative MVC Refinement

  1. Hari KT

    Great post Paul.

    I agree with one action per class. Sometimes I have noticed 1000’s of lines of class and actions which is hard to deal with.

    Also this will be helpful not to create objects which are not needed for a class.

    Eg : When we just need to return a string we may not need the view object or session object or a db connection. Else we inject all the dependencies even if it is not needed for a particular action via setters or params .

    Thank you and looking forward seeing it in action in Aura :) .

    Reply
    1. Aaron Scherer

      I think the “1000’s of lines of class and actions” is solved fairly easily with proper SOLID principles. That being said, this is still an interesting structure.

      Reply
      1. pmjones Post author

        > I think the “1000′s of lines of class and actions” is solved fairly easily with proper SOLID principles.

        Agreed; I opine that this structure would allow for easier SOLID implementation. E.g.: single-responsiblity of one action for a class, rather than many actions in a class; and: only injecting the dependencies needed for a particular action, vs. having optional setter injection for some actions and not others. (These are of course tradeoffs in a design.)

        Reply
        1. Hari KT

          > only injecting the dependencies needed for a particular action, vs. having optional setter injection for some actions and not others

          I feel injecting only certain dependencies for a method / action is not possible with Aura.Di container . Correct me if I am wrong.

          Reply
          1. pmjones Post author

            You are correct. That’s exactly the point I am making. In a controller class with several action methods, where each action has different dependencies, you need to inject every dependency for every method. In a single action class, you inject only the dependencies for the one action.

    2. pmjones Post author

      > I agree with one action per class.

      I only came around to this because of our discussions about “Presenters” in Aura. Working through that problem led to the idea of actions paired with their own responses.

      > Also this will be helpful not to create objects which are not needed for a class.

      Exactly right. Inject only the objects needed for a particular action, not all objects that might be needed by any action in a controller.

      Reply
  2. Christopher Pitt

    Very interesting. I would love the giant convention-reset of having a new word for model. Not just another name for database entity as models seems to be widely purported. PoC sometime?

    Reply
    1. pmjones Post author

      More discussion first, then a POC. Thanks man!

      Reply
  3. James Fuller

    I dig it man. I never liked having a ton of actions in a controller and seems like a good solution. In my current project we have something called “Executables”, which are kind of like the Action/Controller (they only implement one method, execute()). These classes pull in form state, get data, utilize services to get/set/update data, return view content, set headers, do session stuff, etc.

    I look forward to hearing more.

    Reply
    1. pmjones Post author

      > In my current project we have something called “Executables”, which are kind of like the Action/Controller (they only implement one method, execute()).

      That is *exactly* the kind of thing I want to hear about. Patterns are supposed to describe what people are already doing, not prescribe new ways of doing things. I’ve been toying with the one-action-per-class thing myself but not put it into real use, so your report confirms that it is in fact an in-use solution. Thanks dude!

      Reply
      1. Stephan Hochdörfer

        Same here. We are using the idea since a few years. Never understood the idea of a Controller class with action methods. Seen too many god-controllers out there. Dealing with many, many (action) classes is not a problem, that`s what an IDE is made for ;)

        Reply
        1. pmjones Post author

          @Stephan: Do you all have any public documentation on that work? I’d like to cite it in the final version.

          Reply
  4. user

    It looks very nice. I would like to see full example, a github repo with working copy of given blog sample, with some Domain elements.

    Reply
  5. Gary Hockin

    This is a very interesting idea. I truly like the idea of the response being a first class citizen of the design pattern. I’ve been saying for years that either FIG or PHP SPL should include a Response object and this is a step closer to how I’d like to be working.

    I’m now very tempted to prototype this using ZF2 components :)

    Reply
  6. cordoval

    Paul you need to immediately check work done by beberlei and igorw and ocramius, please check EBI pattern, I do this already and if i am not mistaken you want to see EBI or a form of EBI and maybe also the example from igorw douchswag and davedevelopment. Also check FOSRestBundle and FOSRest. That is what comes to my mind. I don’t want to be reductionistic. However the way you explain it sounds the whole reasoning many people did not document. You are a good historian because your deduction basically explains all the history that has gone through. I like rediscovering things in the light of a good explanation! who doesnt!

    Reply
    1. pmjones Post author

      @cordoval: Google reveals little for “EBI pattern.” If you could provide links to the resources you are talking about that would help a great deal. Thanks!

      Reply
  7. Matthew Weier O'Phinney

    Nothing surprising here considering our past conversations. :)

    One thing I’ll note, however, is that I think there are some arguments for the web handler and/or dispatcher to be able to manipulate and return responses. As examples, content negotiation can and should usually happen prior to dispatching an action, as should HTTP method negotiation; verification of authentication credentials (I’m thinking “Authorization header” here) can and should happen prior to dispatching an action; etc. In each of these cases, you have no need to hit the domain, and the response is quite different than if you were doing a successful action call (by successful, I mean that the content negotiation passes, credentials are valid, and the HTTP method is allowed).

    I’m also not 100% convinced you need a separate class per response. For testing purposes, you can often introspect a response to see if it contains expected artifacts. Either way, however, you definitely end up with something that can be more easily tested, and which better models the web request lifecycle.

    Reply
    1. pmjones Post author

      > As examples, content negotiation can and should usually happen prior to dispatching an action, as should HTTP method negotiation; verification of authentication credentials (I’m thinking “Authorization header” here) can and should happen prior to dispatching an action

      (/me nods) This makes me think that there should be some sort of “preconditions” logic of some sort attached to the Action so that the logic is collected in a place related to the Action.

      > I’m also not 100% convinced you need a separate class per response.

      I can easily imagine a generic response logic class that would be reused for common responses. The main point I wanted to make there was that the Response logic is entirely separate from the Action logic.

      Reply
      1. Adrian

        > I’m also not 100% convinced you need a separate class per response.
        I’ve been looking at Go a lot lately and the first thing that occured to me was this. You get a canned Response[1] object that handles all the low level stuff. All you need to do is add the content.

        Food for thought.

        [1] http://golang.org/doc/articles/wiki/#tmp_3

        Reply
        1. pmjones Post author

          /me nods

          Note that the updated version at https://github.com/pmjones/mvc-refinement/ talks about a “Responder” and not a “Response” per se. Some systems keep a shared Response around for the system to use as a whole, and other systems rely on the internals to generate a Response to indicate the processing is done. The point with the Responder is that the work of “building/populating/manipulating the Response” is completely separated from the Action (or Controller) work.

          Reply
  8. Pingback: Paul Jones: Action-Domain-Response: A Tentative MVC Refinement | facebooklikes

  9. Jeremy Cook

    This is really interesting. I’ve been reading a lot about Domain Driven Design and Hexagonal Architecture recently and this seems like a great way to square MVC and DDD. Using the approach you suggest it’s easy for me to think of the action classes/methods as adapters that grant access into the domain (for want of a better description). Thanks for posting this.

    Reply
  10. devosc

    I’ve always refactored frameworks to have individual actions per controller, this idea is not new and I was first introduced to the idea by the Agavi framework.

    In todays current context (being a ZF guy), I would suggest the term ActionListener, becuase that individual Action is effectively an event listener which allows you to prioritize and separate the concerns of the request of that Action, e.g authorization, form validation.

    What I haven’t completely figured out is how best to handle the responses (which is the crux of Paul’s discussion), because we only want to inject objects that are needed and are actually going to be used, especially for the “response”. In ZF2 terms there is the ViewModel, and Response objects. But there in lies a difficulty because the Action (or ActionListener) would need to know about all of the possible outcomes.

    As Paul suggests about decoupling the action logic from the response logic, and I think that this can be best handled as a seperate “event” that is triggered after the action has been executed and will transform this ‘ResponseEvent’ or ‘ActionResponse’ into a contextual response (e.g http response). This would be similar to rendering a ZF2 ViewModel into the content of a http response object.

    So I think this can be handled by having a series of events, this would be a lot more flexible, and the Responder would not be invoked by the Action, it would be invoked as its own event?

    Reply
    1. pmjones Post author

      > individual actions per controller, this idea is not new

      (/me nods) Not trying to claim that it is; patterns attempt to describe things that already exist, not prescribe things that have not been done before.

      > (being a ZF guy), I would suggest the term ActionListener

      Sure, that might be one implementation of an Action. Can’t try to be too specific in the description, though, as there are other ways of doing an Action.

      > how best to handle the responses (which is the crux of Paul’s discussion)

      Yes, exactly! Note that there is a followup working draft based on this article where the current-new name is Action-Domain-Responder.

      https://github.com/pmjones/mvc-refinement/

      The idea is that the Responder handles the logic for building the eventual response. Events, or anything else, might invoke the Responder after the action.

      Reply
  11. Jean-Claude Hujeux

    As a Aura user, I thougth I’d share my experience, as I recently refactored my application from a “ton of actions’ structure to something that looks to me close to what Paul is describing, even if not with the same exact words (at the time I read about MVC, MVP, PAC, MVVM, etc., and that was before Paul’s article, I ended up with something like Controller / View / Action / ActionView or ActionModel, could not decide :-)).

    Just a bit of context: I am using the dojo javascript framework on the browser side, whereas the server side relies extensively on the following Aura components: Web, View, Session, Http, Router, Uri, Sql, Intl, and DI.

    The application is a single page application with one or several dojo tabs, and the user normally interacts with (business) domain objects within a tab: each tab displays a view of the object (‘edit’, ‘overview’, … ), and for each view, a number of actions can be triggered (edit, save, reset, open tab for another domain object, etc.).

    After refactoring,

    – An uri sent by the browser as the result of user interaction is:

    /index.php/myApp/{page|tab|dialogue}/{domain object}/{view: edit|overview}/{action: edit|reset|save|...}?param1=...

    – the code structure has become:

        index.php -> builds the route / request / query from the uri
            myApp.php -> dispatches towards appropriate overall controller if authorized and sends back http response to browser
            Controllers
                Page.php -> called once to initialize and display the page
                Tab.php -> called to display a new tab. Dispatches towards appropriate object controller, gets from it the http response and sends back to myApp
                dialogue.php -> called to interact within a tab. Dispatches towards appropriate object controller, gets from it the http response and sends back to myApp
            Domain objects
                Generic object
                    controller.php -> Object controller class,  triggers the appropriate action controller if allowed, gets its response, and transforms into http response
                    abstractmodel.php -> common business domain data manipulation (get/update/insert/ ...)
                    abstractview.php -> common view description and manipulation (common widgets and methods)
                    Controller actions
                        abstractaction.php -> groups code common to all actions
                        Edit Actions
                            tab.php -> extends AbstractAction, triggers the appropriate action model and returns its response
                            save.php -> extends AbstractAction, triggers the appropriate action model and returns its response
                            ...
                        Overview actions
                            ...
                    Views
                        abstractviewmodel.php
                        Edit view and actions models
                            view.php
                            getmodel.php -> extends AbstractViewModel, returns a response
                            savemodel.php -> extends AbstractViewModel, returns a response
                            ...
                        Overview view ans viewmodels
                            ...
                Domain object 1
                    model.php -> extends abstractmodel
                    view.php -> extends abstractview
                Domain object 2
                    ...
    

    controller.php is now 65 lines of code, including the following response method which dispatches towards the appropriate object action controller:

        function response($request, $query){
            if ($this->user->isAllowed($request['object'])){
                try{
                    $controllerActionClass = 'myMib\\Objects\\ControllerActions\\' . $request['view'] . (isset($request['action']) ? '\\' . $request['action'] : '');
                    $controllerAction = new $controllerActionClass($this);
                    return $controllerAction->response($query);
                }catch(){
                }           
            }else{
            }
        }
    

    and a typical action class is 20 lines of code, for example the save action for the edit view (real code):

    actionModel  = new EditSaveModel($this);
            $this->getModel  = new EditGetModel($this);
        }
        function response($query){/* $query is ignored, provided for consistency with other controller actions*/
            $savedId = $this->actionModel->save();
            $data = array_merge($this->view->userAtts(), $this->getModel->get(['id' => $savedId]));
            return ['title' => $this->view->tabEditTitle($data['value']), 'data' => $data];
        }
    }
    ?>
    

    Creating a new domain object is also very fast and compact (a mere extension of AbstractModel and AbstractView, only describing what’s specific to this domain object, although this was already the case before refactoring as this was my main design goal).

    I also use intensively:

    – dependency injection in the respective class constructors, having now the granularity to only inject / instantiate what is needed for the specific action

    – cascading Abstract classes (AbstractModel, AbstractView, AbstractAction, etc…) to minimize code duplication thanks to inheritance, which was a risk with the one action / one class approach.

    Before this, the equivalent of controller.php was a large file, with a huge switch statement dispatching toward the appropriate action methods for the respective actions, with some of the code pulled into separate files in a failed attempt to keep it modular and maintainable enough. Overall, I have a few more files than before, and maybe slightly less lines of code (as refactoring is normally associated to cleaning and simplification). More important,

    – for each user interaction, much less lines of code get loaded by the php executable (thanks also to Aura’s lazy loading capabilities)

    – the overall code structure is much easier to understand and then to maintain and expand, idem for each individual source file which now almost always fits on one screen (and requires less comments, the part of the source file which I find the most difficult to maintain …).

    Hope you’ll find this useful,
    Rgds,
    jc

    Reply
    1. pmjones Post author

      JC — That is an outstanding writeup. I’m also very happy that it touches on Aura and on refactoring. Nicely done!

      Reply
      1. Jean-Claude Hujeux

        Thanks,

        Too bad indentation got lost when I saved the text, makes it hard to read :-(,
        jc

        Reply
        1. pmjones Post author

          I have taken the liberty of adding some formatting tags to your post. Let me know if it is not to your liking.

          Reply
  12. Pingback: Quick Hits: ADR Pattern Progress, MLAPHP Softcover, Aura Notices | Paul M. Jones

  13. Pingback: Stephan Hochdörfer: Controller classes vs. Action classes | facebooklikes

  14. Pingback: Episode 3: The One with Paul talking about Action-Domain-Responder | PHP Podcasts

  15. Pingback: Tabelle für INPUT erzeugen und Daten in MySQL updaten - php.de

  16. Pingback: Hilfe - If-Elseif-Bedinung NUR fast richtig - php.de

  17. Pingback: Zufallssystem macht Probleme - php.de

  18. Pingback: [Erledigt] Probleme beim übergeben der Werte - php.de

Leave a Reply

Your email address will not be published. Required fields are marked *