Template engines help separate presentation from domain logic. Presentation logic itself can be complex enough, however, to invite consideration of what should be placed in a template and what should be defined in separate classes. Template engines take different views on that point.
According to culinary historians, the first cookies were baked in Persia sometime around the 7th century A.D., serving as a kind of "test cake," allowing the baker to gauge the consistency of the dough. It is easy to imagine that the need to produce uniform-looking cookies soon brought about the first cookie cutters, a device that allowed the baker to neatly separate presentation from content.
A similar need to produce uniform-looking pages and documents, and to separate presentation from content, brought about the modern version of the cookie cutter, the template engine. In the 1980s and 90s, most users interacted with template engines by applying ready-made templates to word processing or presentation documents. Because templates were very simple instructions for layout and visual appearance, designers could focus on creating templates, and users with minimal technical skills could focus on applying those templates to their documents.
Such simplicity was soon eclipsed, however, by the need to produce increasingly complex visual presentations for Web pages. While the desire to separate data from presentation remained, complex visual layout invited more capable template logic, one where programming language code is sometimes used to affect presentation.
I recently looked at code from a project I worked on some months ago using Rails. I was pleasantly surprised to find that the controller code in this application is on average about a dozen or so lines of Ruby code per method, living up to Ruby's alleged simplicity. But the templates are a different story. In some cases, data had to be presented in such complex ways that the size of some of the templates far outstripped the amount of code used in the controllers. My aesthetic sense was disturbed by the complex templates, but I didn't think that alternative implementation techniques would have produced less complex code.
Although some of that complex presentation logic could have been factored out into presentation-related "helper" classes, doing that would not have reduced the complexity of the code, only moved the locus of complexity into other classes. In addition, splitting presentation logic between two classes (an RHTML template and a Ruby helper class) would have introduced a form of duplication, and diminished the overall clarity of the code base. Although the templates were complicated, the intention of the presentation logic remained clear to anyone looking at the template code.
In many cases, however, template engines that allow easy mixing of code with HTML or other presentation markup—be it JSP or RHTML or PHP— can clearly lead to hard-to-understand code. The evolution of Artima's own code base has illustrated this. Artima initially incorporated some proprietary JSP-based code. As the system grew, we extended that code with more functionality. However, such extensions were not easy, because the original JSP codebase consisted of a liberal mix of presentation and business logic.
The next step in the Artima code base was to introduce our own templates, initially based on the Velocity template library. This produced much cleaner presentation code, and we were at first happy with the result. However, as we looked back at some of the templates, it was hard to rejoice for long, since many of them were, in fact, mini programs: Velocity provides a very capable template language, and we found ourselves making good use of its features (such as making method calls into Java objects from the templates or defining complex branching logic).
[We] came up with something very simple—a document with holes in it. As needs dictated, I would gradually increase the power [of those documents] while sticking to my principle of absolutely enforcing strict model-view separation...
Encouraging something is infinitely inferior to enforcing [that thing]. If someone is in a hurry, all of a sudden someone can [do] something in the wrong way. If there is any way to enforce something, then you should do it...
At that time, we feared that [enforcing that] separation would emasculate the power of the template engine. I thought about that for a long time, and realized that it was sufficient to show a direct mapping from the hierarchy of nested templates that would, say, generate an HTML page, show a relationship between that and a parse tree or derivation tree from language theory...
There is a lot evidence that you don't need [to do] that much stuff in the view. In some cases it's clear, but there are many other cases where I'd argue that that computation needs to go into the model... You can't just multiply things in the view, you can't do array indexing, because that assumes that's something is an integer. What if an ID turns into a String next time? You want to try to isolate as much as you can.
Also, you can't have literals in your code... and you can't have any logic in your templates, like HTML in your code that is then passed in as String to the template...
Parr contrasted StringTemplate's philosophy with what he called the "pull model" of other template engines:
My rule is, you must compute everything a priori, and then push the values in [the template], and the template merely operates on those values. In the pull model, by contrast, you're actually pulling something from the model, and that's much more of a programming model than a view.
It turns out that, perhaps as a reaction to the generally messy state of JSP pages, such a clear separation philosophy is catching on. Among the more interesting full-stack Java application frameworks is RIFE. In a recent conversation, RIFE's creator, Geert Bevin told me that:
The template engine in RIFE is very different from what template engines have become over the years... In my opinion, template engines started out to isolate content out of your code and into separate files so that you don't have to put print statements inside your code. That's what I always thought of as templating. People have, over time, turned this into a language instead of just an aggregation of bits and pieces of content. So they started creating if statements, even while loops, for loops, method calls, and then created new languages, such as PHP, that actually started out as a templating system.
We go back to the roots, as I like to think about it. In RIFE, a template is totally dumb. It contains only content that you mark up with blocks and then you put place holders where content can be filled in. Blocks are automatically stripped away, so they don't show up for display, and show only when set inside place holders. To do layout and format your content, you drive that with Java by manipulating the content in a template instance. That's very similar to what you do when you work with PowerPoint, for example. In PowerPoint, you can use a template to create your own presentation. The template will not have logic to do that by itself. That's something you have to do through the application.
That's also how we see templating: You have your view layer that uses a template instance as some of kind layout and content building mechanism.
The clear separation of content from presentation sounds appealing at first. But, thinking back to my Rails templates of a few months ago, I was asking myself how I would have created the complex presentation logic that the project's users required, if I used a template engine that completely prohibited the use of programming language code. Is it really true that enforcing something is always better than simply encouraging a principle?
A natural antagonist to cut-and-dry rules, I'd rather observe two higher-level principles in judging how cleanly a template enforces model-view separation. The first principle is to look out for a special case of code duplication: splitting one logical piece of functionality between two or more classes or methods. Helper classes or methods are a useful way to factor out common pieces of functionality, but functionality not designed for reuse I prefer to define in a single place. Splitting complex layout into a helper class and a dumb template makes it more difficult to understand the code, because now you have to look at two places to grasp what happens. Thus, I think it is fine to place complex layout code in the template, even if that complex layout involves some algorithmic manipulation of data (such as highlighting alternate table rows, or to selectively show content based on the user's role).
The second principle is to try to minimize coupling of code, or what the Pragmatic Programmers call orthogonality. Having a companion class just because the template engine prevents even the smallest inclusion of algorithmic display code, foists coupling between the template and the companion class on the system: The template and the companion class cannot exist without each other, and changes in one almost always impacts the other.
While I am not hostile to a small amount of presentation-only code in templates, code that affects the state of domain objects crosses the line, in my view, into the territory of messy mixing of presentation and business logic. What I would like to see in a template engine is some kind of logic that strongly discourages—even prevents—presentation code to alter the state of domain objects.
What do you look for in a template engine? And where do you draw the line between clean separation of presentation from business logic code, on the one hand, and unacceptable mixing of the two, on the other?
you make some good point, but you skip over some the important advantages of 'dumb' template engines. One of these is skinning of reusable functionality. When templates don't contain any logic and simply semantic identifiers, it's very easy to replace one layout with another since you don't have to work with both the logic and the content in the same document.
This can be used for more than you think. Take for example a site I wrote a while ago, http://blablalist.com, an open-source RIA to-do list tracker in OpenLaszlo and RIFE. The functionality that prints out the entries in a to-do list is present in two locations: a HTML view that users can print out, or an XML view that is the restful response for the RIA UI. The same logic is used for both and different templates are used when needed:
Something you also see here is that templates can include others, which allows you to separate out reusable pieces of content very easily (I tag). You can do the same thing to send out plain text (or html) emails and have templates for that, ...
Just for those that don't know, the other tags are V (value/content placeholder), B (reusable block), BV (reusable block that will by default fill in a value with the same name), BA (reusable block that will by default append to a value with the same name). The BV and BA tags are actually key elements to making a hierarchy of template includes comfortable to work with.
I do agree with you that sometimes it can get a little bit cumbersome to retrieve the template that corresponds to layout logic that is executing (though a debugger makes that quite easy when you are running into trouble). This is however what we try to achieve: to de-couple layout logic from the actual layout itself and to work with a structure that is represented by tag names (quite similar as a DOM structure). If you don't change the tag names, you can change your templates as much as you want without modifying the code that manipulates it. When you're talking about extracting into helper classes, you instead call something that will inject content into your template instead of structurally manipulating it. RIFE supports something like this, since you can include web components (our elements) inside templates and have them render there or just create renderer classes that will produce string content. Finally, if you do want layout logic and template logic to be traveling together, nothing prevents you to put them into the same directories and have the Java class live next to the template with the same name.
Another point that I want to make is about testing web functionality. RIFE supports out-of-container testing and for each request that executed you can step through the entire hierarchy of web components (elements) that executed, and retrieve the templates they printed. You can then inspect those templates and assert on the content of the value placeholders without having to parse anything. Since you've already structured your templates beforehand into reusable blocks and values ... asserting on constructed layout snippets becomes very easy. This is of course in addition to other testing methods where you assert on the actual property values of pojos that you use to generate your layout with, etc ...
There are many advantages to our templating approach than meets they eyes :-)
Sorry for the multiple posts, but I'm still gathering the bits and pieces of my thoughts at this time in the morning ;-)
Anyway, something else that I want to underline is that RIFE's template engine is bi-directional. With that I mean that you not only inject values, execute it and get a result, you can also obtain content snippets at any step of the creation of your layout. This is a very powerful since you can use snippets (with their semantic structure) of one template instance and insert/append it into others, or use their text representation with anything in Java that accepts strings. Also, if there are some parameters to your layouts, you can set them as blocks inside a template that for instance includes a generic configurable template, and the parameters can be obtained from inside Java to configure your layout. There are many possibilities ...
> But the templates > are a different story. In some cases, data had to be > presented in such complex ways that the size of some of > the templates far outstripped the amount of code used in > the controllers. My aesthetic sense was disturbed by the > complex templates, but I didn't think that alternative > implementation techniques would have produced less complex > code.
I've seen quite a lot of examples like this, just with tons of Java code embedded in JSPs. My conclusion is that presentation logic requires a full blown programming language to express that logic, and not a crippled templating language, eg. JSP, even with the (now standarized?) EL.
Finding a pleasant solution is definitely a very interesting task. After a quick glance, both StringTemplate and RIFE work with placeholders and in one way or the other define their own templating language (RIFE with special HTML comments, StringTemplate with special $$$ syntax.
While details differ a lot, the basic approach is the same as with all those other template languages, be it JSP, RHTML, PHP and whatnot. And all have that basic flaw of mixing structure with logic.
A different approach starts with a structured document, eg. XHTML, reads that document and modifies it. Consider the presentation of a HTML calendar. Both the structure (eg. a table with a lot of nested elements) and the logic (looping over dates, events etc.) are fairly complex. You'd start by defining the structure via XHTML, filling the document with some demo data so that your designer has something to work with while creating graphics and tuning stylesheets. Then you take that document and process it, replacing demo data with real data, duplicating elements to create lists of elements, and replacing their contents.
I'm not sure yet if it really works out, but I think it is something very interesting for someone who thinks a lot about templating. I hope to have something ready to show soon.
I don't agree that semantic placeholders and block to create a structure is the same as a template language. In RIFE's case there are only five tags: Include, Value, Block, BlockValue and BlockAppend. There is nothing that says what will be done with that structure, just how it's cut up and where the holes are. There's no logic in that, just ... euhm ... structure ;-)
I'm curious to see what you come up with using jQuery and Rhino, it sounds like an interesting approach.
As a principal author, along with Ian Robertson, of Jamon (http://www.jamon.org/), it's fair to say Jamon is a pretty good match for my requirements.
Key things I look for:
*) Type safety. I want the same support from the compiler in the templates that I get for "non-presentation" logic. In particular, I want to be able to refactor in the controller and domain layers and at the minimum have the compiler tell me what I have to fix up in the presentation layer. Ideally, the refactoring would go all the way through.
*) Support for more than just HTML/XML. While SGML-derivatives are a primary target, they're not the only target. Plain text, SMTP-emails, Java code, etc should all be supported. And supported without cramming them into a CDATA section requiring post-processing to get at.
*) Proper escaping support. It needs to be hard for me to make mistakes with respect to escaping. I want the template engine to "just do the right thing".
*) Minimize the new languages to learn. While template directives need to be learned, I don't want to learn a new language to access my Java objects. I already know Java. Let me use that.
A couple of the use cases we identified early on in the design of Jamon included:
1) Rendering of a hierarchical structure, e.g. a tree
2) Permitting the rendering of the "value" of an HTML select option to be specified separately from the "display value". In particular, the values should be specified and "owned" by the controller/domain layer, and the presentation layer "owns" and "specifies" the display value.
The first of these suggested that we needed a Turing-complete engine, in some way. And once you have recursion, you have "while", and vice-versa. So the idea of artificially restricting the kinds of logic in the template was rejected.
The second suggested "higher-order" templates. We wanted to define a universal "select" template. The implementation would iterate over the values, "calling out" to generate the display value. Even though Java doesn't support first-class functions, we added first-class templates to facilitate this.
> And where do you draw the line between clean separation > of presentation from business logic code, on the one > hand, and unacceptable mixing of the two, on the other?
I feel there's always going to be complex rendering requirements that come up, and I don't want to have to move those into some other layer. Treat the presentation code layer like any other. Presumably you audit and review other layers for violations (domain code in controller, etc), so do the same for your presentation layer. If your presentation technology facilitates functional decomposition, this can be no more painful than others. If your presentation technology is implemented in terms of translation to Java classes, you can utilize tools for layering/dependency violation detection at the presentation layer too.
> I'm still a fan of jsp. I find it easier to keep track > when the HTML and display logic are placed together in one > file. > > As long as there's a clear separation between the display > logic and the rest of the system, and there's a good > library for all of the formatting, etc of the page, it > seems ok to me. > > What's so bad about this code.. >
> There are lots of changes and additions I'd love to see > with JSP, but the bottom line is: it never gets in my way > as long as I don't abuse it.
There's absolutely nothing wrong with your code. I think the point is, the JSP API allows developers access to *all* layers of the domain (including data access) which is a *very bad thing* according to just about everyone IMHO.
So I like it a lot. I do however wonder if StringTemplate is also ideal for people who typically do the presentation tier. I am not convinced of that. In fact, I'm pretty much convinced that they would hate it.
I guess what I'm trying to say is that there is no golden hammer. I'm sure that this doesn't come as a big surprise, but the template engine arena used to be quite a fierce one. (See http://freemarker.org/fmVsVel.html; it seems that Velocity's page that fueled the discussion is gone by now. They did have a page in which they were bashing other template engines a couple of years ago.)
> As a principal author, along with Ian Robertson, of Jamon > (http://www.jamon.org/), it's fair to say Jamon > is a pretty good match for my requirements.
could you detail a bit about the differences between Jamon and JSP? After a first glance it looks like the template syntax is similar, and both get compiled into Java classes. I couldn't find a direct comparison on Jamon's website. So far my guess is that your compiler does a more then the JSP compiler...
> > There are lots of changes and additions I'd love to see > > with JSP, but the bottom line is: it never gets in my > way > > as long as I don't abuse it. >
> There's absolutely nothing wrong with your code. I think > the point is, the JSP API allows developers access to > *all* layers of the domain (including data access) which > is a *very bad thing* according to just about everyone > IMHO.
I don't consider access restricitions the problematic area about template langues. The main reason why I'm looking for alternatives to JSP is because JSPs don't scale. They grow bigger and bigger and become a maintenance hell. About every project I looked at that used JSPs (together with Servlets or Portlets) had a number of JSPs with more then 1000 lines of code and a lot of embedded Java. Noone on those projects had used tag libraries: The budget and timeline was fixed and writing tag libraries was way to complicated, and you had to resort back to writer.write(...) calls. JSP 2.0 may have solved a lot of the problems existing in previous version, but doesn't run on the servers we have to work with (mostly IBM Websphere Portal). Even JSF with it's component model hasn't solved the fallback to write(...) calls in your component classes yet.
One of the issues is that there is such a large gray area between 'business logic' and 'presentation logic'.
Let's say you have some promotion block on a page, in which some of your products are shown; some of them need to be shown with the price tags bold (they're discounted right now) and some of them need to be shown with more details (marketing decided that it looks better if the first of the five products shown has a picture and some extra lines of text).
How to split that neatly into "business logic" and "presentation logic"?
If the last bit of knowledge should be in presentation only, how does the presentation layer get the extra information? Either by pull, or by passing through the extra information all of the time because presentation might need it.
Should a presentation layer know that products are sometimes discounted? What other price characterics should it know? Should the business layer know about prices being shown in bold?
I've come to believe that the separation is a fiction, it's simply not there. The only things that are purely presentation are the large scale layout of the entire page, and all the things you can put in CSS. Code can generate blocks of HTML, or structures trivially transformed into HTML, as long as they use semantic tags and leave all the styling to CSS.
I think that is a very good point and probably one of the main reasons to keep templates that do allow scriptlets or other code clean and maintainable. I personally think that it should all just be done in Java where you can properly structure your classes as needed and just templates as a text construction mechanisms so that you not litter your classes with the actual string snippets.
People that advocate that they want the power in a template engine to run scripts since they otherwise feel too constrained, actually constrain themselves more since unless you fully adopt the features of the platform and language that you're writing your usual code in, it will always be a subset. So why not get it over with and do every logic outside the templates, instead of trying to make a template language more and more powerful (but not too much?). I think PHP here is a perfect example. It started at a template engine, grew into a full language and then people started building other template engines that run inside PHP, pretty ironic imho.
> One of the issues is that there is such a large gray area > between 'business logic' and 'presentation logic'. > > Let's say you have some promotion block on a page, in > which some of your products are shown; some of them need > to be shown with the price tags bold (they're discounted > right now) and some of them need to be shown with more > details (marketing decided that it looks better if the > first of the five products shown has a picture and some > extra lines of text). > > How to split that neatly into "business logic" and > "presentation logic"? >
In the above examples, I think that the business logic should be abstracting out 'sales/marketing' strategy for you (e.g. whether an item is currently on promotion) and the presentation logic should be deciding that promoted items are displayed in bold. For example: