In work, we’ve been using MonoRail for a while. It’s a C#/.NET web application framework, and it’s very much nicer than ASP.NET, which is what I was using before.
Now I’ve had a bit of experience with it, though, there are things I would definitely change: I want the framework to allow me to compose page elements more easily, and to have stronger type-checking.
The easy one first. I’m going to talk about…
I like static type checking. I like that C# recently added generic types, because it makes the static typing stronger. More mistakes are caught at compile-time. This is good. It also means that the IDE is able to help you by autocompleting pretty much anything, and allowing you to refactor identifier names really easily.
Type checking is stymied in a couple of places in MonoRail. One is in the fact that views, actions and URLs are referred to by name, passed around as strings. This is annoying, though it’s a fairly manageable problem. (Somebody has hacked together a solution to this*.)
What I am more concerned about though is the rampant dynamic typing within views.
‘Views’ in a MVC framework like MonoRail are templates which take data provided by the controller (the code which handles the action—page request, or form submission), and bungs it into HTML for output. For example, given a collection of ‘customer’ objects, a view might output a table with one line for each customer and two columns, customer name and customer code.
…and all of them are dynamically typed. A typical line from a view, written in a templating language might look like:
At runtime, these names are looked up, and retrieved from (say) the ‘customer’ object which has been passed in.
But what if I have a spelling mistake? It’s not ‘AccNumbr’, it’s ‘AccNumber’. Yeah, yeah, testing should catch it, but I don’t want testing to catch it; I want the compiler to catch it. I also want to be able to take advantage of automatic refactoring to change it to, for example, ‘AccountNumber’ without hunting through every view which refers to it. And I’d like the development environment to be able to save me typing, so I just need to type ‘cust.Acc…’.
Ideally views would:
- Be compiled into bytecode† at compile-time, (and the compiler would check type-errors). This implies that each view would…
- Declare parameters and declare the types of these parameters. This implies views would…
- Essentially be objects which have methods which take parameters and return a result.
Now at this point I expect someone to chime in and say that views have got to be dynamically typed, since they’re fodder for HTML designers, and they’re therefore supposed to be written in a nice, soft, non-static-compilation kind of a language; or that views should be simple, and static type checking isn’t ‘simple’. I don’t buy that. Essentially we’re not changing anything here, except catching a class of bugs earlier. Were not actually making the display logic any more verbose.
Views shouldn’t look too much like programs. They’re performing intentionally simple computations. They’re processing text. The controller should contain the main program logic; the view should only be concerned with display logic.
All we need should need to specify in the way of type information is either the interface which the view implements (which implies the types of the arguments), or else a list of named and typed parameters. Something perhaps a little like this:
// Such-and-such a project
// Main page, shows list of customers
title=Main page for $login.Name
That would be a view with three parameters and two ‘methods’; one method which returns the page title, and one which returns the HTML to be jammed into the body of the page.
The syntax needs a little work. One would need to work out how to accommodate (or work around) importing types from different namespaces. (I’d rather not begin each view with a list of namespace/package imports.) Ideally the system should also accommodate parameters passed implicitly, like MonoRail-style ‘helpers’, or other, common parameters—like the location of the site root—which potentially every view needs.
However I believe that the concept is sound. It would make my life easier.
One final note: in the example above, most templating languages would take the value of
login.Name (presumed to be a string), and jam it into the output HTML. This causes a huge class of security issues called XSS vulnerabilities. Any values should be correctly converted or encoded when output. I may have more to say about that.
* It seems that this ‘hack’ is now a public project, the Castle.Contrib.CodeGenerator project. I might start using it…
† I’m working in C# at the moment, hence assuming that you’d compile everything to bytecodes (for Java or .NET).