OdeToCode IC Logo

Parr's Rules for MVC Views

Tuesday, June 22, 2010

There are a number of ideas to chew on in this 6 year old paper by Terence Parr: "Enforcing Strict Model-View Separation in Template Engines". Parr is one of the creators of the StringTemplate template engine, which is ".. as simple, consistent, and powerful as possible without sacrificing strict model-view separation".

One of the highlights is the list of 5 rules implied by strict separation. Parr introduces them like so:

Before formalizing my intuition, I kept a few simple rules and tests in mind to evaluate entanglement. Could I reuse this template with a completely different model? Could a designer understand this template? 1f it looks like a program, it probably is. If the template can modify the model, it’s part of the program. If order of execution is important, it’s part of the program. If the template has computations or logic dependent on model data, it’s part of the program. If types are important, the template is a program.

The idea behind a strict separation is to avoid programming in the view and merely apply templating. With the web forms view engine in ASP.NET MVC we can not only break all 5 of Parr's rules, we can crumple them up like tissue paper and light them on fire. Of course, we can also behave ourselves and follow the rules of separation- or at least all of the rules except the one stating "the view cannot make data type assumptions".

Strongly-Typed Views Are Evil?

Most MVC developers I talk to prefer to use strongly-typed views. Strong typing gives us intellisense and compiler errors.  But - is there a cost? Does strongly typing the view lead to a form of bad coupling between the view and the model? Does it make the view harder to change? Does it make the designer's job more difficult?

I can hear you saying "no". Is this because the rendering phase of the processing pipeline is nearly impossible to test? Would it change your mind if testing a view template was easy?

ActionResult result = controller.ChangePassword();
var output = result.ExecuteResult();

What do you think?