The Case Against Logic-less Templates

At a conference I recently attended, two separate topics related to templates sparked a debate off-stage about Logic vs No-logic View Templates. Folks were very passionate about the side they represented. Those discussions were the high point of the conference, since I learned much more from them than from the sessions that were presented.

While everyone involved in the debates had different opinions about the ideal templating solution, we all agreed that templates should…

  • not include business logic
  • not include a lot of logic
  • be easy to read
  • be easy to maintain

In this post I'll describe what I prefer--rules, best practices, performance considerations, etc. aside. My preferences come from my experience with templates for medium to complex applications.

Full-of-logic, logic-less, and less-logic solutions

Before I go into the details, I would like to make one thing very clear. Although I'm trying to make a case against logic-less templates, that does not mean that I am advocating the other extreme--i.e., a templating language that allows a lot of logic. I find such templating languages, especially those that allow the host programming languages to be used inside the template, to be hard to read, hard to maintain, and simply a bad choice. A JSP template with Java code in it and an Underscore template with JavaScript in it both fall into the category of being a full-of-logic template. JSP and Underscore are not necessarily at fault here; rather, developers often abuse the additional freedom such solutions offer.

What I am advocating is “less-logic” templates in place of “logic-less” templates (thanks, Veena Basavaraj (@vybs), for the term “less-logic templates”!).

Good and great templating languages

A good templating language should offer, at a minimum, the following features:

  1. Clean and easy-to-read syntax (including the freedom to use whitespace that will not show up in output)
  2. Structural logic like conditionals, iterations/loops, recursions, etc.
  3. Text/Token replacement
  4. Includes

A great templating language should also offer the following features:

  1. Ability to be rendered on the server and the client
  2. Easy learning curve with as few new concepts as possible
  3. Simple template inheritance
  4. Easy debugging
  5. Great error reporting (line numbers, friendly messages, etc.)
  6. Extensibility and customizability
  7. Localization support
  8. Resource URL management for images, scripts, and CSS

The case against logic-less templates

I consider a logic-less template to be too rigid and hard to work with due to the restrictions it imposes. More specifically, here are the reasons I am not a big fan of logic-less templates:

  • Writing a logic-less template requires a bloated view model with comprehensive getters for the raw data. As a result, a messy and difficult-to-maintain view model usually accompanies logic-less templates.
  • Every new variation to the view requires updating both the view model and the template. This holds true even for simple variations.
  • Getting the data ready for the template requires too much data "massaging."
  • Offsetting the rules of a logic-less template requires a lot of helper methods.

Regarding the argument of better performance with logic-less templates: While they might have a simpler implementation, they require additional preprocessing/massaging of the data. You therefore have to pay a price before the data gets to the template renderer. Granted, a templating language that allows more logic might have a more complex implementation; however, if the compiler is implemented correctly, then it can still produce very efficient compiled code. For these reasons, I would argue that a solution involving templates with more logic will often outperform a similar solution based on logic-less templates.

Conclusion

No doubt, there are advantages like simplicity and readability associated with logic-less templates such as Mustache. And arguably, there could be some performance gains. However, in practice I do not think these tradeoffs are enough to justify logic-less templates.

Logic in a template isn’t really a bad thing, as long as it doesn’t compromise the template's readability and maintainability.

And as an aside, I'm definitely in favor of more debates than sessions in future conferences, since we actually learn more by hearing multiple viewpoints.

I welcome your thoughts!

Credits: Many thanks to my colleague Patrick Steele-Idem (@psteeleidem) for helping me write this post. He is working on some cool solutions like a new templating language; be sure to check them out when they are open-sourced.

15 thoughts on “The Case Against Logic-less Templates

  1. rupa

    If your template variables are html, or you're nesting little sub-templates of html snippets, the templating language has failed at the very thing it exists for. On the other hand, PHP is worse.

    Reply
  2. Jonathan Allen

    Why do you have a "view model"? You service layer should be returning data models, or possibly even raw data transfer objects, that you can use directly without having to wrap them in something else.

    You comment about view models reminds me of ORM developers. Not “developers who use ORMs” but rather developers who only think in terms of ORMs. The kind of people who call SELECT * on the database to populate heavy weight entities, then map those entities to models, and then map the models into view-models. Each step of the way a bit more information is lost, information that should have never been read from the database.

    Now I don’t mean to accuse you of that, I’m just saying that’s the connotation the term is starting to develop.

    Reply
    1. Patrick Steele-Idem

      It is a not always feasible to design a one-size-fits-all service-layer and sometimes the data needs to be massaged before it is passed to the template for rendering to HTML. Things like ql.io (a data orchestrator) can help, but there is is often certain derived information that the service layer should not be providing in returned data. For example, if the service layer returns data that includes the ending date for an auction then it doesn't make sense for the the service layer to also include the "time remaining" since that is derived data. If the time remaining time needs to be displayed to the user then that information can be added to the view model passed to a template via a front-end controller. In addition, the service layer should not typically be formatting data (dates, currencies, numbers, etc.) because then that restricts how the client can present the data since the data has already been pre-formatted. Therefore, the front-end controller might need to populate the view model with formatted data. Another option, for richer templating languages, is to provide directives in the template that perform the formatting.

      Reply
    1. Patrick Steele-Idem

      I think that what Mustache calls “logic-less” is not really logic-less, but rather a *very* limited number of tags and no support for complex expressions (only simple property references). The result of these restrictions is that more view code must be written to populate a view model.

      I think it is helpful to show comparisons of “logic-less” versus “more logic” so I created the following Gist:
      https://gist.github.com/3125854

      I think the code samples with more logic are as easy or easier to read and maintain as the “logic-less” sample. In addition, for the “logic-less” example, the view is required to populate the view model with the following properties:
      - cartEmpty
      - cartNotEmpty
      - cartItems

      In comparison, in the case of the the “more logic” examples, the view is only required to populate the view model with a single “cart” object that has “isEmpty” and “getItems” functions as properties. Allowing complex expressions results in less massaging of data by the view.

      Having a richer templating language is not necessarily a bad thing. Even with a richer templating language, a developer can optionally choose to code with the restrictions that “logic-less” languages automatically impose, but it is opt-in and not a forced decision.

      Reply
  3. Brad

    Mustache (and Handlebars which is more popular) are considered logic-less in the respect that you aren't writing Application Business Logic into the view itself.

    Compare that to an ERB or JSP template where you can write anything you want, in the same language as the application code... and so people invariably do.

    They don't however mean you don't use logical constructs for presentation. I will frequently write a Handlerbars helper to format some html in a particular way to fit the UI design (eg. render a span containing a value to 2 decimal places, with classes for right aligned and making the text red if negative).

    Reply
    1. Jaime

      "Compare that to an ERB or JSP template where you can write anything you want, in the same language as the application code… and so people invariably do."

      So you are admitting the problem is not the language, but bad development practices by people.

      Reply
  4. Taylor

    Hi..
    Writing a logic-less template require a overstuffed view model with complete getters for the raw data. As a result, a messy and difficult-to-maintain view model usually accompany logic-less templates.

    groupon software

    Reply
  5. Pingback: Ractive.js Expressions and the New Wave of Reactive Programming | Flippin' Awesome

  6. Mateusz Szczap

    At mobile.de (owned by eBay Inc.) we have a lot of legacy FreeMarker code which contains lots of more business logic than it does.

    We have decided a logicless (or maybe not so logicless) templates a go, we selected Google Closure and developed now two applications in it.

    I think it is unfair to put all logicless template engines into one bucket because Google Closure Soy Templates give us a minimal set of operations we can perform. The former example on the gist showed that in case of one logicless templates one doesn't even have if statement.

    Google Closure Soy provide if..
    https://developers.google.com/closure/templates/docs/commands#if

    Still our new soy files are very clean, we have a view model but we do not think it is wrong, in fact it is a famous "presentation model pattern" from martin Fowler, which to my knowledge has not yet been called an anti-pattern :)

    It looks like other companies such as LinkedIn are also moving towards this direction, they use another logic-less templates, called dustjs, which are also not that logicless after all.

    So far I like logicless templates such as Google Closure Soy and I recommend them, we have to plans to go back to FreeMarker hell.

    Mind you there is a very important case here about Unit Testing, which should rather be done in the backend code rather than in Frontend (which is also possible I know).

    I also want to mention that polimorphism and injecting a different implementation of a view should be done in the backend and is sometimes required and necessary otherwise it leads to messy code.

    Naturally you can keep even FreeMarkers templates very simple, it just turns out on the large code bases people won't and you cannot easily police that.

    Reply
  7. nick

    In the interest of the community in the ease of templates and logic I would like to state my case. We have server side business logic to group data into a complex object. Once this object is done, we then render the object into a view that is rendered using Razor. The next step is we then parse this client side data using our templates to present html data differently based on logic, a href, span, div for example. I am finding it impossible to maintain two pieces concurrently when a higher level logic changes how the whole product is presented, meaning a column being added or name changed or another entity entirely. Maintaining workflow inside of a template is the end result but is not the real answer because the right questions were not asked yet.

    Reply
  8. Pingback: Клиентские template ← Incoding framework

  9. Pingback: AngularJs logicless templates : non à la logique au sein des templates

  10. Pingback: TIWEN

  11. Mick

    I think folks are missing a few critical points.

    One, there is an architectural principle that is being supported by the separation of view objects from data or business objects...which enforces discipline required to make the view truly agnostic and replaceable.

    Any compiled language is slower and less maintainable by definition. I know about servlet caching etc...but resting the view in Java is simply not light weight.

    Lastly, if you check into the Spring development path you will notice that Thymeleaf is heavily recommended and supported...and that other choices like gradle as a build tool, programmatic configuration instead of xml etc...will soon be so fundamental to the use of Spring you'll be swimming upstream to stick to outdated and flawed practices from the 2000s....like JSPs. You should forget JSPs.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>