- 9 minutes read

My previous article focused on what the MV* paradigms are. But it didn't answer the question whether using one of the MV* patterns is worth the pain. One thing is for sure: none of the MV* paradigms comes for free. It depends on your project whether using an MV* patterns is a wise investment or a waste of time and money.

Dissecting a chess application

For instance, consider my AngularJS 2.0 chess program (see the source code at GitHub or play it at AngularFaces.com/chess). It doesn't follow any particular architectural pattern. Or rather, it doesn't follow one of the established MVW patterns. To begin with, there's no model. I simply didn't need it. The program's data are stored in the controller component of the program. I don't know all the subtleties of the MV* theory, but I guess it's OK to say the chess demo stores its data in the viewmodel layer.

Actually, the chess demo doesn't consist of many layers. There's the HTML code, there's the chess engine and there's some glue code.

My previous post (and the majority of tutorials) claims that AngularJS favors the MVVM pattern. Let's stick to this fiction for a moment. It's easy to identify the view layer: that's the HMTL pages and the CSS stylesheets. The glue code is the viewmodel. I already said that there's no need for a model layer.

What about the chess engine? It doesn't belong to the view. Nor does it belong to the viewmodel. Nor to the controller. It's an additional layer. Some commenters on reddit called the MV* patterns "overengeneered", but that doesn't stop these patterns from being incomplete. They are a simplified sketch of a part of your application.

Even so, it's not correct to claim my chess application follows the MVVM pattern (or the VVM pattern, for what it's worth). In reality, the TypeScript code and the HTML code are wildly mingled.

The component-first paradigm

When I wrote the chess demo, I was under the impression that Angular 2.0 prefers another architectural pattern. The basic building block of my chess program is the component. It's divided into a couple of components that form a tree structure. I don't have enough experience with Angular 2.0 to say that this approach is the way to go, but it definitely worked well with my chess program. The architecture diagram looks like so:

I went into trouble shortly after passing the magical 1.000 lines mark, but that wasn't caused by a lack of structure. Quite the contrary: there's structure in abundance. Each individual component follows the MVVM paradigm. It has some HTML code, a viewmodel which is called "controller" for some reason, and optionally there's a model.

So the architectural pattern I chose focused on nested components. And I saw that it was good.

Each of these components implements a tiny but full-blown MVVM pattern. But that's merely an interesting detail without much importance to the developer. They care more about how to link components together when they need to cooperate. The second-most important architectural pattern of my chess client is Dependency Injection. It's so important I have to set it in capitals.

What's the benefit of using the MVW pattern?

'nuff said about the benefits of not using the MV* patterns. Dear sceptical redditors, now you know that I do listen to what you say. :) Nonetheless, I do use the MVC pattern at work, and I'm pretty convinced that it's a good idea. Why do I think so?

The key points are

  • separation of concerns
  • large teams
  • flexibility
  • multi-channel strategy
  • and testing.

Separation of concerns

Probably that's the one thing I like most. When I'm looking for a bug, I always have a faint idea where to look. Most bugs have something to do with the view, the model or the controller. More often or not, you don't have to thing twice to guess which layer is affected.

Putting it the other way round, every MV* pattern enables you to keep three of the most important concerns separated. It's a good idea to separate the database access layer from the rest of the application. Database programming is a skill of its own. So is front-end programming. The average pre-dot-NET VisualBasic program used to mingle these concerns. To rename a database column, you had to check the entire program because every source code file might contain a SELECT statement accessing this particular column. Teams following the MVC paradigm only have to check the model layer only. The other layers are not affected, unless you modify the interface of the model layer, too.

Assigning concerns to different team members

Way to many companies use the MVC pattern to form three teams: the UI team, the middleware team and the database team. Personally, I don't think that's a good idea. Reducing a developer to a small wheel in an assembly line does no good to their motivation. I imagine it's hard to make such a team collaborate. I've met middleware developers who've never even seen the GUI of their program. They didn't even care.

I prefer holistic thinking, so degrading skilled developers to assembly-line workers is nothing I recommend. Nonetheless, the MV* patterns allow you organization to build smaller teams according to the architecture pattern. In particular, large and huge teams may benefit from this option.

Flexibility

Back to something I appreciate. The MV* patterns give you a lot of flexibility. I already mentioned renaming a database column. Other examples are introducing new libraries (or update libraries you already use) or refactoring and/or replacing one of the layers. For instance, moving from a DB2 database to an Oracle database used to be quite a challenge in the VisualBasic 6 era. The MVC pattern reduces the problem by three. You don't have to care about the view. Nor is the controller affected by the migration project. You can concentrate on the model. That's still a lot of work, but it's a lot more manageable. Or you could replace the old-fashioned HTML client by a modern AJAX client. Again, MVC reduces the risk by dividing the number of source codes to modify by three.

Multi-Channel strategy

Talking of which: there's an interesting variant of the problem. Who's to say that the MVC pattern implies there's only one view? There isn't. One redditor reported he'd implemented three different clients for an application: a native Android client, a fancy desktop client and an HTML client that was available virtually everywhere.

Testing

Testing is another important benefit of separating concerns from each other. It's hard to test one of the old VisualBasic 6 programs because you couldn't test individual components. When the view directly accesses the database, you can't test the view layer without testing the database layer. The MV* patterns make that a lot easier. Granted, testing UIs is still a pain, but at least you can test the database layer and the application logic independently. Tools like Mockito help to you get independent of the database (which is usually a bottleneck when it comes to testing because databases are so hard to re-install).

But it's so much work!

No, it ain't. Granted, MC* adds a lot of interfaces, which means a lot of extra work. But then, one of the redditors discussing my previous article showed this simplistic example:

var controller = function (event) { switch (event) { case 'start': model = 123; view(); break; case 'increment': model++; view(); break; } }; var model; var view = function () { if (confirm('The value is ' + model + '. Increment?')) { controller('increment'); } else { // Do nothing. } }; controller('start');

This example show the idea of the model-view-controller paradigm in a nutshell. No doubt about it, it's more work than doing it without using a pattern at all:

function step(n) { confirm('The value is ' + n + '. Increment?') && step(n+1); }; step(123);

But the extra effort isn't something to be afraid of. Take your time to ponder about it before starting your project. Chances are the benefits of adding a clean structure to your code outweigh the inconveniences.

So what about the chess program?

My chess demo doesn't implement a classical MV* pattern. But yet, the architecture achieve the same goals. That's because the program is divided into different layers, too. Only they are vertical layers instead of horizontal layers. In other words: the components are aligned to business domains (if such a word is appropriate for a chess game).

There's an interesting side effect: each component consists of the view layer, the controller and the model. They are located in the vicinity to each other. This makes some changes simpler. For instance, modifying the type of a database column probably also required you to modify the controller and the view. Due to the component-oriented architecture, all three files are located within the same folder. In a classical MVC approach, the three files are far away from each other.

Wrapping it up

Granted: the MV* patterns are only one of many other viable patterns, and they aren't the right tool for every pattern. I demonstrated this at length with my chess program. But that doesn't render architectural patterns like MC* useless. Mind you: if you're responsible for designing a new application, you can use one of the proven design, or you can invent your own. Is it really likely that your design is better? If so, go ahead. Unfortunately, many home-grewn architectures are worse than any of the MV* patterns. So most architects and developers are better off with one of the battered designs that have proven their value in zillions of other projects. Your MV* pattern of choice may not be perfect, but it's good enough to do the job.


Comments