Before I get into any meaty details, a quick question. You have a dynamic, database-driven web application and you’re ready to sit down and bang out its HTML output. One part of one page will be an ordered list containing comments left by visitors. You have the following choices for doing this:
Option A:
<ol class="comments"> {% get_comment_list %} {% for comment in comment_list %} <li>{{ comment }}</li> {% endfor %} </ol>
Option B:
item = page.new_content_element('ol') item.class = 'comments' for comment in db.get_post(post_id)['comments']: c = item.new_subelement('li') c.contents = comment
Which one do you think is preferable?
If you went with option B, go talk to Elver Loho who, in his rant on templating languages, seems to come to the conclusion that this is more suited to “rapid web development and Web 2.0.” If you went with Option A, congratulations: you’re sane.
Elver’s main beef with template languages seems to be that there’s no way to avoid having some sort of logic in them; since logic of some sort is inevitably necessary to generate the correct output, he wonders whether it might be better to just do away with template languages altogether and have pure logic. Styling will be accomplished by hanging CSS onto the markup generated by the logic.
And he seems to think that this transition is somewhat inevitable:
In any case, yes, it certainly works to have some logic in the template and it’s certainly a practical approach, but it stops working quite fast. Unless you’re a superman of some sort, you’re not good enough to design and code at the same time. You get the design from the designer and then you add code to it… Now suppose the design has to be tweaked a bit, but, oh no, it fucks up when loaded back into the designer’s favourite app! And after a lot of iterative development (also called: evolution), you end up with more and more logic inside the template.
There are a ton of things wrong in that paragraph, some of which I will now enumerate.
And thence proceeds Elver’s argument into a sort of Old Testament edict about separating presentation and logic: yea, the Lord saith that whosoever doth mingle the two shall be cursed, and cursèd shall be all of his seed, even unto the seventh generation. But that ignores the fact that separation of logic and presentation is a guideline, not a commandment, and that treating it as the latter will have nasty consequences. Like, say, having to do item = page.new_content_element(‘ol’) instead of just <ol>; that’s throwing the baby out with the bathwater.
As for the aforementioned “rapid development and Web 2.0”, well, markup-based templates are pretty darned good at that; sure, HTML and XML can be more complicated than you’d expect, but the most important and commonly-used aspects of both can be learned quickly. And they’re extremely fast for mocking things up — you can just drop in some lorem ipsum and roll with it rather than first having to write a database-driven backend to hook some sort of markup-generating program into.
And, frankly, replacing the front-end guy by putting more work on the back-end guy isn’t likely to work for most people.
Does this mean that we should just abandon the separation of logic from presentation altogether, and mingle them at will? Of course not; pretty much every developer worth his or her salt realizes the problems with that once it’s time to make a significant change to My First PHP App™. Remember, this is a guideline we’re talking about.
Elver also has some nasty words for Django‘s template language in particular:
Why is this bad? Well, you’re already writing SQL*, Python/whatnot, XML and JavaScript. Now you’ve got yet another language to learn and use. Not that big a deal, really, true.
But consider this. The whole point of decoupling presentation from logic is that you decouple code from how the thing ends up looking. Not only have you failed to do it, you’ve actually invented a new, buggy, inferior and untested programming language to hide that fact from yourself.
To paraphrase Jason, this is the part where I cough and it sounds like a naughty word. Any template language suitable for use in a dynamic, database-driven site has to provide at least a few features that aren’t in any HTML standard:
Django’s template system provides all of those, and without diving too deeply into the programming end of the pool:
{{ var_name }}. Is that really likely to blow the mind of someone who’s already learned “SQL, Python/whatnot, XML and JavaScript”?
{% if %}. It’s your friend. No matter how little programming someone knows, they can get this pretty quickly.
{% for %} (to deal with reptition within a single page) and {% extends %} (to deal with repetition across many pages). Still nothing particularly difficult going on.
{% get_recent_entries %} goes into one template, and suddenly every page has a list of the most recent blog entries.
As for “buggy and inferior”, well, Django’s template language has worked like a charm on an awful lot of sites over a period of several years, so I’d be careful about jumping to conclusions there.
And let’s not even get into how Elver’s proposal for ensuring that he “decouples code from how the thing ends up looking” is to… um… replace the way the thing ends up looking with some more code.
So, short and sweet:
Whew.
Comments for this entry are closed. If you'd like to share your thoughts on this entry with me, please contact me directly.
When people say “there shouldn’t be logic in templates,” they’re either:
While application logic has no place in templates, there certainly is such thing as presentation logic, and the template is exactly where it belongs. The nice thing about a well-designed template language like Django’s is that it allows for basic presentation logic that is easy enough for people that aren’t really programmers to understand, but it also is limiting enough to prevent people from trying to put application logic in templates (and trust me, I’ve tried…hehe).
And the designer scores yet another good point.
Let’s provide some context here.
The superman argument about being able to do both code and design. That’s not actually all that common, at least not around here. It’s good that you know how to do it, though. Congrats.
About the designer not being able to load the template back into his editor. Um. The company I work for here is currently working with an outside designer who’ll probably deliver the result by the end of the year. Probably as a PSD. It’s Estonia. Very few competent people.
About having more logic in the template. Then yes, in some cases, you do end up with a lot of logic in the template. I’m doing a database front-end to browse a couple of million books by a lot of different criteria. You do end up with an annoying number of decisions in the template. Sure, it won’t bother you when doing something as simple as a blog.
As for the code samples, then there’s probably a better, more saner way of doing this. (item = ol(), c = item.li(), …) The general idea, however, is that you start with a layout template, which is your basic XML document. In your controller code, you find the right element you need (div with some id, for example), and then you add additional tree elements to it as needed. And toss the outcome to the browser. This is later skinned with CSS.
Regarding the commandments, then that’s just my observations over the years. Yes, decoupling presentation from code is just a guideline and ye olde mightye God will not strike you down for not following it. However, it’s rather helpful.
Anyhow, it’s just an idea I’m playing with. What annoys me is how pretty much every existing templating system is either:
I’d like to see if perhaps an alternative approach of some sort will provide something better.
Why not build the dynamic parts of the XML tree in the code? You get more powerful tools to do so and if you’re doing XML/CSS properly, then your design should be in CSS, not XML anyway. Your XML tree should be design-neutral.
This is a people problem, not a template-language problem. And if your designer can’t open up anything that’s not a PSD, then there’s no template system on earth — pure code or otherwise — that can help him out.
I’ve worked on sites that were plenty more complicated than just blogs, and what I said above holds true; when you find yourself putting a ton of logic into your template, it’s time to revisit your view code.
As someone who does a fair amount of work with JavaScript, I can attest to this being absolutely the most painful way in the world to build a document. Again, markup is much faster and simpler.
Well, again, building a document tree in code tends to be a painful process. And, again, markup is pretty darned useful and quick to mock up and tweak, regardless of whether you have the backend finished. If your “templates” are serialized programmatically-constructed document trees, you’re going to have a heck of a time trying to test it unless your backend is complete, debugged and filled with content. Meanwhile, lorem ipsum us just a copy/paste away.
As for having the markup be design-neutral, well, I’d disagree with that myself; I think that page structure is an integral part of design, so even though markup and CSS should remain as separate as possible, you’ll still want to be keeping both in mind as you build up a template.
I have to say that I see Elver’s point despite disagreeing with him.
If the only person working on a project is a Python developer, then it makes perfect sense to stay “inside” Python whenever possible. This is the rationale that puts Django’s ORM, settings layer, RSS feeds, etc. in Python instead of some XML, INI, or any of the other formats that might work. Python kicks ass; using it rocks.
However.
The moment your work gets big enough that you need to delegate the front-end work to a designer, the pure-Python approach just doesn’t cut it. As my friend and collegue Wilson put it in this comment thread:
(Loudthinking doesn’t have comment permalinks, so you’ll find that nugget of wisdom about 1/3 of the way down the comment thread).
Luckily for Elver, there’s already a number of excellent Python-only template langauges he could use; PTL (part of quixote) and Nevow spring to mind; I’m sure there are others.
But is something like this ever going into Django’s core? No; Django’s optomized for building real-world sites where many people have varied roles; the single developer can easily install other software to suit her/his needs.
If you’re using an MVC framework with, say, PHP, then your view code should only need to look something like:
In my opinion, that’s really not worse than using a template language. (Let’s hope the comment form doesn’t destroy this code…)
Oh crap, let’s try this again:
ol ?php foreach ($comment in $comment_list): ? li h3?= $comment-title ?/h3 ?= $comment-body ? /li ?php endforeach; ? /ol
Here’s what Jesse was trying to post:
PHP is kind of an odd case, because it can be its own templating language…
Thanks James! The Markdown page was giving a 404 yesterday :P
Yeah I think that’s a strength of PHP. You also see this in ColdFusion, JSP and probably others. I think any language for the web needs this ability. If it’s not there, templating languages can certainly take their place.
Not to be aggressive, but your view is rather narrow minded. Elver is 100% correct. If one looks at Nevow your “option B” is a poor hyperbole, and only points out the further failures of Django and other similar Python frameworks.
There are more options, for example
def render_commentlist(self, c, d): # Get comment_list from somewhere # return ctx.tag[(tags.li[comment] for comment in comment_list)]
Now for starters, you maintain separation of logic from presentation after all the structure of your li tags is not going to change. On top of this, you have not introduced any strange programming languages - only a new XML namespace.
The other way of doing this is pattern renderer which would look something like
def data_commentlist(self, c, d): return comment_list
and the template
Now looking at these two methods, it’s far clearer what the better choice is. The better choice is not inventing languages.
I don’t feel like learning yet another language just to post comments either.
http://divmod.org/users/exarkun/nevow-api/public/nevow.rend-module.html#sequence http://www.karnaugh.za.net/show?id=219
Colin, I gave you your very own dedicated entry a couple hours ago. I await your response.
Jeff Croft came up with a priceless term, “presentational logic”.
In the end the truth is that css is too stupid to style a page without some massive hints.
Every time you chose between <ol> and <ul>, every time you choose between %ltp> or %ltdiv> every time you output a class=”header” and every single <li> in your code is a presentation element.
Do you want to trim coment entries to 255 characters? Make the category list Sentence Cased? reverse printed passwords?
More and more presentation logic.
Heck! even the order in wich data is presented is presentation logic. Headers go before footers? Data is to be packed in tables? Presentation I say!
From your program POV it may be more convenient to get the footer first from cache, then dynamicaly generate the header and finaly retrive your data from the DB.
But when you choose to output the header first you have already made a desing choice. And you shouldn’t have to, but you have, because css is too stupid to do it by itself.
“But that is a problem with css” you say? I agree, that’s what template languages are good for. They are not about getting the logic into the desing, but getting the design logic out of the business logic.
If fact I can even ask you Elver, why oh why do you insist on mingling the logic with the presentation? Do you want to be bothered every time the designer wants the program to output the date in a different format?
Or you just have a problem with people inventing new programing languages? I assume you code punching cards, write?
I wonder how much of this debate - and it’s one which I’ve had with myself over the years - is due to the confusion of page design with page styling. I think perhaps it was one of Joel Spolsky’s essays that brought this to my attention, but it would explain a lot if there are two quite different things being lumped together under the term design, wouldn’t it? There’s what I’ve always thought of as the real design - what content is on the page, and how is it arranged so as to make the page usable. And then there’s the stuff the Web Artistes (tm) do, which I’ve long thought of as cluttering up the content with stuff that might look good in print, or as a poster, but which too often makes the page a right pain to use - setting running text in a small font to cause eyestrain, or crowding the content to one side to make room for the Artiste’s photoshop collage… or, worse, some flash trash that’s more of a teevee commercial than useful content.
Anyway, I have a hazy notion that a template language tries to live in the uneasy ground where these two types of design fight it out. And I find some points on both sides in discussions like this that resonate, but working with Django’s templates have convinced me that the separation of logic is more than worthwhile. So the next Great Leap Forward should be a similar separation of the graphic design from the logical design of the content… if that’s possible. Possibly it doesn’t have a generally useful factoring (and also, possibly some kinds of pages don’t fit well in the way a particular template language divides the business from presentation logic - I don’t have wide enough experience myself to form an opinion on that).
BTW +1 on calling it “presentation logic” - that might help sorting out the real design and the styling aspects of what we tend to lump together as “web design”
Meta comment: what, no preview? Okay, then you’ll have to live with any typos or other flaws I’m not going to see, and so won’t correct, through this dinky little entry box that can barely show a short paragraph at one time. :-/
//If fact I can even ask you Elver, why oh why do you insist on mingling the logic with the presentation?//
The idea is the separate logic/structure from styling. Logic/structure should ideally be style-agnostic. This is hard to do, indeed, but it’s a worthy goal, methinks.