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?

Gravatar Andy Edinborough Wednesday, June 23, 2010
Strongly-typed views make data type requirements, not assumptions. Without strong-typing, the views would be forced to make data assumptions. At some point a view is working with data. If the view shouldn't be concerned with the data, and only worry about displaying it, then it would be the model that handled formatting--which would break a rule of separation.
Igor Loginov Thursday, June 24, 2010
According to Parr, we shall stop programming in views for strong separation. Now we program there anyway - with strings and with types.
So, neither good nor evil, just a way of doing things. Actually, AJAX is close to the ideal approach.
Gravatar Jauco Thursday, June 24, 2010
In the 5 minute intro to ST it shows that you can print a property by saying $user.name$. If you write that in your template you assume that upon rendering the view there will be an object "user", and that object will contain a property "name". If you strongly type your view then you are simply allowing the system to verify that assumption for you. No _new_ assumptions are made.

Ideally, of course, the Type in the definition would be an interface or custom object that is rather specific to the assumptions you make in this view. To allow you lots of freedom in your controller to choose what objects to send to the view. i.e. you don't want to require some specific business object if all you are using is it's ToString method.

P.S. I didn't quite get where you were heading with the testing tangent.
Gravatar scott Thursday, June 24, 2010
@Jauco: For testing I'm saying it would be easier to catch errors in a view if views were easier to test. Apologies for the confusion.
Igor Loginov Friday, June 25, 2010
@Jauco: You touched the main point of this discussion with your example. ST treats $user.name$ as just a "marker" for search & replace. This marker contains a kind of meta info about object structure but (!) not about types. Such a code is still testable (again, without type validation, as soon as we agree not to make any data type assumptions). The only thing we lost here is intellisense in view. But we are trying to avoid programming in views. Something like this...

The real challenge here is a good pipeline for processing partials in controller. We need these partials reusable, so their classes must keep all possible context dependencies.
Comments are closed.