SitePoint Sponsor

User Tag List

Results 1 to 13 of 13

Thread: MVC Question

  1. #1
    SitePoint Enthusiast
    Join Date
    Jun 2012
    Posts
    46
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    MVC Question

    When working in an MVC environment, is it ever ok for the View to make a direct call to the Model, or is this bad practice?

    It seems like passing the Views' database requests through their Controllers is sometimes unnecessary, particularly when all you need is an array of data and the Controller processes nothing on its own.

  2. #2
    SitePoint Wizard bronze trophy Jeff Mott's Avatar
    Join Date
    Jul 2009
    Posts
    1,149
    Mentioned
    14 Post(s)
    Tagged
    0 Thread(s)
    You could, and most MVC diagrams certainly imply it's OK. But I think you should avoid doing that. I think the controller should make the database requests and pass that data as parameters to the view. The reason I think that's better is because your view won't be tightly coupled to any particular data source. That means, for example, that you could create dummy data to pass to the view for testing, to see how the view behaves with certain data values, and the view doesn't need to know or care whether the parameters it uses came from a database or somewhere else.

  3. #3
    . shoooo... silver trophy logic_earth's Avatar
    Join Date
    Oct 2005
    Location
    CA
    Posts
    9,013
    Mentioned
    8 Post(s)
    Tagged
    0 Thread(s)
    Actually the view should have direct access to the models. This does not couple the view to a single data source, that is the point of the models. The models decouple the view from the data sources.
    Logic without the fatal effects.
    All code snippets are licensed under WTFPL.


  4. #4
    SitePoint Enthusiast
    Join Date
    Jun 2012
    Posts
    46
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by logic_earth View Post
    Actually the view should have direct access to the models. This does not couple the view to a single data source, that is the point of the models. The models decouple the view from the data sources.
    Apart from whether the View should/shouldn't have access to the Model, this was my understanding of MVC also. Correct me if I'm wrong, but I've been under the assumption the Controller shouldn't have knowledge of the database connection either.

    Jeff, thanks for your reply. It got me wondering about a related MVC question. If the system were aggregating data from a third party web service, should this connection be handled through the Model also? I would imagine so.

  5. #5
    . shoooo... silver trophy logic_earth's Avatar
    Join Date
    Oct 2005
    Location
    CA
    Posts
    9,013
    Mentioned
    8 Post(s)
    Tagged
    0 Thread(s)
    The model handles all forms of data, not just from a database so yes it would.
    Logic without the fatal effects.
    All code snippets are licensed under WTFPL.


  6. #6
    SitePoint Guru bronze trophy TomB's Avatar
    Join Date
    Oct 2005
    Location
    Milton Keynes, UK
    Posts
    988
    Mentioned
    9 Post(s)
    Tagged
    2 Thread(s)
    Quote Originally Posted by Jeff Mott View Post
    You could, and most MVC diagrams certainly imply it's OK. But I think you should avoid doing that. I think the controller should make the database requests and pass that data as parameters to the view. The reason I think that's better is because your view won't be tightly coupled to any particular data source. That means, for example, that you could create dummy data to pass to the view for testing, to see how the view behaves with certain data values, and the view doesn't need to know or care whether the parameters it uses came from a database or somewhere else.
    The view should certainly have direct access to the model. I wrote quite an in depth article on why this is here: http://r.je/views-are-not-templates.html

  7. #7
    SitePoint Wizard bronze trophy Jeff Mott's Avatar
    Join Date
    Jul 2009
    Posts
    1,149
    Mentioned
    14 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by TomB View Post
    The view should certainly have direct access to the model. I wrote quite an in depth article on why this is here: http://r.je/views-are-not-templates.html
    I fully accept and agree that the MVC definitions have the view and the model communicating with each other. The crucial difference I see is that those MVC definitions are written with desktop applications in mind. Web applications are a bit different, because HTTP is stateless. In server-side web applications, there's no such thing as the view reacting to user input, nor updating itself due to changes in the model. And without those behaviors, the view is essentially just a templating system. And when it comes to templates, I think that the less they know about the wider application, the better.

  8. #8
    SitePoint Guru bronze trophy TomB's Avatar
    Join Date
    Oct 2005
    Location
    Milton Keynes, UK
    Posts
    988
    Mentioned
    9 Post(s)
    Tagged
    2 Thread(s)
    Quote Originally Posted by Jeff Mott View Post
    I fully accept and agree that the MVC definitions have the view and the model communicating with each other. The crucial difference I see is that those MVC definitions are written with desktop applications in mind. Web applications are a bit different, because HTTP is stateless. In server-side web applications, there's no such thing as the view reacting to user input, nor updating itself due to changes in the model. And without those behaviors, the view is essentially just a templating system. And when it comes to templates, I think that the less they know about the wider application, the better.
    You lose reusability/modularity though.

    Let's say I have a view which displays information about a user. Their address, email, name and all that.

    If you have a controller doing this:

    PHP Code:
    $user $this->user->findById($_GET['id']);
    $this->template->setVar('user'$user); 
    There are several concerns here:

    -This code needs to be repeated wherever the view is used.
    -The controller could inadvertently omit to set the user variable
    -$user can be anything. Is the view expecting an array? An object? A primitive? There's no way to know.

    Whereas if the controller is doing this:

    PHP Code:
    $this->view->setUser($_GET['id']); 
    The controller is now agnostic about display concerns (what speficic information is needed by the view) and the view can be initialised from anywhere without the repeated data fetching logic.

    In the real world, this makes a big difference when it comes to maintainability. Imagine the view is reused a dozen times and some extra information needs to be added. For example, the latest post the user has made. You now need firsly locate where the view is used, then go through a dozen controllers and add the binding logic for the post. If the view has access the model, you make the change in one place: the view. Which inquires from the model about the new information it requires.

    Wherever the controller contains display logic (e.g. pagination, forms) this logic needs to be repeated which is at best messy. By moving the display logic where it belongs--the view, it's entirely reusable.

    By giving the view a firm contract with a model, the view will always know what is available to it, and it will *always* be available. It's never possible to create state where a variable hasn't been passed into the view by the controller. This is, in effect, the premise of something often referred to as "design by contract" which itself has many benefits when it comes to writing testable and reliable code.

    Whether this is on the web or a desktop application is irrelevant. The same pros/cons apply. The only part of MVC which is redundant is view refreshing (Which is an extension of the pattern anyway)

  9. #9
    SitePoint Wizard bronze trophy Jeff Mott's Avatar
    Join Date
    Jul 2009
    Posts
    1,149
    Mentioned
    14 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by TomB View Post
    -This code needs to be repeated wherever the view is used.
    Controllers can be reused too -- or at least in Symfony they can. You wouldn't need to repeat the data fetching code.

    Quote Originally Posted by TomB View Post
    -The controller could inadvertently omit to set the user variable
    That's true either way. Setting an ID instead of an object won't help you remember to actually call the setter.

    Quote Originally Posted by TomB View Post
    -$user can be anything. Is the view expecting an array? An object? A primitive? There's no way to know.
    That's also true either way. The only difference is your view expects an ID and mine expects an object.

    Quote Originally Posted by TomB View Post
    You lose reusability/modularity though.
    Assuming you can reuse controllers and therefore the data fetching code, I think you actually gain reusability/modularity, because the template becomes more reusable.

  10. #10
    SitePoint Guru bronze trophy TomB's Avatar
    Join Date
    Oct 2005
    Location
    Milton Keynes, UK
    Posts
    988
    Mentioned
    9 Post(s)
    Tagged
    2 Thread(s)
    Quote Originally Posted by Jeff Mott View Post
    Controllers can be reused too -- or at least in Symfony they can. You wouldn't need to repeat the data fetching code.
    They *can* be reused though generally they're not because they shouldn't do enough. A requirement for reusing controllers hints at what Padraic Brady called a "Fat Stupid Ugly Controller" and you have domain logic in the controller. If you're using MVC proper, the time's they're reused are when they're working with a different view. That different view, a lot of the time, is going to be... different.. with different data sets required from the model making reusing the controller with a different view (or indeed a different model) next to impossible. The controller's sole responsibility is to accept user input. If you're capturing events from a view via post/get as long as the view is providing the required information back to the controller the controller has no need to have knowledge of what the view is actually displaying. This makes it more reusable than binding display logic into the controller itself.

    That's true either way. Setting an ID instead of an object won't help you remember to actually call the setter.
    But by using a function the function can type check what it's receiving is what it expects.




    Assuming you can reuse controllers and therefore the data fetching code, I think you actually gain reusability/modularity, because the template becomes more reusable.

    But it's already reusable in the model, which the view can access. Why make the controller a mediator? All you're doing is tightly coupling a controller to a model and the model to the controller. By skipping the middle man, any number of views can use the same model and controller, any number of views can use any number of models providing they have the same interface, and any number of views can use any controller.

    By tightly coupling a model, a view and a controller only the top layer, if the view is replaced OR the model is replaced the controller has to also be replaced to accommodate the changes (e.g. the model returning different data or the view requesting different data). By giving the view access to the model the controller isn't concerned with display logic or model logic and can work with a substituted model or view without needing to be updated.

  11. #11
    SitePoint Wizard bronze trophy Jeff Mott's Avatar
    Join Date
    Jul 2009
    Posts
    1,149
    Mentioned
    14 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by TomB View Post
    The controller's sole responsibility is to accept user input.
    Very true. This seems to be another place where web programs differ significantly from desktop programs. In web programs, there are no keyboard commands, no mouse clicks, no gestures for a controller to accept. The primary input is just a URL, which won't even change during a program's execution. A proper MVC controller hardly has anything to do in a web environment.

    It's probably a misnomer to label server-side web applications as MVC. An awful lot of what MVC solves doesn't even apply to a web application. Ultimately, web applications merely try to achieve good separation of concerns. You're absolutely right that what we call a controller is mostly just a mediator. It allows both the models and the views to be ignorant of the wider application, and I think that's a good thing. The view doesn't need to know where the data comes from.

  12. #12
    SitePoint Guru bronze trophy TomB's Avatar
    Join Date
    Oct 2005
    Location
    Milton Keynes, UK
    Posts
    988
    Mentioned
    9 Post(s)
    Tagged
    2 Thread(s)
    I disagree. Separation of concerns IS the key and arguably, a controller is even more vital on the web. The user intput being $_GET, $_POST and $_FILES. The security aspect alone of keeping domain and display logic out of the controller is important. The controller should take $_GET/$_POST and pass them into the model in a format it's expecting. That's its job, it's all it ever needs to do.

    More important than that though is as you say, separation of concerns. By introducing extra responsibilities into any class (in this case the controller) you lose exactly that. This blog: Flaw: Class Does Too Much contains a good explanation of why sacrificing separation of concerns is bad.

    Let's also keep in mind that most "MVC" frameworks on the web already misuse the pattern by making each function/controller action do view selection. Having a "controller" which handles View/Edit/List for a particular type (e.g. users, products, etc). This breaks a fundamental part of MVC design by making it so a controller is essentially the view and the controller.

  13. #13
    Resident OCD goofball! bronze trophy Serenarules's Avatar
    Join Date
    Dec 2002
    Posts
    1,911
    Mentioned
    26 Post(s)
    Tagged
    0 Thread(s)
    After having gone through quite an exhaustive line of research on my own and talking via PM's with Tom, I think it's important to not simply point out what's wrong with modern web-based MVC frameworks, but explain why it isn't MVC, and what it actually is. I would suggest the everybody who is in doubt, please read the following, along with the links in Tom's signature.

    http://www.garfieldtech.com/blog/mvc-vs-pac

    Having said this, I see nothing wrong with somebody using the PAC architecture, if they so choose, as long as they understand that it isn't MVC, as it is so commonly referred to today.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •