The MVC Paradox

Use of the Model View Controller (MVC) design pattern is generally accepted as a best practice in modern web applications. Like all design patterns, MVC is a reusable solution to a common problem. The MVC pattern is intended to address the following concerns:

Support for multiple types of clients

Reduce duplicate code when supporting multiple types of clients

Isolating domain logic from the user interface

Note that items 2 and 3 are both dependent on item 1. Support for multiple types of clients is the single driving force behind the MVC design pattern. Following are some examples of client types:

Do you really need to use the MVC design pattern in order to support User Agents, Admin Processes, and Unit Tests? Likely not. That’s not to say that there aren’t benefits to isolating domain logic from the user interface. However, if you don’t need to support multiple types of clients you should really question your use of the MVC design pattern. There are many approaches one can take to separating the domain logic and the user interface, of which MVC is just one.

This bring me to The MVC Paradox. Modern MVC web frameworks inadvertently encourage the coupling of domain logic and user interface. If you don’t need to support multiple types of clients, then decoupling the domain logic from the user interface is the only reason left to use the MVC design pattern.

Modern MVC web frameworks often involve a lot of boilerplate code just to support the primary client type of User Agents. This boilerplate code typically does little to help with supporting the other client types of Admin Processes and Unit Tests. As a result of the overhead introduced by this extra boilerplate code, developers often find themselves creating Fat Controllers (a side-effect of The MVC Paradox). Controllers take on too many responsibilities, both vertically and horizontally. Vertically, Controllers start to handle domain logic that should be pushed down to the Model layer. Horizontally, multiple concerns get stuffed into a handful of Controllers. These different horizontal concerns should be separated out into multiple Controllers (the Single Responsibility Principle). The overhead introduced by modern MVC web frameworks leads directly to these problems.

In contrast, take a look at the Slim PHP 5 micro framework. While not a completely RESTful framework, it does a pretty good job of addressing the concerns I’ve laid out in this post. Here is the “Hello world” example from Slim’s homepage:

There is very little boilerplate code involved in handling a User Agent’s request. Minting and handling new routes is incredibly simple. Placing your entire front-end application layer in one file may seem absurd at first. However, it has the nice side-effect of making it painfully obvious if you start to handle domain logic outside of your Model layer or if one route is doing too many things. If your front-end application is large enough, then you can organize your routes into separate files.

This post is not intended to discourage you from using an MVC web framework. There are certainly times when such a framework is useful. As with any technology decision, carefully consider what problem you’re trying to solve and what technology will best address your problem set. Sometimes your technology choice can undermine the very purpose of using that technology in the first place, as is the case with The MVC Paradox.

Interesting point. I mostly aggree with you, but I think that MVCis not important only because of these reasons. If you follow this pattern, your code is going to be easier to maintain, easier to understand.
On the other hand, I am not familiar with Slim, I will give it a try.

Slim looks an awful lot like Silex, which is sort of Symfony2 Junior. I haven’t built anything with it directly yet, but the main issue I see with it, and with Slim (from the one code sample above), is that it’s not going to scale to controllers that have to be complex (lots of form handling) and/or lots of controllers. Drupal (my main development system) has over 300 routes out of the box; it’s not unusual for a site to have nearly 1000 routes by the time you’re done, and yes they all have a purpose. Defining all routes and controllers inline at that point is completely unsustainable, especially from a performance perspective. You’re creating hundreds of closures, only one of which you’ll ever use.

Also, if all of your controllers are defined inline as closures, you cannot unit test them. For a project with a half dozen controllers you can probably get away with that. Anything bigger and you’re really short-changing yourself.

I think frameworks like Slim and Silex “support” spaghetti code too much. IMHO, there is no clear separation of anything. Nothing you can’t do yourself, but then you might be better off with another framework.

On debugging – Silex is kind of annoying in this regard – especially phar’d. Then I’d argue it’s not at all micro if you happen to need something other than routing you step through two dozens of Symfony2 components.

I can’t see how MVC supposedly “Support for multiple types of clients” from accepted definition of MVC like the one from Wikipedia: “Model–View–Controller (MVC) is an architectural pattern that splits interactions between users and applications into three roles: the Model (business logic), the View (user interface), and the Controller (user input).[1][2] This separation of concerns facilitates the independent development, testing, and maintenance of each role.”

“This bring me to The MVC Paradox. Modern MVC web frameworks inadvertently encourage the coupling of domain logic and user interface. If you don’t need to support multiple types of clients, then decoupling the domain logic from the user interface is the only reason left to use the MVC design pattern.”

I dont understand this paragraph. The 3rd sentence does not provide any support for the claims of the 2nd sentence, leaving the 2nd sentence kind of without basis.

Supporting multiple clients is only one of many advantages. MVC’s main purpose is to separate concerns, hence the name. This enables you to grow your codebase while maintaining flexibility. It also makes your code easier to understand for other developers, because they can quickly recognize the pattern and guess where this and that process occurs. And the list goes on.

I find the full toolset of Asp.Net Mvc (asp.net environment, model binders, action filters, view engines, path resolvers, html helpers, routing) as the reason to get involved with this type of mvc framework. The rest are all well known issues for the community. But from my experience, things are changing fast so its better to ‘go standard’ and don’t get very theoretical if you know what i mean.