Template languages and separation

  1. Today, it's common to use template languages to produce markup code. My recent work on data and UI separation on the web, made me realize that this technique offer poor separation between design and implementation. Can we use a different approach?

    A little on template languages

    A typical template engine allows insertion of dynamic data and programmatic constructs into templates through the use of a template language. The engine then interprets and manipulates the template, inserting data from a model.

    Let's assume the following model, which consists of two objects. It is written in XML for simplicity. Typically the model would be in-memory objects.

    <menu>
      <items>
        <item>
          <url>http://arenybakk.com</url>
          <label>Home</label>
        </item>
        <item>
          <url>http://arenybakk.com/Development</url>
          <label>Development</label>
        </item>
        <item>
          <url>http://arenybakk.com/Games</url>
          <label>Games</label>
        </item>
      </items>
    </menu>
    <articles>
      <article>
        <title>Article A</title>
        <lead>This is the first article</lead>
        <text>Lorem ipsum...</text>
      </article>
      <article>
        <title>Article B</title>
        <lead>This is the second article</lead>
        <text>Lorem ipsum...</text>
      </article>
    </articles>

    Below is an example of a simple FreeMarker template. Tags with hashes are FreeMarker directives and the dollar expressions results in data interpolation. Syntax differ between languages, but the essence is the same.

    <#if menu>
      <ul class="menu">
        <#list menu.items as item>
          <li><a href="${item.url}" title="${item.label}">${item.label}</a></li>
        </#list>
      </ul>
    </#if>
    
    <#list articles as article>
      <div class="article">
    
        <#if article_index == 1>
          <h1>${article.title}</h1>
        <#else>
          <h2>${article.title}</h2>
        </#if>
    
        <p>${article.lead}</p>
    
        <div>${article.text}</div>
    
      </div>
    </#list>

    Right off the bat, this doesn't look all that bad, but this is a very simple example. A more realistic template would probably look much worse, and so would the model. Even so, we can spot some problems:

    1. You have to manipulate the initial design by inserting extra code. You lose design-time test and example data, and the ability to observe the intention of the designer. Updating the template with a new design is potentially very difficult. Changes in the template may also require changes in construction of the model.
    2. Debugging is hard. Line numbers will almost always be different in template and output, since many lines will only contain logic. Indenting and line breaks can improve template readability, but can at the same time cause messy output. Logic in the template makes it increasingly difficult to understand.
    3. You'll likely need to adapt another language, not just an engine. This either introduces another project role; the design implementer, or you must force either the designer or the developer to do something which is, strictly speaking, outside their sphere of expertise.
    4. Performance. Interpreted code will always have a performance impact, even if it doesn't have to be big. The model expected by the template might not be readily available either, but have to be constructed first, most likely after a series of database queries.

    A small wake-up call

    I first became aware of these issues when I came across a library called "Weld" (now deprecated in favor of "Plates") written in JavaScript, and I was surprised why we are using template engines at all. They're just bad.

    Weld automatically map model properties to HTML element attributes, such as the "class" attribute. This may not always work, particularly when the designer is not also the developer, so the library offers custom mapping. While this is a lot better than using a template engine, I believe there's a better way.

    Lets remove the code from our template so that it more closely resembles what a designer would produce. I believe such a design template should never be manipulated, and updates to a design should result in new templates rather than replacing the old. For the sake of simplicity, lets use a HTML template.

    <ul class="menu">
      <li><a href="" title="Menu item 1">Menu item 1</a></li>
      <li><a href="" title="Menu item 2">Menu item 2</a></li>
    </ul>
    
    <div class="article">
      <h1>Title</h1>
      <p>Here goes the lead.</p>
      <div>Lorem ipsum...</div>
    </div>
    
    <div class="article">
      <h2>Title</h2>
      <p>Here goes the lead.</p>
      <div>Lorem ipsum...</div>
    </div>

    Separating data from presentation

    I have previously written about the semantic web, and the limitations of HTML. Most content on the web today exists as HTML, be it articles, web pages or interactive applications. This is a lot more than HTML was intended for, and what we have ended up with is a markup language that has both data and representational properties. We should separate the two, and the best way to isolate data is to make it readily available on the vast web through querying, in the spirit of the semantic web. In any case, separating design from implementation also helps in this regard.

    Let's assume our menu and data exists in two RDF graphs, and by writing a couple of SPARQL queries, we obtain the data we're interested in.

    SELECT url, label
    FROM ..
    WHERE {
      ?item url   ?url
      ?item label ?label
    }
    SELECT title, lead, text
    FROM ..
    WHERE {
      ?item title ?title
      ?item lead  ?lead
      ?item text  ?text
    }

    A declarative approach

    In my post about the limitations of HTML, I proposed introducing XML/HTML attributes for mapping data in a template. One of the examples is shown below. Note that the post wasn't written with RDF graphs and SPARQL queries in mind.

    <document dataset="/data/news?i=2.newsitems" title="Latest news @ Mysite.com" description="The latest news from Mysite.com" keywords=".newsitem[0..].keywords">
    
      <mysite:banner>Mysite.com brings you the latest news</mysite:banner>
      
      <mysite:mainmenu data="/data/mainmenu.menuitems.menuitem">
        <mysite:mainmenuitem>
          <anchor href=".url" title=".name" content=".name" />
        </mysite:mainmenuitem>
      </mysite:mainmenu>
      
      <mysite:newslist data=".newsitem">
        <block>
          <header content=".name" />
          <paragraph content=".text" />
        </block>
      </mysite:newslist>
      
    </document>

    While this method offer less impact on data interpolation, is still forces changes in the template much like a template language. In fact, it would be a template language, just in a different, declarative language.

    The idea behind my project "Snorky" was based on a declarative approach, like Weld was. A simple conceptual example is given below.

    <link id="rdf-menu" rel="alternate" type="application/rdf+xml" href="http://www.site.fake/menu.rdf" />
    <script id="sparql-menu" type="application/sparql-query" src="script/menu.rq" />
    var binding = new snorky.Binding("#sparql-menu", ".menu")
      .map("url",   "li a[href]")
      .map("label", "li a[title]")
      .map("label", "li a");

    While I think my idea of mapping SPARQL query results to a template was a good idea, the declarative approach was obviously limited, and there was still a need to manipulate the template if used in a browser environment. I have therefore put that effort on hold.

    I came to realize that a declarative approach may often not be enough. There are common cases where you wish to control the produced markup in a greater degree that what can be handled automatically. For example, you may wish to generate a piece of code only in certain situations. It is difficult or impossible to attend to all possible cases, and trying to do so will lead to a very complex library.

    A programmatic approach

    An alternative is a programmatic approach, much like what most template languages offer, but it must be written outside the template. The problems are inherently difficult, much like programming is, and are heavily affected by practice. It's not realistic to expect all designers to follow the same practice. Sometimes the design is produced by a third party that isn't directly part of the project. Likewise, all developers have their different opinions on good and bad practice.

    The right solution

    So, what silver bullet do we apply for the job? I don't think there is one at this moment. You will have to make a strategic choice based on the requirements. I think, however, that design-implementation, and data-presentation, separation is something to strive for, and typical template languages don't fit the bill.

    Both the outlined approaches requires creation of the DOM on the server side, and they only partially solve the mentioned problems. I think an unobtrusive declarative approach is preferable (if that's even possible), but if you have to program something, it makes more sense to use a programmatic approach. By choosing a programmatic approach, you also have the benefit of using a language the developers are already familiar with.

    In my view, HTML should be replaced by pure XML-based UI templates, added with some powerful browser-side data linking mechanisms. Actual progress in web technologies, however, makes this a mere wish. For now, we'll have to try to make the best of it.