Getting started with the MVC pattern

6 min read

Published on: 01/22/2024

So I guess you might have stumbled upon this blog post because you've read something along the lines of "this framework uses the MVC pattern" or "this is a MVC framework" on a site you visited. But what does that mean? What is MVC? And why is it so popular?

What is MVC?

The abbreviation "MVC" stands for "Model-View-Controller". It is an architectural pattern that is used in many web frameworks and it aims to make your application more maintainable and easier to understand. It does so by splitting your application into three parts (also called layers): the model, the view and the controller. Each of these parts has a specific purpose and they all work together to create a functioning application.

Now you may be wondering: "What is the point of splitting up my application into different parts/layers?" Well, the answer comes down to the separation of concerns. The idea behind the separation of concerns could have its own blog post, but in short it means that each part of your application should be responsible for it's own thing with as little overlap between the parts as possible. If done right, this makes your application easier to understand and maintain in the long run.

Overview of the MVC pattern

A diagram showing how the MVC layers interact

The above diagram shows how the different parts of the MVC pattern interact with each other, but let's go over each part in more detail.

The model layer

This is the layer that is responsible for the data of your application. This is the layer that interacts with your persistence solution (eg. database, file system) and it also contains the business logic.

Now the fact that the model layer contains business logic might be a bit missleading. In most applications the main business logic (that isn't persistence) is stored in it's own layer outside of the MVC pattern, which is called the service layer. For the sake of simplicity, I will assume that the business logic is stored in the model layer in this blog post but you should be aware that the service layer exists (and is usually called by our next layer, the controller).

The controller layer

This is the layer that is responsible for handling the requests that come from the client. It retrieves and stores data from the model layer and then transforms this data into a format that the view layer can understand.

Any side effects that are caused by the request (eg. sending an email) are also handled by the controller layer.

The view layer

Now the view layer might just be the simplest to understand. It is responsible for displaying the data that is passed to it by the controller layer (essentially it's an html template with dynamic content).

Many applications that are made with a framework MVC pattern are missing this layer, these applications are most commonly API applications that only return JSON data to the client and the actual presentation logic is handled in a different client side app.

A real world example

Now that we have a basic understanding of the MVC pattern, let's look at a real world example of how it could be used. For this example we will look at a registration flow using the MVC pattern.

  1. The user fills out a form with their name, email and password and submits it. This request is handled by the controller (which here is class named RegisterController).

Lets look at some code for this controller:

class RegisterController {
    function handleRequest(request) {
        // Validate the request (eg. check if the email is valid in the valid format, check if all required fields are present)
        validate(request);

        // Check if the user already exists
        if (User.alreadyExists(request.email)) {
            return view("register", { error: "User already exists" });
        }

        // Create the user
        const user = new User(request.name, request.email, request.password);

        // Save the user to the database
        user.save();

        // Send an email to the user to verify their email address
        Mailer.sendVerifificationEmail(user.email);

        // Return a new view with the data of the user, notice how we don't pass the password to the view (so we are transforming it)
        return view("verify-email", { user: { name: user.name, email: user.email }});
    }

    function validate(request) {
        // ...
    }
}

Here you can see how the controller ties all thing together. It validates the request, then interacts with the model (we'll look at that in a second), sends out an email (which is a side effect) and finally it returns a view with the data of the user.

  1. Now let's the model layer (in this case the User model). The controller asks the model layer if a user with the given email already exists, this is business logic. After that the controller creates a new user and saves it to the database, this is persistence logic.

Let's look at some code for the User model:

class User {
    constructor(name, email, password) {
        this.name = name;
        this.email = email;
        this.password = password;
    }

    static function alreadyExists(email) {
        // Check if the user already exists in the database
        // ...
    }

    function save() {
        // Save the user to the database
        // ...
    }
}
  1. Finally, the view layer. The controller returns a view with the data of the user, which is then rendered by the view layer.

Here is how the view layer might look like:

<h1>Verify your email</h1>
<p>
    Hi {{ user.name }}, we have sent you an email to {{ user.email }}. Please click the link in the
    email to verify your email address.
</p>

Notice how we use data that was passed to the view by the controller to display the name and email of the user. Replacing the {{ user.name }} and {{ user.email }} with the actual data is done on the server side at the end of the request-response cycle.

Is MVC the right pattern for you?

Let's look at some potential use cases to help you decide if it is the right pattern for your next project.

The MVC pattern might be a good fit if

The MVC pattern might not be a good fit if

Frameworks that use the MVC pattern

Now that we have a basic understanding of the MVC pattern, let's look at some frameworks that use it. Here is a small list of some of the most popular ones:

Conclusion

The MVC pattern is a very popular architectural pattern that is used in many web frameworks. It splits your application into three parts (the model, the view and the controller) and it aims to make your application more maintainable and easier to understand.

Just like any other pattern, MVC has its pros and cons. It is a very popular pattern and it is used in many frameworks, so it is definitely worth learning. However, it is not the only pattern out there and it might not be the best fit for your next project.

Tags:

Web Development
Backend
Patterns