Here I will compare the basic structure of a web application in various languages and framework to illustrate the model view controller design pattern and explore some of its most striking features. Since I have been a consumer of this pattern and since I like to question the whys of our common uses of a concept, I wanted to be able to sketch as clear a view as I can of the mvc pattern and its use in the context of web application development.
The model view controller pattern is a pervasive expression, widely used in the software world, particularly for developing web or mobile applications. Let’s start from one very short definition to get us going :
Model–view–controller(MVC) is a software design pattern for implementing user interfaces on computers. It divides a given software application into three interconnected parts, so as to separate internal representations of information from the ways that information is presented to or accepted from the user.
Before exploring the MVC pattern let’s simplify the objects that we are dealing with:
- The model is the data representation, i.e. the business side of the project (what are we storing in our databases, and what are we doing with this data).
- The view is the graphical user interface that the user sees and can interact with. It is the presentation layer of the application.
- The controller is where the logic of the application is handled, it treats the actions of the user.
But what is a software design pattern ? it is supposed to get us a general and reusable solution to a common software problem. This remark of Derek Greer is useful in insisting on the pragmatic aspect of a design pattern: It’s best to think of architecture patterns as being as much in the realm of art as science. Interactive architecture patterns aren’t the computer science equivalent of Newton’s Law of Gravity. They merely represent our ever evolving attempt to apply the best approach for application development. source So what exactly was the problem in the first place ? Since we are exploring the pattern in a web application context, there is a clear answer to this question: avoiding the pitfalls of so-called “spaghetti code” produced by using a classical procedural method. This kind of approach would typically have all the model (data structure / database interactions), application logic (controller) and the view (the html and css templating) in the same page of code. We will use as example a book club web application. In this application the user can browse a list of books submitted by the member of the club, propose a review for one of the book, submit a new book or read the reviews of the members for any book available. Let’s see a very schematized representation of the spaghetti code procedural method for the list of books page.
This kind of implementation is of course doable and can work well for very small one man non-evolutive projects. But, it is probably not suitable for many other uses. To highlight the disadvantages of the procedural spaghetti-code (PSC) web implementation we will quickly examine it through the lens of a prominent software design motto, the separation of concerns. We will use here the formulation of Derek Greer :
The Principle of Separation of Concerns states that system elements should have exclusivity and singularity of purpose. That is to say, no element should share in the responsibilities of another or encompass unrelated responsibilities.
Here we are concerned (pun intended) by vertical separation of concerns: separating elements according to what they are doing (their responsibility in the project). It should be evident that, in figure 1, the separation of concerns is violated since tasks involving data collection are mingled with presentation and logic tasks. In this example, if the developer wants to make a drastic graphical change in the presentation of the list of books, it will be difficult because of the mix of presentation, database manipulation and logic in the code. Testing will probably be difficult for the same reason, in particular unit test will be almost impossible due to the hard coupling of the model, view and controller. So what is the MVC pattern proposition to resolve the “problem” of spaghetti code and hard coupling ? Of course, by separating the concerns, that is, here, by decoupling model, view and controller. Let’s see how a MVC inspired implementation could work for the book club example:
- The model will represent the following data structures: book (author, title, publisher, date of publication, etc.), review (book, author, date), user (pseudo, collection of reviews, collection of books submitted). It will handle reads, updates, deletes and storages of the data in a database.
- Each page of the web site is built around a view - controller duo
- One of the views will be the list of all the books currently available with links/button to submit a new book and read the reviews for each book (click on submit book button = HTTP request sent by the browser). The view will typically be html or some other templating language such as pug or twig. It will finally be rendered by a browser’s engine such as Gecko .
- For example, the controller for the list of books will gather the current list of available books from the model. It will interpret the inputs of the user from the view, collect relevant data by asking the model and send back an HTTP response to the view. In some implementation the view must be first compiled by a controller before sending it as html to the browser for rendering.
To have a more concrete representation of an MVC implementation, let’s examine below a schematic layout of a typical MVC web application (made with symfony 3 or Node.js for example).
What are the advantages and limits of MVC in a web context ?
To sum up, what did we really gained while moving from procedural spaghetti code to an MVC implementation for a web project ? To some, the advantages seemed a little bit abstract at first, and one can even doubt of the interest of the MVC pattern seeing the real increase in complexity. Then, after having worked on a real project in Symfony, I saw more clearly the main benefit: MVC yields to a more m aintainable application :
- More suitable to team working : person one can work on the models and controllers while person two works on the view.
- Readability benefits. An implementation of the pattern will have a structure that is familiar and easily comprehensible by its author or an external party. There will be less duplication (notably from the model, since the model will be accessible by any controller). That means less cognitive stress by relying on well established and useful conventions.
- Easier to create and update u nit tests (since you can separate model and controller unit tests)
- Easier to debug : the source of the bug is easier to identify (a template, a model, a controller), while in a procedural structure, the source of the bug is not identifiable at a glance (since database calls, templating and logic are all in the same file).
Although the advantages are numerous, more and more uses cases challenge the MVC approach for the web. To stress this point, I will briefly talk about my experience of an MVC classical implementation in Symfony2. We first worked on a web application with a standard view in html. Then we had to make a mobile application which would use the model of our web application. To do that, we created a Rest api serving the model in json via http endpoints. We first thought we could have one easily maintainable api. Yet we had to admit that it was not the case when when we add to create a new version of the api for each new mobile project that used our model. We were closer to a BFF approach, i.e. a series of apis taylored for the mobile projects, than to one global api serving our model to a variety of views. While this approach can certainly work with a reasonably large organization, it wasn’t a good fit for our smaller team where the same people worked conjointly on the api part and on the web part. The drawbacks appeared more numerous that we have anticipated:
- A notable code duplication since we basically developed two times the same logic (between apis and between the controller of the web project and the apis)
- A poor maintainability / evolutivity
- Difficulties for testing (double the unit tests for a start)
An alternative with no real “classical” MVC centered around one single Rest api could have avoided us some of these drawbacks:
- The resources (i.e. a model + some logic ) are accessible via http methods GET, POST, PUT, DELETE as a representation in a usable and standard format, typically. JSON or xml.
- The representation (which is nowa he view) can then be served to a mobile application or rendered as html (maybe via a framework such as Angular).
When I realized what we could have gained by questioning our original approach (MVC for web + duplicate logic in Rest api), I learned the hard way not to be too attached to a particular design pattern, even if it is widely used. MVC is not by large the only way to develop a web application. For many other cases, e.g. a micro-service having a very specific role, it would be absurd to try to force the mvc pattern into a project.