7

I'm trying to wrap my head around models, views, and controllers, but I feel as though the more I read, the more conflicting information I seem to encounter. I guess the general goal is--as far as I've seen--to shoot for fat models and thin controllers, but I'm still a bit baffled by where to put what. Can I give an example from something I'm working on?

This is just a personal project that I'm messing about with in PHP for fun--a mini-game of sorts. Adding timed tasks to an itinerary and collecting rewards when the task completes. So a class kind of like this exists:

class ItineraryEntry {
    public $user_id;
    public $task_id;
    public $completion_time;
}

And another class like this:

class Task {
    public $task_id;
    public $description;
    public $duration; //in seconds
}

So in the user interface, the user sees a task description and clicks something like "Add to Itinerary". Now if I'm understanding correctly, the controller needs to pick up that request and do something with it. But...how much? So for example, I need to figure out when the task will complete. Keeping it simple, that's merely time() + the duration of the task. So does the controller do that calculation and then give it to the model to validate, or does the model just handle all of it? And the controller is really just a glorified router of data?

Then the second part is what happens when an itinerary task completes. So from the user interface, a task will show as completed if the completion time is in the past, and the user will have to click something like, "Claim Rewards". Let's just say it's...I don't know...XP (i.e., experience points)--something that gets updated on the user's account. And let's say that the amount of XP is calculated in some way based upon the difficulty of the task, time required, etc.

So where would I put that calculation? Is that inside the model class for my user object, or do I have a controller that figures all of that out and then sends it to the user object? In the model for my itinerary entry model? And the reason I ask this specifically is because any kind of Claim Rewards code would have to do a couple of things at least:

  1. Actually claim the reward and update the user's account
  2. Clean up the expired task from the database (or marking it completed or something)

So it would be interacting both with the user and the itinerary entry.

A little specific guidance would be really helpful. My brain is starting to hurt from reading all of these explanations that are kind of like what I need to know, but not totally. So thanks in advance!

6

MVC can mean a lot of different things, and the right answer probably looks like, "Whatever works with my framework and whatever else I am using or doing."

This is a topic where understanding history helps you understand why people do things the way they do them, what it means, and how the idea could evolve in the future. The last is important - if you can figure out how people will do things in 5 years, in 5 years you can have 5 years more experience doing it "the modern way" than anyone else! For a full version of the history, see http://c2.com/cgi/wiki?ModelViewControllerHistory.

