Template Languages

Somehow I keep on building websites, re-building or otherwise…  Sometimes I think it just practice – just like playing a piano – most of the time it doesn’t have any true purpose, but it allows me to try different techniques and approaches.  When I think of big systems, NoSQL datastores (for example) it’s really hard to just play, it takes weeks to build the base system…   Then if you want to rebuild the IO subsystem it’s pretty involved, though I’ve  been know to do this…

Now back to templates!

I like the Zend Framework in PHP, it really helps abstract you from where the mess comes in (if you live in PHP).  However, it doesn’t relieve you of the worst risk in the language which is your templates are still in PHP.  One of the biggest points that drove me crazy at Yahoo! was their input filtering policy, where they mandated that some characters had to be removed from input to prevent people from accidentally letting them flow out to the HTML.   The challenge with this approach is that now all of a sudden you can’t have “&” or “<” in an input string…  You’re masking a class of bugs with a policy.

The following three lines are three different template systems for the same function:

<input id="name" name="nm" type="text" value="<?= htmlspecialchars($filter['nm']) ?/>" autocomplete="off" />
<input id="name" name="nm" type="text" value="{{ query.get('nm','') }}" autocomplete="off" />
<input id="name" name="nm" type="text" value="{{ query.nm }}" autocomplete="off" />

These are all real lines, two of which are in production – one is demonstration.

Case #1 – You need to explicityly escape your code, thus meaning you mandate code reviews since bad things happen when people get tired of typing htmlspecialchars().  Which they do, because 30% of your code is “internal” safe variables – and you don’t need to escape…  But, of course you do – since the source data might have come in via an AJAX API that you implemented 6 months later…

Case #2 – Good, escaping by default.  But, turns out that now you’re providing sensible defaults to everything.  But, typically the default is the empty string, failure to provide yields “None” or “null”.  More typing by rote, good but not great.

Case #3 – I like this approach.  Two big value adds – Defaults are sensible, you don’t have to worry about the kind of data you’re dealing with.  Is it an object, is it a dictionary, is it an array ( result.location.3.title ) – is it a function…  By the time you get to the template level, you really just want as sensible default and an ERROR kicked into a logfile.  Don’t throw an error if result.location only has two items.

Case #4 – Strange languages like HAML, at the end of the day HTML is the Lingua Franca between Engineering and Design… Why introduce translation.

At the end of the day, really think about how you’re abstracting things.  The goal of a good system  is the ability to get the maximum amount of work done with the minimum amount of syntax.  Since the more we type, the more mistakes happen, the more review is needed…

FYI – We’re looking at PHP, Tornado and Django (it could have been Handlebars).  Tornado makes no claims about being a full featured Template system, but until it get’s “big” it’s quick to whip things up in.  I really should wire up the 15 line Tornado<->Django connector that pulls Django templates into Tornado, but that’s another day.