The aim of MVC is to promote good programming practices and code reuse by separating a web application into three layers: data, presentation, and the interaction between the two. By separating these elements from each other, one can be easily updated without affecting the others.
Having a good understanding of MVC will be extremely helpful for anyone who is interested in learning a web framework like the ones mentioned above. Many frameworks are built around Ruby on Rails’s implementation of MVC, so understanding the core concepts well makes learning other similar MVC frameworks much easier.
To understand MVC, we will look at each layer in some detail. Throughout this article, I will use the classic example of a blog to show how the concepts of MVC work in a real application. In short, the model represents the data. The view represents the user interface (the web page), and the controller facilitates communication between the two.
The three layers of MVC in detail are:
The model represents the data in the application. “Data” in this context means the nouns, or things, in the application that can be abstracted (generally using a database). For example, blogs store posts in a database. In an MVC application, this would imply a model called Post. Post would tell the application what type of data a post contains, which is usually a title, a date, and some body text.
In addition to defining the data that a “thing” would contain, it’s also the model’s job to interact with the database where the actual data for posts are stored, and to implement all logic relating to the creation, fetching, updating, and deleting, and other data manipulation of posts. The model is also built on top of an object-relational mapping (ORM), a system that connects the elements of the model object to the appropriate fields in the database. It will automatically handle all interaction with the database, allowing the developer to avoid writing SQL altogether.
The code in the model is often referred to as business logic. Business logic is all the rules that define data and how to interact with it. By isolating the business logic from the presentation layer, it is easier to write and maintain the logic for the application in a way that is both reusable and transportable (perhaps to another framework) without conflicting with the way the user interacts with it on the web page.
A common example of business logic is validation rules. When a new blog post is made, the application developer may want to ensure that the post has been given a title. This would be enforced by the model, because it is a rule applying to the expected format of the data.
When the new post is submitted via web form, the model looks at the data it receives and checks if it conforms to any validation rules that apply. If there are any errors, such as an empty title field in this case, the model rejects the data, and sends an error back to the user. If the data passes validation, the model will open a connection to the database and save a new post record, using its ORM.
It is a common mistake for developers just beginning with MVC to think of models as simply a fancy name for a database. It’s important to remember that the model is not the database, it’s an abstraction of the data itself, and everything the application knows about what the data is and how it works is part of the model. It is considered good practice to put as much of the code as possible into the model. Try searching Google for fat model, skinny controller for additional details on this idea.
The view is the presentational layer of the application: the user interface. The view will look familiar to web developers who have done mostly procedural programming. For the most part, the view is simply the HTML page. Small bits of inline logic are included, such as simple loops to create tables or just printing dynamic data like in any other server-side script.
The goal in creating a good view is to have as little logic as possible – save the heavy lifting for the model and the controller. A view should be simple enough that someone who only works with markup and doesn’t program, like a designer, can work with it easily.
There will be a different view for each different page in an MVC application. In our blog example, the pages for viewing all blog posts, viewing a specific blog post, adding a new blog post, or editing an existing blog post will all be separate pages, and hence, separate views. Web frameworks that use MVC usually offer a method of dividing the view into even smaller sections to further modularize code.
There are many elements of a single page that will be in common with other pages on a site. Consider the logo and branding, navigation, and footer text. These are usually the same on all pages. To keep from repeating all this code in every view, the view offers us a layout (in Rails parlance), an HTML template that contains all the markup in common to multiple pages. When a page loads, the framework will take the specific view for that page and insert it into the overall layout.
MVC frameworks typically offer other features in the view as well, such as helpers, classes that can be included in order to speed up common tasks such as encoding HTML entities or formatting times and dates. Another common feature is what is referred to in Rails as a partial.
A partial is to the view what the view is to the layout. It’s simply a very small chunk of reusable markup that can be inserted wherever it’s needed. A partial might be used in our blog example to contain the markup for an individual blog post. On the page that shows us one specific entry, this partial would be used just once, but on the index page, where all recent posts are shown, the partial would be called in a loop.
Partials are simply another way to organize the code into small chunks, following the programming practice called Don’t Repeat Yourself (DRY), which is one of the core philosophies of rapid development frameworks like Rails.
Think of the controller as the translator between the view and the model. The controller receives requests from the view (the user), decides what to do, communicates with the model as necessary to send or retrieve data, and then prepares a response for the user to be delivered back to the view. If models are the nouns of your application, the controllers are the verbs.
The controller is made up of actions, methods that operate on a model. Our blog would have actions for creating, viewing, editing, and deleting blog posts. When a user follows a link in the application, the request is sent through what is called the dispatcher, which accesses the appropriate action in the appropriate controller.
If a user goes visits a link to a single blog entry, the dispatcher will call the blog controller’s show action. The controller will then ask the model for the data for the blog post that the user is requesting. When the controller receives this data from the model, it will set variables with that data and pass it on to the view.
Again, it is common for new MVC developers to put most of their code into the controller. After all, it is the controller that receives data and decides what to do with it. In best practice, the controller will not do any manipulation of data or user interface itself, it will merely translate between the view and the model. It will present the model with requests for data that it can understand, and it will provide the view with data that it knows how to format and present to the user.
The big picture
Now that we’ve seen the details of the M, the V, and the C, let’s try to get an understanding of the big picture by looking at how they all work together. The diagram below illustrates a standard request cycle in an MVC application.
A typical MVC request cycle
The process begins when a user takes an action on a web page – submitting a form that adds a new blog post, for example. The request is sent to the blog controller, which extracts the data submitted via the HTTP POST request and sends a message to the blog model to save a new post with this data.
The model checks the data against its validation rules. Assuming it passes validation, the model stores the data for this new post in the database and tells the controller it was successful. The controller then sets a variable for the view indicating success.
Finally, the view displays this message to the user back on the web page, and they know their new blog post has been successfully created. If, for some reason, validation of the data failed, the model would alert the controller of any errors, which would set a variable containing these errors for the view. The view would then present the original form along with the error messages for any fields that didn’t validate.
Though there is a lot to take in when first learning MVC, it’s really not as complicated as it sounds. Just remember that the model is the data, the view is the user interface, and the controller is the mediator. Even if not using a web framework that uses MVC design, the principles of separating presentation and business logic in an application are very helpful in creating clean, compact, reusable code that will be fun and easy to work with. Once the concepts of MVC are mastered, learning a new framework is a breeze.