Wednesday, March 21, 2012

Language Driven

If templates weren’t languages, we wouldn’t call them template languages, nor have so many of them: HAML, HTML::Mason, TemplateToolkit, PHP, Smarty, pagelib and Output, and so forth.

(This is essentially a repost of something that used to be on my old blog.)

In particular, LiveJournal makes a fantastic case study, since they had their old style system that basically allowed for substituting end-user-chosen color values into developer-written HTML (one HTML file per each of the four views that they offered: main journal, friends page, calendar, and... whatever I’ve forgotten).  When they designed a next-generation style system, S2, the templates were code and could produce all of the views from a single file.  And of course that file could define functions to share across the views and declare semantic color names instead of “weak accent color #2 foreground”.  (Along with other options like “place sidebar on left/right”, IIRC.)  S2 also has the interesting property of being non-Turing-complete by design: the only looping construct it offers is over finite lists.  Even so, they also have a time limit set so that the server doesn’t melt beyond a certain point when load gets high.

LJ’s S2 is just the end-point of evolution of the realization that templates are code: if you want to display a list of items, or a distinct block with a “Sorry, no results found” message in case the list is empty, these are fundamentally a process driven by the result set into the output language (HTML for S2).

If a template language is strictly declarative, then the template language is no longer self-contained: instead of being able to set data and then have the template interpreter run, the higher level code becomes responsible for inspecting the data for optional/looping parts, and composing the resulting template itself.  Responsibilities a template processor would normally take on become implemented in the nearest level of non-template code.

Consider other famous declarative languages: a notable shortcoming of CSS is its lack of support for adding units, like, “I want a box 30% wide, minus the 2em of padding I’m going to add.”  As the link implies, this may be coming soon as css3/html5 support expands across browsers, but also IE has had the capability to determine CSS values through JavaScript expressions for a decade, with the caveat that this has terrible performance—IE can’t see the conditions that would change the value because it is code, so it runs the code excessively often to make sure the value is still accurate.

CSS is doing its best to maintain declarative purity, which is why CSS generators like Less and Sass have come about: they give you a stateful, imperative layer above CSS with which to generate CSS.  Alternatively, they’re a template language (still non-declarative) that simply results in CSS instead of HTML.

Spreadsheets could be the poster child of declarative languages, but this was also seen as limiting enough to give Excel a macro system, and conditional formatting.  The latter was something I wanted at one point in, but I had to make do with an extra column, styled appropriately, filled with =IF(stuff, "+OK", "") formulas: this would fill the cell with a plainly visible value whenever stuff was true.

Another common “declarative” language is SQL, except that it is also intimately involved with process.  Performance can change drastically depending on whether a conditional can be resolved at JOIN, WHERE, or HAVING time.  In fact, that last one is pretty much useless in real code; specifying “do all this complicated work, and then narrow down the results of that” fails to be efficient even at small scales.  The query analyzer does have some freedom to rewrite SQL code into more efficient execution plans, but most RDBMSes offer tools like index and join order hints to give programmers and DBAs more control over the process.  In any case, every SQL optimization guide ever explains the effect of SQL in terms of the process the DB engine must go through to satisfy the terms, so that process is constantly leaking out from behind the language.

So template languages need to be non-declarative, or else the next layer up becomes an ad hoc template processor; and declarative languages are generally extended (or built atop of) until they aren’t strictly declarative anymore.  The only reason CSS hasn’t been papered over or replaced completely is that it always ships alongside JavaScript, which is Turing complete and can fix up CSS’ most common difficulties.

No comments: