Friday, 16 September 2011

MVC

What the hell is a “Model-View-Controller”?

The Model-View-Controller Architecture, or MVC for short, is a way of programming that separates your application into three main parts:
  1. the Model
  2. the View
  3. and (you guessed it) the Controller
Basically, the separation of these three allows developers to differentiate three aspects of your application:
  1. Business Data (represented by the Model)
  2. Presentation Data (represented by the View)
  3. and Application Logic (represented by the Controller)
This allows for very rapid development – each aspect can be developed side by side by different developers at the same time. For example, we can have a designer working on the View and just allocating spaces where data will appear and at the same time, we can have a developer programming the Controller, who will just provide the View the data to be displayed. While all of this is being done, we can have another developer working on the Models, who will be in charge of retrieving data from the database and implementing the business-specific logic to them, and making sure that there are methods available for the Controller to be able to retrieve the data in different situations.
Using this also makes decoupling and modularization of your application very easy. Since each action on your application will have its own view-controller pair, this pair can be developed separately from another function with little or no setback.
The first time I read about MVC, I was a bit confused about the concept of three separated aspects of my application. I’ve read countless analogies trying to explain the MVC, and for me, one of the best analogies I’ve seen so far was from this article – Another way to think about MVC:
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)*.

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.

MVC in Web Development

Currently, a lot of web applications and Frameworks (Zend, CakePHP, Symfony, to name a few)  make use of the MVC Architecture. According to the Cookbook from CakePHP:
Why use MVC? Because it is a tried and true software design pattern that turns an application into a maintainable, modular, rapidly developed package. Crafting application tasks into separate models, views, and controllers makes your application very light on its feet. New features are easily added, and new faces on old features are a snap. The modular and separate design also allows developers and designers to work simultaneously, including the ability to rapidly prototype. Separation also allows developers to make changes in one part of the application without affecting others.
If you’ve never built an application this way, it takes some time getting used to, but we’re confident that once you’ve built your first application using CakePHP, you won’t want to do it any other way.
A diagram from ash.MVC, another PHP framework which uses the MVC architecture, illustrates the usual data-flow for a web application built with MVC in mind:
  1. First, the browser sends an HTTP request to the web application
  2. A dispatcher usually will get this HTTP request and determine which controller to be used. This dispatcher is usually called a Front Controller (not illustrated)
  3. The appropriate controller will receive it and from the data received, determine which model/s are needed, what data is required and what action is to be done to the data
  4. The model will be told by the controller and retrieve the data and implement any necessary actions. Then, it will return the results to the controller, successful or not.
  5. The controller, based on the results from the model, will then determine which view should be used and provide the view whatever data is to be published to the browser.
  6. The view will receive this data, implement any presentation logic to the data, and return it back to the controller.
  7. The controller will then return the results to the browser.
From this data-flow, we can see what role each part of the MVC plays in every request made.
On a standard web application, the MVC can be represented by the following:

Model

The model, in a web application, is usually composed of classes which represent data from the database and manipulative logic relative to the data. Let say you have a table called “guestbook_entries”. On your application, a Guestbook Model will represent this table, and be responsible for retrieving data from this table in many different situations – for example, on one page, you could probably be viewing all of the guestbook entries, so your model should have a “fetchAll” method somewhere. On another page, you can also be viewing one entry, so this model should also be responsible for finding and retrieving the data of a single record from the table as well. There could also be situations where you need the entries to be retrieved based on a particular post, a date, or even a set of records, limited to 5, starting on the 10th index of all records (read: pagination). All of this should be handled exclusively by the model.

View

The view is obviously the HTML/CSS aspect any web application. The view should never retrieve data from the Model, and should only be able to get this data based on what the controller gives it. This makes the view decoupled from the business logic, and makes it easier to change the logic with little or no effect on the view. This separation also allows for the application to reuse the view, making your application instantly template-friendly. Continuing from our example above, we can have a single view which is used to display a single guestbook entry. On a page which displays all of the entries, we can reuse the html file which displays one guestbook entry,and include it multiple times to show all of the entries.

Controller

The controller is the hub of all requests – it is usually the one who implements the actual application logic to the data-flow. It determines which model and view to use, based on the request that a user sends to it. It is usually represented by the different pages of a web application, like for example, the login page will usually have an Authentication controller, as would a registration page and a downloads page. From our example above, the guestbook page would have a controller, and this controller would be able to support requests for viewing a single guestbook entry and viewing all of these entries as well.

Note: Front Controller

Additionally, most MVC applications implement the use of a Front Controller. Basically, it’s a controller for all of the controllers. It determines which of the controllers is appropriate for specific pages and dispatches necessary information to them. For example, in our guestbook page, we send an HTTP request to view all of the guestbook entries to the application. This request will be received by the Front Controller, and based on the request data (POST, GET), it determines that it should be handled by the Guestbook controller. It will then send the data (the user, wanting to view all of the guestbook entries) to the controller.

No comments:

Post a Comment