MVC and its alternatives

This post is part of The Software Architecture Chronicles, a series of posts about Software Architecture. In them, I write about what I’ve learned about Software Architecture, how I think of it, and how I use that knowledge. The contents of this post might make more sense if you read the previous posts in this series.

Creating maintainable applications has always been the real long-term challenge of building applications.

Not long ago, I worked for a company whose core business application was a SaaS platform, used by a few thousands of client companies. That crucial application was three years old and had code files with HTML, CSS, business logic and SQL mixed up. Of course, two years after being released, the company decided to rebuild it from scratch. Although these situations still happen, today many of us know these practices are wrong and know how to avoid them.

However, back in the 1970s, mixing responsibilities was the common practice and people were still trying to discover how to do it better. As application complexity grew, making changes to the UI would inevitably imply changes to the business logic as well, increasing the complexity of the changes, the time spent to do those changes and the likelihood of bugs (because there would be more code changed).

MCV came into play to solve those problems, by promoting “separation of concerns” between front-end and back-end.

1979 – Model-View-Controller

MVCWith the intention of solving the issues explained above, in 1979 Trygve Reenskaug came up with the MVC pattern as a way to separate concerns, isolating the UI from the business logic. The pattern was used in the context of desktop GUIs, which existed since 1973.

The MVC pattern separates the code in three conceptual units:

  • The Model represents the business logic;
  • The View represents a widget in the UI: a button, text box, etc.;
  • The Controller provides for coordination between the view and the model. This means it:
    • Decides what views to show, and with what data;
    • Translates user actions (ie. click of a button) into business logic.

A model could be a single object (rather uninteresting), or it could be some structure of objects.

Trygve Reenskaug 1979, MVC

Other important concepts to know about the original MVC pattern is that:

  1. The view uses the Model data objects directly, to show their data;
  2. When the model data changes, it triggers an event that immediately updates the View (remember, in 1979 there was no HTTP);
  3. Each view is, typically, associated to one controller;
  4. Each screen can contain several pairs of view & controller;
  5. There could be multiple views for each controller.

Today’s HTTP Request & Response paradigm, that I’m familiar with, does not use this original MVC flavor because, in this case, the flow goes from the View to the Controller, like what I am familiar with, but then in the other direction it flows directly from the model to the view without passing through the Controller.

Furthermore, in the current Request & Response paradigm, when data changes in the DB it does not trigger an update in a View being shown in a browser (although this could be implemented using web sockets). To see the updated data, the user needs to do a new request and the updated data would always return through the controller.

1987/2000 – PAC / Hierarchical Model-View-Controller

HMVC

PAC, aka HMVC, provides for increased modularity in contexts of widgetization of sections of the UI.

For example, when we have a View with a section that is used in the exact same format throughout several other Views or even simply repeated in the same view. A practical example is a section of a web page with the contents of an RSS feed, which is reused in other pages.

Using HMVC, the controller that handles the main request will forward sub-requests to other controllers in order to get the renderization of the widgets and then incorporate it in the renderization of the main view.

Personally, I have encountered the need for this a few times in a context of HTTP Request/Response paradigm, but I find it a much simpler approach to have the UI make an AJAX call to the controller that can render the widget. This keeps the benefits of modularization without the added complexity of having nested controller calls, and the plus side that these sub-requests can be cached in something like Varnish.

1996 – Model-View-Presenter

MVP

The MCV pattern provided a great improvement in the programming paradigm of its time. However, as applications complexity grew, so it grew the need for further decoupling.

In 1996, the IBM subsidiary Taligent made public their MVP pattern, based on MVC. The idea was to further isolate the Model from the UI concerns:

  • The View is passive and unaware of model;
  • Focus on thin controllers (presenters) that contain no business logic and simply invokes commands and/or queries in the model, passing raw data to the View;
  • A change in data does not trigger an update in a view directly: it always goes through the presenter, which in turn updates the View. This allows for the controller (presenter) to perform extra presentation-related logic before updating the view. For example, also update data related to the data that changed in the DB;
  • There is a single presenter for each view.

This is closer what I am used to seeing in today’s Request/Response paradigm: the flow always goes through the Controller/Presenter. Nevertheless, the Presenter still does not actively update the view, it always needs a new request to be performed for the changes to be visible.

In MVP, the Presenter is also known as a Supervisor Controller.

2005 – Model-View-ViewModel

MVVMAgain, derived from applications increased complexity, in 2005 the MVVM pattern was announced by John Gossman, one of Microsoft’s WPF and Silverlight architects, with the goal to further segregate the UI design from the code and provide data binding from the View to the data model.

