views:

72

answers:

2

I've been learning about the Model-View-Controller paradigm ("MVC"), but I'm quite confused since some tutorials contradict other tutorials.

My current understanding of the process looks something like this:

Router / Dispatcher / Front Controller:

  • Though not specifically referenced in the "MVC" name, the Router is still a very important part. It is here that requests are translated from raw URLs to a specific controller. For example, routing a request for www.StackUnderflow.com/question/123 to the "Question" Controller of the application.

Model:

  • This is where raw data is collected from some storage source, such as a database or XML file. The model serves as an abstraction layer, translating the Controller's request for specific data into (for example) an SQL query, and translating the query results into a standard format like a data object.

  • For example, in the /browse/all scenario stated above:

    • The "Question" Controller would ask the Model "Please give the data for question 123."
    • The Model would then translate that into "SELECT * FROM Questions WHERE Id = 123;" and punt it to the database
    • The database would return a "Question" record to the Model.
    • The Model would take the record, and translate it into a Question data object
    • The Model then asks does the same thing "SELECT * FROM Answers WHERE QuestionID = 123;" and creates an array of Answer objects from the resultset, and adds that to the Question object's answers member variable.
    • The Model would return the Question object to the "Question" Controller.

Controller:

  • This is the real workhorse of the application. In addition to relaying messages back and forth to the Model and the View, the Controller is also responsible for things like Authorization and application/"business" logicEdit: Per answer, business logic belongs in the Model.

  • In the ongoing example, the Controller wold be responsible for:

    • Ensuring the user is logged in.
    • Determining the QuestionId from the URL.
    • Determining which View to use.
    • Sending HTTP codes and redirecting if needed.
    • Asking the Model for data, and store needed data in member variables.

View:

  • By and large, the View is the simplest part of the application. It mostly consists, in a basic application, of HTML templates. These templates would have placeholders to insert data into the template from the Controller's member variables:

e.g.

<html>

  <head>
    <title>
      <?php $question->getTitle() ?>
    </title>
  </head>

  <body>
    <h1> <?php $question->getQuestionText(); ?> </h1>
    <h2> Answers: </h2>
    <div class="answerList"> 
      <?php formatAnswerList($question->getAnswers()); ?> 
    </div>
  </body>

</html>
  • The View would also contain methods to format data for delivery to the user. For example, the formatAnswerList() method above would take an array of answers, taken from the Controller, and loop through them while calling something like include $markupPath . "/formatAnswer.inc" which would be a small template of just an answer container.

Questions:

  • Is this view of MVC fundamentally accurate?
  • If not, please carefully explain which components are misplaced, where they should actually go, and how they should properly interact with the other components (if at all).
  • How many classes are used to describe this? In my example there are four objects - one each for the three components of MVC and one that simply stores related data for transmission. Is this normal, or should some be combined. If so, which ones?
+1  A: 

I think this description puts too much weight on the controller and not enough on the model. The model is ideally where the business logic resides. The controller is really just an interface for the user of the site, routing control where it needs to go. Take a look at a previous discussion on the topic:

http://stackoverflow.com/questions/3109715/understanding-mvc-whats-the-concept-of-fat-on-models-skinny-on-controllers

David
I think I see where you're going with this. A lot of what I have in the Controller is actually part of the Model, and the abstraction layer I have in the Model is probably more of a separate entity (possibly considered a subset of the Model) rather than the purpose of the Model, is that correct? Could you possibly update your answer to specify which pieces of my Controller should stay and which should go to the Model? Also, should the M, V, and C all be separate classes, or should they be combined in some way. If so, which parts form which classes? Thanks.
AgentConundrum
Your example is pretty good already, honestly. I was mostly remarking on the "workhorse" comment on the controller. It's the UI workhorse maybe, though a lot can be done in the view logic, but the model is the domain workhorse. As in a different answer, a key thing to note is that the Question entity (record as you called it) and Question DTO (object as you called it) are separate. One should be modifiable without affecting the other.
David
@David: I realized while reading Giles' answer that I had possibly been confusing wrt the classes, though I thought it could be inferred from context what I meant. As far as "Question" objects were concerned, I saw four in the example. QuestionM (the model), QuestionV (the view), QuestionC (the controller), and plain old Question which served mainly to encapsulate the data - it could just as easily have been an array rather than an object I suppose.
AgentConundrum
@David: More to the point, are there examples I used in the Controller that don't belong there? I think everything there was confined to either describing state (and the QuestionC, to my understanding, is also in charge of remembering state) or passing information to/from the view or model. Should the HTTP code part (or in fact anything HTML related, such as meta tags, such as keywords, or the page title) be part of the view, or are they fine in the controller? The example used is very CRUD-oriented, and I don't want to get confused down the line: so you're saying all heavy-lifting is Model?
AgentConundrum
@AgentConundrum: No, I think the examples of the controller in the question are pretty spot-on. Naturally, as much presentation should be in the view as possible. But there's always presentation-related things that need to be handled by the controller, as in the examples you give. For my sites, probably the most common piece of logic in a controller is per-action authorization. Based on the current authentication token, it checks against roles and allows or refuses an action based on that.
David
@David: Excellent. I think I'm really starting to understand this. Please accept this 'Accepted Answer' bonus as a token of my appreciation. :)
AgentConundrum
@AgentConundrum: Aw, I was actually hoping for a zero-score accepted answer. I'm pretty close to an Unsung Hero badge. I don't know if un-voting after the fact will have the same effect, though, so might as well keep the vote :)
David
@David: I just tried to undo the vote, but since it's been two hours since I voted, the vote has become locked. If you edit the answer (something trivial), I'll retract the vote and see if that helps. If not, I'll unaccept the answer and see if accepting it again at 0 votes gives you the badge. It would be nice to give someone a Gold badge, but I don't think Unsung Hero is as simple as "accepted with zero votes" - check out some of the people who have them and you'll see what I mean. Also, it says "Zero score accepted answers: more than 10 and 25% of total." Dunno what the last part means...
AgentConundrum
@AgentConundrum: I appreciate it, but don't worry about it. From what I can tell, all I need is a total of 11 zero-score accepted answers (more than 10) before I reach a total of 44 accepted answers (25%). I've got 4 to go. It's that easy, note the Tenacious badge where I had 6 zero-scores (more than 5) before I had 30 total (20%).
David
A: 

Essentially you have everything in the right place.

In your example you define a Question class - which would be known as a ViewModel, simply a container for all the data that is to be used in the View/ retrieved from the View.

In some cases I have seen the ViewModel overlooked and the Model is passed to the View - this confused me when I was first looking at tutorials, and I don't like omitting the ViewModel, I think it confuses things.

Giles
Is your ViewModel my Controller, or am I getting confused? I was looking at the pattern as being three distinct objects (hence why my View referenced $question rather than $self). With what you're saying about overlooking the ViewModel, would that be like having no Controller and just having the Model and View talking directly to each other?
AgentConundrum
Think of the model as your actual domain of objects and logic, the viewmodel as a simple POCO DTO that gives data to the view, and the controller as the switchboard operator that passes the information along (and handles any UI related things, like session state, that don't belong in the model.
David
@David: Ok, so the "ViewModel" is just what you call an object used to hold data-only for transfer/storage, the Model is for working on the data, the Controller is for storing data/state and passing data between Model<->View, and the View is just for rendering the HTML? Is that essentially correct?
AgentConundrum
@AgentConundrum: Sounds about right. The Model can get pretty complex. For most of my sites, the business logic is kept behind a service layer and the Model is essentially just an interaction with the service. It ends up being more procedural than I'd like in that case, but it is what it is.
David