Action-Domain-Responder: A Tentative MVC Refinement

UPDATE: This article has been updated into a working draft, with PHP-based example code, at http://pmjones.github.io/adr.

Are you stuck with a legacy PHP application? Subscribe to "Modernizing Legacy Applications in PHP" for tips, tools, and techniques that can help you improve your codebase and your work life!

44 thoughts on “Action-Domain-Responder: A Tentative MVC Refinement

  1. 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 :) .

    • 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.

      • > 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.)

        • > 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.

          • 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.

    • > 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.

  2. 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?

  3. 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.

    • > 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!

      • 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 😉

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

  4. 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.

  5. 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 :)

  6. 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!

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

    • > 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.

      • > 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

        • /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.

  8. 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.

  9. 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?

    • > 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.

  10. 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

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

  11. Hi Paul, very cool post. I’ve been interested in this approach since I first saw the Symfony2 HttpKernelInterface.

    I’ve been working on a “framework” demonstrating some of these concepts, you can check it out at https://github.com/bradyo/commando-php
    It uses RequestHandler interface instead of Action, but similar concept.

    To Jean-Claude Hujeux comment – creating a dispatcher to abstract actions (controller.php) and re-using them is a great way to get arond the “too many Action classes” issue. I give an example of this in my sample application for RestRequestHandler, which is a RequestHandler made up of several abstract RequestHandlers (one for each REST method, i.e. POST, GET one, GET all, PUT, DELETE). For each domain resource you add, you only need to add one RequestHandler (Action) and not one for each action (which would result in class explosion).
    An example of that here: https://github.com/bradyo/commando-php#compositional-rest-modules

    To Matthew Weier O’Phinney point about “global mapping” (i.e. authentication, global request/response manipulation) I think I found a good way of doing that using decoration and delegation. I have a little example for a RequestHandler that does authentication to create an AuthenticatedRequest, and then delegates to handlers that can use the AuthenticatedRequest instead of basic Request. Some benefits are you can potentially make the Request immutable and use decoration through a chain of RequestHandlers to get the final Response in a type-safe, immutable way.
    An example of that here: https://github.com/bradyo/commando-php#delegating-to-decorated-requesthandlers

    I’ll have to check out Aura v2, looks pretty slick.

  12. I love this idea, I’m probably going to use it in my uber-large project.

    ps: Small typo, you say “Reponse” by terms.

Leave a Reply

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