[MVVM] is a variation [of MVC] that is tailored for modern UI development platforms where the View is the responsibility of a designer rather than a classic developer. […] the UI part of the application is being developed using different tools, languages and by a different person than is the business logic or data backend.

John Gossman 2005, Introduction to Model/View/ViewModel pattern

The Controller is “replaced” by the ViewModel:

[The View] encodes the keyboard shortcuts and the controls themselves manage the interaction with the input devices that is the responsibility of Controller in MVC (what exactly happened to Controller in modern GUI development is a long digression…I tend to think it just faded into the background. It is still there, but we don’t have to think about it as much as we did in 1979).

John Gossman 2005, Introduction to Model/View/ViewModel pattern

The ideas behind MVVM were:

  • One ViewModel corresponds to only one View and vice-versa;
  • Move view logic to the ViewModel to simplify the view;
  • One on one mapping between the data used in the view and the data in the ViewModel;
  • Binding of the data in the ViewModel to the data in the View, so that when data is changed in the ViewModel it immediately reflects in the View.

Just like in the case of the original MVC pattern, this approach is not possible in a traditional Request/Response paradigm because the ViewModel can not actively update the View (unless using web sockets) and MVVM requires it. Also, the fact that the ViewModel has properties matching the data used in the View is not what is common practice in a Controller, in my experience.

Model-View-Presenter-ViewModel

M-V-P-VMWhen building complex Enterprise Applications for the Cloud, I prefer to rationalise the application UI structure as M-V-P-VM where the ViewModel is what Martin Fowler called a Presentation Model, back in 2004.

  • Model

    A set of classes that contain all the business logic and use cases;

  • View

    A template, with which to generate the HTML using a template engine;

  • ViewModel
    (aka Presentation Model)

    Receives raw data from a query (or Model entities from which to extract raw data), and holds that data to be used in the template. It also encapsulates complex presentation logic, in order to simplify the template. I find that the usage of the ViewModel is especially important because we will not be tempted to use entities in the template, which allows us to completely isolate the view from the Model:

    • Changes in the Model (ie. changes in entities structure) might bubble up and impact the ViewModel, but not the template;
    • Complex presentation logic will not leak into the domain (ie. creating methods in business entities that are exclusively related to presentation logic) because we can encapsulate it in the ViewModel;
    • The dependencies of the template become explicit because they must be set in the ViewModel. Making those dependencies visible can help us, for example, to decide what should be eagerly loaded from the DB to prevent N+1 problems.
  • Presenter

    Receives an HTTP request, triggers a command or a query, uses the data returned by the query, a ViewModel, a Template and a template engine to generate the HTML and send it back to the client. All Views interaction goes through a Presenter.

Here’s a simple (and naive) code example of how I do it:

<?php
// src/UI/Admin/Some/Controller/Namespace/Detail/SomeEntityDetailController.php
namespace UI\Admin\Some\Controller\Namespace\Detail;
// use ...
final class SomeEntityDetailController
{
/**
* @var SomeRepositoryInterface
*/
private $someRepository;
/**
* @var RelatedRepositoryInterface
*/
private $relatedRepository;
/**
* @var TemplateEngineInterface
*/
private $templateEngine;
public function __construct(
SomeRepositoryInterface $someRepository,
RelatedRepositoryInterface $relatedRepository,
TemplateEngineInterface $templateEngine
) {
$this->someRepository = $someRepository;
$this->relatedRepository = $relatedRepository;
$this->templateEngine = $templateEngine;
}
/**
* @return mixed
*/
public function get(int $someEntityId)
{
$mainEntity = $this->someRepository->getById($someEntityId);
$relatedEntityList = $this->relatedRepository->getByParentId($someEntityId);
return $this->templateEngine->render(
'@Some/Controller/Namespace/Detail/details.html.twig',
new DetailsViewModel($mainEntity, $relatedEntityList)
);
}
}
<?php
// src/UI/Admin/Some/Controller/Namespace/Detail/DetailsViewModel.php
namespace UI\Admin\Some\Controller\Namespace\Detail;
// use ...
final class DetailsViewModel implements TemplateViewModelInterface
{
/**
* @var array
*/
private $mainEntity = [];
/**
* @var array
*/
private $relatedEntityList = [];
/**
* @var bool
*/
private $shouldDisplayFancyDialog = false;
/**
* @var bool
*/
private $canEditData = false;
/**
* @param SomeEntity $mainEntity
* @param RelatedEntity[] $relatedEntityList
*/
public function __construct(SomeEntity $mainEntity, array $relatedEntityList)
{
$this->mainEntity = [
'name' => $mainEntity->getName(),
'description' => $mainEntity->getResume(),
];
foreach ($relatedEntityList as $relatedEntity) {
$this->relatedEntityList[] = [
'title' => $relatedEntity->getTitle(),
'subtitle' => $relatedEntity->getSubtitle(),
];
}
$this->shouldDisplayFancyDialog = /* ... some complex conditional using the entities data ... */ ;
$this->canEditData = /* ... another complex conditional using the entities data ... */ ;
}
public function getMainEntity(): array
{
return $this->mainEntity;
}
public function getRelatedEntityList(): array
{
return $this->relatedEntityList;
}
public function shouldDisplayFancyDialog(): bool
{
return $this->shouldDisplayFancyDialog;
}
public function canEditData(): bool
{
return $this->canEditData;
}
}