Here is a summary. Originally MVC appeared for interactive applications. (I know this seems like a diversion, but this will matter.) Every single interactive component - every dropdown, etc, had its own model, view and controller. The job of all three was well defined. The Controller would have a set of possible events that could happen (someone clicked a mouse, pressed a key, another controller passed a message saying do something) that it was supposed to take care of. In turn it knew about a view and a model. The view knew how to draw itself (you were told to scroll down, select item #3, etc). And the model was in charge of the data that determined what was in the view (eg list of entries for a dropdown). Very, very granular. Lots of components. Lots of dynamic interactions.

MVC is still used this way for interactive applications.


Then the web came along. One thing programmers do when they move to a new domain is try to carry along existing patterns. MVC was a proven one. In the context of the web, the only event of interest is "request page X". Suppose that is a page where a user can edit their information. There is going to be a data model associated with it. Think "User object, with these fields". There is going to be a view. Think, "Template for how to show the user." You can even have different views for the same object - if I look at your home page I am allowed to see different information than you are.

So far, so good. Where is the problem? There are many. Here is a short list.

  1. Generating a dynamic web page is usually much more complex than handling a click of a button in an interactive application. Therefore each of the three components is doing a more complex thing than they would in the application case.
  2. It is unclear to people what belongs where. The same code can go in the model, view, and controller, and it is not immediately obvious that it matters where it lives. But random things tend to be particularly easy to insert into the controller.
  3. Complex web pages include multiple things that want data models - for example a form, a sidebar, ads, and so on. How do you represent that?
  4. Over a website you generally have many views, but you want to maintain a consistent view across them. How do you structure your views to allow this, while making them make sense for designers who are not programmers?
  5. Over time we're moving towards richer and more complex interactive pages, with tricks like AJAX. How do you shoehorn this into a per-page mentality that is natural when handling http requests?

And so on.

There are a lot of possible solutions to these, with different tradeoffs. In general if you use a framework, and try to solve things the way the framework expects, things work well. If not, well, then things get challenging. Hence my advice above to do whatever works with your framework.


But there are general principles.

Since controllers have a complex job to do, and are easy to insert additional logic into, the natural progression of code over time is that everything winds up in the all-knowing controller. Single large interacting blocks of code tend to not scale well. So you want to keep everything that can be kept out of the controller, out of the controller. (Some frameworks make things even simpler by splitting up controllers recursively!)

Business logic almost always belongs in the model. If you've got a database and an Object Relational Mapper, it is easy to structure models for simple applications as fairly straightforward layers over database tables. This is a popular design.

The view usually winds up being some sort of template system. How to handle commonalities is up to your template system. Understand the system you use, try to work within it.


You're a self-admitted beginner. I would highly recommend picking a framework, following advised best practices for said framework (even if you later decide they are not best, organizing code like your framework expects tends to be a path of least unexpected surprises), and getting practice with simple applications before tackling anything more complex. I highly, highly, highly recommend this - before trying to run, make sure that you're good at walking.

But as you walk, come back to this post, look at the list of pain points I gave above, think about your did or didn't hit them, and how you could handle them within what you built. This type of deliberate "how would I?" self-reflection is a critical part of improving. As I say, those are known pain points that come up across many different frameworks and I don't think that we've found the best way to handle them yet.


If I had to guess where we'll go, what do I think?

My belief is that as web pages get more interactive, they are becoming more like existing interactive applications. (Have you used gmail with keyboard shortcuts recently?) The more that they become interactive applications, the more that it makes sense to use MVC in JavaScript in the way that it is used in interactive applications. The more complex your front end becomes, the more it makes sense to have the html that delivers that being delivered by code which is structured the same way that the code you are generating is being delivered.

If so, then we should (indeed I believe already are) see front end web pages that have many controllers, many models, and many views which can interact. These will eventually be pushed back to the server which will be expected to generate those parts of the page with similar granularity (albeit with the ability to pass information around so that the JavaScript library that enables X is actually loaded in the appropriate part of the page for that).

I think this in part because I have worked with a proprietary system that was structured this way. It was interesting. There were many controllers, views and models. However the controllers turned into data structures with some data inheritance to handle commonalities, the views into simple templates, and the models were parametrized by information from the controller. The concerns were so well separated that we were able to put the three into three different languages (Perl models, YAML controllers, TT templates). We were able to do things like completely rewrite the back end to the website (literally different pages, accessed in a different order, that were hitting different services) while managing to reuse, unchanged, most of the front end.

It was clear to me that that implementation was not exactly the right way to do it. But I think those ideas will be rediscovered multiple times, and over the next decade I think that is the direction that a lot of people will head.


If this sounds likely to you, and you like front end work, then after getting some simple sites working in whatever server language you want (from the sounds of it PHP, though I personally would prefer anything else), I'd suggest learning JavaScript, picking up a popular MVC framework like http://angularjs.org/, and trying to write interactive applications using it. Pay close attention to what works and doesn't, make your own theories, experiment, get feedback, and you'll be likely to be ahead of the future when the future arrives.


(How did this answer get so long? Oh well, it is written, might as well post it.)

  • 1
    Very thorough. Thank you. To be clear, I'm not a beginner. I've been coding for years in a variety of languages including PHP, C#, VB, and a ton of JS--professionally, even. Just not in an environment that required this sort of structured approach. Personally, I've developed some rather complex games and sites, largely for fun, sometimes to share. I know coding in other words. I know how to make things work in the modern web environment. I just don't work with frameworks and haven't had any use for patterns like MVC. But I do want to learn. So thanks again. – thewatcheruatu Jul 6 '13 at 7:17
  • AngularJS does look pretty interesting, though. I'll have to spend some time with it. Thanks! – thewatcheruatu Jul 6 '13 at 7:47
  • 1
    @thewatcheruatu Sorry, I don't know why I had the impression that you had claimed to be a beginner. But still I highly recommend actually using a couple of very different things that claim to be MVC. When you're done you'll know what people mean, what they don't mean, and have your own opinions about how it does or does not make your life easier. (I've certainly spent time fighting frameworks!) – btilly Jul 6 '13 at 15:32
  • Oh, no worries--I wasn't offended. I could see how you got that impression. I just wanted to clarify that it's not the coding piece so much that is the hurdle, but figuring out new patterns of organizing things when I've been working with websites and application that haven't really required those sorts of approaches. Also, I'm foolishly inclined to want to avoid abstraction layers like frameworks, but I realize I need to start using the things everybody else does, as it would eventually make me a better coder. Anyway, thanks again. – thewatcheruatu Jul 6 '13 at 16:01
2

With whatever model works for you. MVC is a pre-web concept that's not really a perfect fit for a scenario where you have that big giant http wall to chuck stuff over. It's also a heavily loaded marketing term that carries more "serious-sound" weight than practical use to most.

I think of the controller's role as being app logic and I think older-school versions of MVC agree with that.

I think of model as biz logic.

The DB (in my mind) should be separate. Log-in details are really an app-logic concern that interacts with the DB, just as whether or not that user gets a 25% discount is a business logic concern but is also tied to the DB.

The user of the server-side is the browser. Not the guy in front of the computer. Web apps are basically best thought of as two apps. Your job on the server-side is to present something the browser can use.

Am I right by a lot of MVC definitions? Probably not but I'm considering the application in terms of ways I might want to break all but one piece of it out. The DB might work differently but I could keep everything else. The client-side might need different HTML but I keep everything else. I might want the same DB, biz logic, and HTML but app logic details like how users are authenticated and how we need the HTML built/templated might change a bunch.

When you have control, split things out as they're important to be split out to you. People advocating the "one way" to do MVC aren't doing it the way it was originally conceived so don't fret about whether you're doing it right. Just figure out what's right for you.

  • Thanks. Haven't got enough reputation to vote this up, but it was helpful. In the past, I have tended to just come up with solutions that work--not always without much regard for whether it's the best way to do it. I guess I'm just at a point in my career that I feel I should finally understand all of these best practices. But MVC seems very broadly defined, despite some people insisting otherwise. – thewatcheruatu Jul 6 '13 at 3:52
  • Don't sweat it. Use what you can make sense out of. Experiment and have a healthy skepticism of anything you can't. There's a lot of folks out there making money off of telling programmers how to "do it right." They're not necessarily dishonest, but why aren't they making their bucks writing apps? – Erik Reppen Jul 6 '13 at 4:04
  • @ErikReppen "It's also a heavily loaded marketing term that carries more "serious-sound" weight than practical use to most." That's the truth. – johnny Sep 2 '14 at 14:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.