Another way to think about MVC

This is just a simple intro post to the concepts of MVC. It is intended for those who are starting to grasp the basics, but are having a bit of a hard time understanding some of the rules and concepts.

We’ll use this interesting analogy that I thought works quite well to further clarify some things…

So, let’s imagine a bank.

The safe is the Database this is where all the most important goodies are stored, and are nicely protected from the outside world.
Then we have the bankers or in programmatic terms the Models. The bankers are the only ones who have access to the safe (the DB). They are generally fat, old and lazy, which follows quite nicely with one of the rules of MVC: *fat models, skinny controllers*. We’ll see why and how this analogy applies a little later.

Now we’ve got our average bank workers, the gophers, the runners, the Controllers. Controllers or gophers do all the running around, that’s why they have to be fit and skinny. They take the loot or information from the bankers (the Models) and bring it to the bank customers the Views.

The bankers (Models) have been at the job for a while, therefore they make all the important decisions. Which brings us to another rule: *keep as much business logic in the model as possible*. The controllers, our average workers, should not be making such decisions, they ask the banker for details, get the info, and pass it on to the customer (the View). Hence, we continue to follow the rule of *fat models, skinny controllers*. The gophers do not make important decisions, but they cannot be plain dumb (thus a little business logic in the controller is OK). However, as soon as the gopher begins to think too much the banker gets upset and your bank (or you app) goes out of business. So again, always remember to offload as much business logic (or decision making) to the model.

Now, the bankers sure as hell aren’t going to talk to the customers (the View) directly, they are way too important in their cushy chairs for that. Thus another rule is followed: *Models should not talk to Views*. This communication between the banker and the customer (the Model and the View) is always handled by the gopher (the Controller).
(Yes, there are some exception to this rule for super VIP customers, but let’s stick to basics for the time being).

It also happens that a single worker (Controller) has to get information from more than one banker, and that’s perfectly acceptable. However, if the bankers are related (otherwise how else would they land such nice jobs?)… the bankers (Models) will communicate with each other first, and then pass cumulative information to their gopher, who will happily deliver it to the customer (View). So here’s another rule: *Related models provide information to the controller via their association (relation)*.

In our bank it would look something like this:
Worker Andy -> asks banker Bob Buzzkillington -> who asks another banker Jim Buzzdickenson -> who gets the loot from the safe (the DB).

In CakePHP terms it looks very similar:
$andysInfo = $this->Bob->Jim->grabMeSomeLoot();

So what about our customer (the View)? Well, banks do make mistakes and the customer should be smart enough to balance their own account and make some decisions. In MVC terms we get another simple rule: *it’s quite alright for the views to contain some logic, which deals with the view or presentation*. Following our analogy, the customer will make sure not forget to wear pants while they go to the bank, but they are not going to tell the bankers how to process the transactions.

Well, that about covers most of the basics. I hope this analogy helps somebody rather than confuses them even further…

Let’s just summarize some rules and concepts:

  1. Fat models, skinny controllers!
  2. Keep as much business logic in the model as possible.
  3. If you see your controller getting “fat”, consider offloading some of the logic to the relevant model (or else bad things will start happening!).
  4. Models should not talk to the views directly (and vice versa).
  5. Related models provide information to the controller via their association (relation).
  6. It’s quite alright for the views to contain some logic, which deals with the view or presentation.

P.S. Any suggestions on clarifications or additions to this little article are welcomed as always.

