Thursday, February 05, 2009

The Fat Controller must die!

As most parents with little boys know the Fat Controller is a key figure in the Thomas the Tank Engine TV series (and books, toys, clothing, linen, bags, crockery, snacks, etc.). he is a cheery fellow, unfortunately prone to angrily shouting at train engines, but equally kindly and caring about his beloved vehicles (especially steam powered ones like Elizabeth the lorry). For the sake of my children I must point out that I have no problem with this jolly fellow.

fat controller

There is another domain where fat controllers exist, and that is the world of the MVC (Model-View-Controller) pattern. The pattern has experienced a renaissance recently in web applications, particularly because of Ruby on Rails, and now Microsoft's ASP.NET MVC offering.

Now these Ruby on Rails guys have been doing this for a little while longer than the ASP.NET guys, and one key paradigm became clear fairly early on:

"Try to keep your controller actions and views as slim as possible."

This was most clearly explained by Jamis Buck in his excellent Skinny Controller, Fat Model post back in 2006, which is still worth reading even if you don't use Ruby on Rails. More recently Ian Cooper has pointed out this is the same problem webforms had:

"This is the good old problem of domain-logic in code-behind that we had in ASP.NET webforms. Indeed Webforms are just another type of controller, a page controller, and switching to an application controller model does not remove the need for us to watch for domain logic creeping into the controller. There can be a temptation to believe that just because the controller is easier to test it is now safe to put domain logic in there. Do not fall into that trap."

In his book, Domain-Driven Design, Eric Evans identifies this as the Smart UI Anti-Pattern.

“Put all the business logic into the user interface. Chop the application into small functions and implement them as separate user interfaces, embedding the business rules into them. Use a relational database as a shared repository of the data. Use the most automated UI building and visual programming tools available.”

SmartUI
Image from David Hayden's blog

Eric is kind (and pragmatic) enough to point out when it is useful.

“A project needs to deliver simple functionality, dominated by data entry and display, with few business rules. Staff is not composed of advanced object modelers.”

Clearly ASP.NET's webforms model encouraged this sort of practice (it is just far too easy to do), but surely a controller is a safe place for this code? After all, a controller can use many views, so it is more clearly separated than code behind. The problem is that whilst application logic ("Which view do I show next?", "What domain object is handling this request?") makes perfect sense in a controller, there are too many examples of them being used as stores for business/domain logic - which is the province of the domain model.

Hang on, we probably have a (ubiquitous) language problem here. You see, the "Model" in MVC != the "domain model" in Domain-Driven Design (DDD). In fact we need to map the DDD concept of layered architecture to MVC in order to see what we truly have.

MvcMapToDdd

Instead of giving the Model layer a fully fleshed out domain and supporting infrastructure (repository and services), many ASP.NET developers seem to want to treat the Model as pure database infrastructure and DAL (like the one in the Smart UI graphic above). This leads to the problem of where to put the business logic, and the natural assumption is that it belongs in the controller ... which is like making the navigator the captain of the ship.

Ian and Jamis have much more (technical) stuff to say on this subject so I'd advise you to check their posts out if you're into .NET or Rails, respectively, but do take this message with you, the Fat Controller must die!

1 comment:

  1. I neglected to mention that the skinny models must gain weight! LOL

    ReplyDelete