The template and the ViewModel have a one-on-one match, which means that a View can only be used with a specific ViewModel and vice-versa. This actually even makes me think that maybe we could encapsulate the template and the ViewModel inside a View object, effectively decoupling the Controller from the template and the ViewModel, making it depend on a generic View Interface, but I never experimented with this.

Conclusion

We might find other variants of MVC on the web. However, these are the ones I find more interesting and/or relevant for my work.

Nevertheless, the patterns I referenced here were created for a context of desktop applications and/or rich clients and therefore they don’t always fit 100% to the Request/Response paradigm.

If you are doing Enterprise Cloud Applications and you are using MVC, most likely you are actually using something closer to MVP, but in any case, my point is not about following a specific variant of MVC or know all the names and being annoyingly strict with it, my point is that we should learn from all of them, so we can use and adapt as we need. The end goal is, as usual, low coupling and high cohesion: separation of concerns.

Sources

1979 – Trygve Reenskaug – MVC XEROX PARC 1978-79

1979 – Trygve Reenskaug – MVC

1987 – Joelle Coutaz – PAC, an Object Oriented Model for Dialog Design

1996 – Mike Potel – MVP: Model-View-Presenter: The Taligent Programming Model for C++ and Java

2000 – Jason Cai, Ranjit Kapila, Gaurav Pal – HMVC: The layered pattern for developing strong client tiers

2003 -Trygve Reenskaug – The Model-View-Controller (MVC): Its Past and Present

2004 -Martin Fowler – Presentation Model

2005 – John Gossman – Introduction to Model/View/ViewModel pattern for building WPF apps

2006 – Martin Fowler – Supervising Controller

2006 – Martin Fowler – GUI Architectures

2011 – Mārtiņš Tereško – Architecture more suitable for web apps than MVC?

2017* – Tracy-Gregory J. Gilmore – Never the twain shall meet. The tale of MV*

2017* – Tech notes – MVVM vs MVP vs MVC: The differences explained

2017* – Wikipedia – Model–view–controller

2017* – Wikipedia – Presentation–abstraction–control

2017* – Wikipedia – Model-view-presenter

2017* – Wikipedia – Hierarchical model–view–controller

2017* – Wikipedia – Model–view–viewmodel

2018* – Wikipedia – History of the graphical user interface

* Viewed in

11 thoughts on “MVC and its alternatives

  1. The picture describing MVC is not drawn correctly, in the original description at the link the user interacts with the controller

    Like

    1. The controller is a piece of code presenting views to the user and connecting them with the system, to quote: “It provides […] for relevant views to present themselves in appropriate places on the screen.” and “views provide a special controller, an editor, that permits the user to modify the information”.

      Point being that, it has no visual representation so the user can not interact directly with it.

      On the other hand, the view: “…is a (visual) representation of its model.”. It is what we see when we open a web page. So the user interacts directly with it.

      The drawing is therefore correct.

      Like

  2. Nice blog I wonder how I could have missed it. I’ve been Googleling these subjects for a while and your website didn’t come up.
    I like the view Tom Butler(r.je) has on the subject. I wonder what you think of his thoughts on the matter. I particularly liked his posts about mvc/mvvm.
    I see you also referenced Anthony Ferrara. It’s a shame he never posted last part of his series about this topic. I am intrigued to see what his alternative solution would have been.

    Thanks for taking the time write these articles. I think I am going to read some more. 🙂

    Like

  3. In M-V-P-VM there is any trigger that call changes in View ? Model can trigger event to change View through Presenter and ViewModel ?

    Like

    1. I personally only do web development, and in such context refreshing a view usually implies a browser refresh, so no. Unless we use a reactive pattern with web sockets.

      Like

Leave a comment