43 thoughts on “Another way to think about MVC

  1. Nicely done, Teknoid! I enjoyed that analogy. It’s most likely due to the fact that I work in the banking industry and have been working over the past 2 years exclusively on a banking application written in CakePHP. With that said, I can neither confirm nor deny that any of our clients are “fat, old and lazy” :P

  2. Nice post Teknoid, I enjoyed reading this.

    However I think the analogy makes more sense if you actually understand MVC already, which is unfortunately often the case with such analogies! I would be interested to know if anyone not familiar with MVC found this explanation helpful.

    After doing security-analysis on a non-cake php app today, I can confirm there are still people who don’t understand the importance of decoupling / MVC, so I hope your post helps those people and I can stop having these WTF moments while reading other people’s code.

  3. @Adam

    You might be right, unfortunately there is no way for me to tell if this is actually helpful or just a bunch of weird gibberish :) Hopefully at least the summary of rules will put someone on the right path of thinking about MVC.

    @marius

    Absolutely, no need to ask even… I don’t believe in copyrights and all that nonsense (of course a little link back would be nice :))

  4. Creative Commons Attribution License! :) I think WordPress has a plugin that allows you to add a CC license, and considering how much useful information you have on this blog for CakePHP users, I think requesting a link back for those that wish to use your information to be a good thing.

    Ok, back to the topic at hand. I have a question over a situation I have with one of my apps that if given the chance, I’ll do over again completely from scratch (leaving only the database and data intact). It was my first CakePHP project afterall.

    It’s a voting/ranking application. Once per week, one registered user may vote on a set of options. On the “add vote” page, there are the same number of dropdown boxes as optional votes for the week, all set in an ordered list. So, assuming there are 10 items to vote on in the database, the first dropdown box will assign 10 points to that item, the second dropdown in the list will assign it 9 points, and so on, accumulating points to create a ranking system.

    The problem is that once the system has points in the database, a business rule is activated. No item can be voted +/-2 ranks from its position the week before. As this is business logic, I feel it should be handled by “the banker”, but at the same time, that means there’d be N number of requests to the database in order to create the lists, rather than a single query to access the current ranking order, and let PHP do the work in the view (which is what I’m doing now). But, the controller, from what I understood, should be what smooths over the data for the view, simply passing data values, but primarily simple modifications. I’m accessing a global variable for the rule CONST number being passed in from the controller (+/- *2*), and…well, I don’t know.

    The more I think about this specific situation, the more I get confused as to where it should be. :)

  5. Now I get it ;) Just joking. Fantastic analogy. I always wanted to become a banker but unfortunately, I’m only a gopher!

  6. @Beth

    Ohh… I hope you get through this tough line of work :)

    @Brendon

    I honestly tried to figure out your issue, but the holiday season (aka vodka) had slowed me down just a little bit… hopefully I’ll (or somebody more responsible) will have an answer soon… ish…

  7. @Tarique Sani

    Well, I would hate the break the analogy there :) Plus we’d agree that on a basic level it’s better that controllers handle the “communication”.

    Completely unrelated, could you shoot me an email? I have some potential projects that I may need to “offload” very soon to a trustworthy bunch of CakePHP devs. I know that you guys have been around for a while, so I was hoping you’d have some room for extra work (all paid).

  8. @teknoid: Thanks for the reply here and on Stack Overflow.

    I feel like I have the concept straight now, but I’m still pretty shaky on the execution. In moving logic from controllers to models, I’ll be relying heavily on model callback methods and custom model methods, correct?

    Only two pages in the Cookbook dedicated to this:
    http://book.cakephp.org/view/76/Callback-Methods
    http://book.cakephp.org/view/72/Custom-Methods-and-Properties

    And of the numerous Cake tutorials I’ve looked at, I can’t recall one that uses these. If you’re considering topics for upcoming blog posts, I’d love to see some material on writing methods for your models.

  9. @Ryan

    No problemo.

    Yes, the model callbacks like afterFind() and beforeSave() is where you’d like to move some/most of the logic.
    As far as writing your own methods, it is not different than simply wrapping some logic inside a good ol’ function(). Actually if you search around the blog, I have quite a few posts that directly or indirectly show how to deal with model methods.
    Plus, don’t be afraid to take at the cake core, you can learn quite a bit ;)

    HTH

  10. @teknoid: Will do! And FYI, I subscribed to this thread but didn’t receive any of the email notifications (in my inbox or spam filter).

  11. @teknoid: I just realized…my specific business logic belongs be in the view in this paradigm, but if I have repetitive business logic it should be separated in to a Helper. It just randomly dawned on me, figured I’d post back. Such a simple solution too. :P

  12. I am a beginner in the CakePHP MVC framework. Your analogy has helped with the headaches I have had learning MVC. But, what do you suggest for the learning curve of having to know linux / unix commands? I seem to get stuck there (as I haven’t gone through computer science yet in the university), and pay the other guys to do that stuff on our server…

    Thanks,

    Filling in the knowledge gaps while trying to build a business.

  13. @Jared

    IMO, the system administration world is changing… with new cloud services available from many vendors, your tasks as sys admin really diminish.
    “Everything” comes pre-installed, firewalls are fully manged, you don’t need to worry about system resources with burst-able setups. Even load balancing and content delivery networks are ready to work out-of-the-box (with services like CloudFront).
    It’s important to pick the direction of what exactly you’d like to learn, for basic unix commands there are countless google results that will answer almost any question, or, of course, you can go an old-fashioned way and buy a book ;)

  14. What an excellent anology! Think this has finally got the concept straight in my head, now off to try find some example implementations. Thanks!

Leave a comment