I <3 Steve McConnell*
Coding Horror
programming and human factors
by Jeff Atwood

Feb 4, 2009

You're Doing It Wrong

In The Sad Tragedy of Micro-Optimization Theater we discussed the performance considerations of building a fragment of HTML.

string s = 
@"<div class=""action-time"">{0}{1}</div>
<div class=""gravatar32"">{2}</div>
<div class=""details"">{3}<br/>{4}</div>";
return String.Format(s, st(), st(), st(), st());

The second act of this particular theater was foreshadowed by Stephen Touset's comment:

The correct answer is that if you're concatenating HTML, you're doing it wrong in the first place. Use an HTML templating language. The people maintaining your code after you will thank you (currently, you risk anything from open mockery to significant property damage).

The performance characteristics of building small string fragments isn't just a red herring -- no, it's far, far worse. The entire question is wrong. This is one of my favorite lessons from The Pragmatic Programmer.

When faced with an impossible problem, identify the real constraints. Ask yourself: "Does it have to be done this way? Does it have to be done at all?"

If our ultimate conclusion was that performance is secondary to readability of code, that's exactly what we should have asked, before doing anything else.

Let's express the same code sample using the standard ASP.NET MVC templating engine. And yes, we render stuff like this all over the place in Stack Overflow. It's the default method of rendering for a reason.

<div class="action-time"><%= User.ActionTime %></div>
<div class="gravatar32"><%= User.Gravatar %></div>
<div class="details"><%= User.Details %><br/><%= User.Stuff %></div>

We have a HTML file, through which we poke some holes and insert the data. Simple enough, and conceptually similar to the String.Replace version. Templating works reasonably well in the trivial cases when you have an object with obvious, basic data types in fields that you spit out.

But beyond those simple cases, it's shocking how hairy HTML templating gets. What if you need do to a bit of formatting or processing to get that data into shape before displaying it? What if you need to make decisions and display things differently depending on the contents of those fields? Your once-simple page templates get progressively more and more complex.

<%foreach (var User in Users) { %>
    <div class="action-time"><%= ActionSpan(User)%></div>
    <% if (User.IsAnonymous) { %>
        <div class="gravatar32"><%= RenderGravatar(User)%></div>
        <div class="details"><%= RepSpan(User)%><br/><%= Flair(User)%></div>
    <% } else { %>
        <div class="anon">anonymous</div>
    <% } %>
<% } %>

This is a fairly mild case, but you can see where templating naturally tends toward a frantic, unreadable mish-mash of code and template -- Web Development as Tag Soup. If your HTML templates can't be kept simple, they're not a heck of a lot better than the procedural string building code they're replacing. And this is not an easy thing to stay on top of, in my experience. The daily grind of struggling to keep the templates from devolving into tag soup starts to feel every bit as grotty as all that nasty string work we were theoretically replacing.

Now it's my turn to ask -- why?

I think existing templating solutions are going about this completely backwards. Rather than poking holes in HTML to insert code, we should simply treat HTML as code.

Like so:

foreach (var User in Users)
{
  <div class="action-time">[ActionSpan(User)]</div>
  if (User.IsAnonymous)
  {
    <div class="gravatar32">[RenderGravatar(User)]</div>
    <div class="details">[UserRepSpan(User)]<br/>[UserFlairSpan(User)]</div>
  }
  else
  {
    <div class="anon">anonymous</div>
  }
}

Seamlessly mixing code and HTML, using a minumum of those headache-inducing escape characters. Is this a programming language for a race of futuristic supermen? No. There are languages that can do this right now, today -- where you can stick HTML in the middle of your code. It's already possible using Visual Basic XML Literals, for example.

Visual Basic XML Literals used in an ASP.NET MVC view

Even the hilariously maligned X# has the right core idea. Templating tends to break down because it forces you to treat code and markup as two different and fundamentally incompatible things. We spend all our time awkwardly switching between markup-land and code-land using escape sequences. They're always fighting each other -- and us.

Seeing HTML and code get equal treatment in my IDE makes me realize one thing:

We've all been doing it wrong.

Posted by Jeff Atwood    View blog reactions
« Mixing Oil and Water: Authorship in a Wiki World
Don't Reinvent The Wheel, Unless You Plan on Learning More About Wheels »
Comments

It's called PHP and it sucks

Lee on February 5, 2009 1:01 AM

I forgot to mention that Tapestry's templates are previewable: they can be viewed directly at a browser without a server and they render exaclty like they would when requested through a server. This way, web designers and programmers can easily work without messing with each other code/HTML/CSS/whatever.

Thiago on February 5, 2009 1:02 AM

Mixing HTML with code reminds me of a couple of things I've worked with in the past. One of them is PHP, another is JSP. I guess mixing code with HTML is where we're coming from, and it is really not where we should be going.

I've come to like component-based frameworks such as Tapestry 5 and Wicket very much. Their component model, IMO, is the first thing that really makes you want to write components - because unlike taglibs and templating engines and JSP and JSF and most other things, these things are actually useful for writing reusable bits that output HTML.

Henning on February 5, 2009 1:02 AM

One of the problems with NHaml or Spark is, AFAIK, you don't get compile time checking of your views, which I find really useful if I'm doing heavy refactoring. As more and more components like the Grid in MvcContrib are built, I think drawbacks to using the standard ASP.NET templating engine will be fewer and fewer.

Nick Gieschen on February 5, 2009 1:08 AM

@Rob Paveza on February 5, 2009 08:35 AM :

This is ASP.NET MVC. You don't use a server-side managed form (i.e.: form runat=server...)

Andrei Rinea on February 5, 2009 1:09 AM

Funny, that almost exactly looks like how qpy works. See: http://www.mems-exchange.org/software/qpy/

Your example would look like this

def div:xml(klass, *stuff):
'div class=%s' % klass
'br /'.join(stuff)
'/div'

for user in users:
div(action-time, action_span(user))
if user.is_anonymous:
div(gravatar32, render_gravatar(user))
div(details, user_rep_span(user), user_flair_span(user))
else:
div(anon, anonymous)

Highly recommended.

M-MZ on February 5, 2009 1:19 AM

This post made me recall some of the worst ASP Classic code I'd ever seen. I have no wish to return to those days.

There is something to be said for specialization. Most web developers I know are terrible at CSS and browser compatibility. Usually they are equally poor at T-SQL (myself included). Separating HTML from [language of choice] from [database of choice] gives you the ability to divide the labor amongst people qualified to manage it.

As soon as you try to merge these three paradigms (I am not fond of LINQ either) you end up shifting the bulk of programming responsibility on the server-side programmer, which tends to be the most expensive programmer in the group. You also dilute his/her knowledge of the stack they're working on, which creates its own problems.

HTML is a markup language, not a procedural language. Regardless of its original purpose, it is usually now tightly coupled to graphic design. Factor the HTML out and you produce better, more maintainable, reusable code. If you can't factor your HTML into something that an object instance could emit seamlessly, it's time to replace your HTML developer.

RickCabral on February 5, 2009 1:23 AM

not mentioning markaby here is a crime :)
http://markaby.rubyforge.org/

sam on February 5, 2009 1:41 AM

Adding another vote for Wicket. If you want to see templating done right, you should check it out. Actually calling it templating is taking it a bit too far. All the template are pure html pages and will render in a normal browser fine. There are no ifs or loops or variables. Instead you link id's in your html file with ids in your code.

It's very clean and very powerful.

Ståle Undheim on February 5, 2009 1:50 AM

But beyond those simple cases, it's shocking how hairy HTML templating gets. What if you need do to a bit of formatting or processing to get that data into shape before displaying it? What if you need to make decisions and display things differently depending on the contents of those fields? Your once-simple page templates get progressively more and more complex.

Maybe you don't hate PHP as much as you profess, Jeff.

Frank on February 5, 2009 2:05 AM

@Justin: I don't think designers should be doing HTML, thats what CSS is for.

Angel on February 5, 2009 2:13 AM

Jeff, the only difference between your last two code examples are a few '%' tags, and now you have to compile your html. Yet somehow, this is obviously better? I don't think so.

You want to keep things simpler? The solution isn't to fundamentally re-architect how data and html interact. The solution is to break up your templates into more manageable units. It's analogous to breaking a 100 line method up into 4 30 line methods...there might be a few more lines of overhead required for this, but individually they're much easier to understand because they have fewer responsibilities.

Use user controls, or server controls. That's what they're for.

Doug on February 5, 2009 2:31 AM

I really like Groovy's MarkupBuilder - it's a really nice way to create HTML/XML in your code, like this (taken from the Groovy website, modified slightly):

def foo = false

def writer = new StringWriter()
def xml = new MarkupBuilder(writer)
xml.records() {
car(name:'HSV Maloo', make:'Holden', year:2006) {
if (foo) {
country('Australia')
record(type:'speed', 'Production Pickup Truck with speed of 271kph')
}
}
car(name:'P50', make:'Peel', year:1962) {
country('Isle of Man')
record(type:'size', 'Smallest Street-Legal Car at 99cm wide and 59 kg in weight')
}
}

println writer.toString()

Josh Brown on February 5, 2009 2:37 AM

I guess we need a LINX analog to LINQ. VB XML literals are a step in that direction, and I'm a little jealous that we don't yet have this in C#!

Daniel Fortunov on February 5, 2009 2:52 AM

I've enjoyed the asp.net apps that override the Render and just issue lots of Response.Write statements to output all the strings that make up the web page...

Steve on February 5, 2009 2:52 AM

@Sebastian - i noticed it too... i had to break out of my rss reader just confirm what i was seeing.

Jeff Martin on February 5, 2009 3:03 AM

As others have pointed out, Seaside's ( http://seaside.st/ ) Canvas API is very much along those lines. We came to the conclusion a number of years ago that templates just don't scale. As your application gets bigger and more composed and you go through several revisions, they just get messier and messier.

Seaside's strategy is to express all the html generation in code. The major benefits here are that you don't have to mentally context-switch between code and HTML all the time and that you can apply all of Smalltalk's refactoring tools to split parts of it into reusable methods and so on.

If you're generating a lot of very plain-jane static HTML, it can be slightly more verbose than the HTML it generates but as soon as you start throwing in dynamic IDs, callbacks, ajax, and so on it's really a beautiful way to work.

Julian Fitzell on February 5, 2009 3:11 AM

*ahem* TeX *ahem*

Seriously, I think that TeX encapsulates a lot of what's good and bad about this idea.

Brooks Moses on February 5, 2009 3:19 AM

Having been through CGI, JSP, ASP (arrggg)/ COM (double arrggggg), XSLT (better than all ASP soup), WebForms from 1.0, now looking at MVC.... have come to the point of just hacking together my own methods of least resistance, abusing any of the above if I need to.

2 questions that beg asking:
- WTF is the one true way going to be next week?
- Is it just me, or are we going in circles here?

seanb on February 5, 2009 3:22 AM

Yes. We are going in circles.

Andrew on February 5, 2009 3:37 AM

I'm starting to wonder if it's not better just put everything in javascript and make server calls only to get content. Leave the javascript to build all the html (presentation of the content) and put the content in place. This way you are basically putting most of the effort in the client instead of the server. By caching the javascript you are also saving bandwidth/time and of making your website more responsive.

Hoffmann on February 5, 2009 4:07 AM

Admittedly I don't do a lot of Web work these days. But isn't the whole idea to separate the UI from the business logic? If we're just talking about presentation-layer code, I can understand the need for this discussion to an extent. Still, I've seen very limited need for code in the presentation layer of Windows Forms applications.

Bill Sorensen on February 5, 2009 6:32 AM

There's nothing wrong with templating if you have good tools. Strong tags libraries and an expression language are all you need.

http://en.wikipedia.org/wiki/JSTL

Mike on February 5, 2009 6:48 AM

May be Element Construction Set (java) will get some respect.

BuggyFunBunny on February 5, 2009 6:57 AM

Ever heard of it?

XSLT on February 5, 2009 7:11 AM

Martin Fowler hates XSLT too

http://www.codinghorror.com/blog/archives/000333.html

Jeff Atwood on February 5, 2009 7:14 AM

In The Sad Tragedy of Micro-Optimation Theater we discussed

Optimization you mean, Jeff? Sorry, didn't mean to nitpick, but I thought you'd might want to be aware of that one.

Mike on February 5, 2009 7:29 AM

Ever poked into coldfusion? It's the closest I've seen to treating html code as the same thing- Actually, most CF commands are in the form of markup tags, so the way to assign x = 4 is cfset x=4. Pulling variables within your HTML is as easy as adding surrounding pound signs (modified to square brackets): [h1]The value of x is #x#[/h1].

Alex on February 5, 2009 7:30 AM

Genshi templates embed Python code into XML.

Example:

lt;py:for=User in Users
lt;div class=action-time${ActionSpan(User)}lt;/div
lt;py:choose test=User.IsAnonymous
lt;py:when test=True
lt;div class=gravatar32${RenderGravatar()}lt;/div
lt;div class=details${UserRepSpan()}lt;br/${UserFlairSpan()}lt;/div
lt;/py:when
lt;py:otherwise
lt;div class=anonanonymouslt;/div
lt;/py:otherwise
lt;/py:choose
lt;/py:for

http://genshi.edgewall.org/

Hau on February 5, 2009 7:33 AM

yeah I absolutely agree!
There just is no way to separate HTML and Code completely. It's an illusion. Everybody knows that.
Then people come up with crazy complicated template meta languages, which aren't really keeping thing simple. So yeah, mixing code and HTML, best thing to do. Producing code and classes that makes sence.. always better than obey Mr. You-CANT-do-that-Design-Pattern, just for the sake of it!

greg on February 5, 2009 7:37 AM

You can simply ignore HTML and do everything in code.
Have a look at Seaside (http://www.seaside.st) a mature web framework in Smalltalk. Its HTML generation is very elegant et very convenient.

fstephany on February 5, 2009 7:42 AM

Are you saying that HTML is wrong?

Josh Stodola on February 5, 2009 7:43 AM

TAL seems to get close, as a templating language which is really just code (or really, it turns the template into code). http://wiki.zope.org/ZPT/TALSpecification14 - though the spec is somewhat cryptic as EBNF type specs tend to be. Its been implemented in a few different languages, like php http://phptal.motion-twin.com/

Anyway, instead of defining a wholely different syntax, it uses xml namespaces to provide programming structures - letting you write 100% valid XML. You can even insert 'placholder' text/elements which get replaced by the template, so the page will render full HTML without the templating engine.

There's currently a 'backlash' in the PHP community against templating engines - reason being, PHP is sort of a templating engine in itself, given the right setup. Most of the MVC frameworks make it so that you cant do too much 'dangerous' stuff in the templates because they're in a limited scope, but if you still don't trust the template writer (maybe because its part of some CMS), a template engine is needed just to protect the system from 'real' code. Template engines in PHP were mostly designed before MVC became possible (pre php4) to still give code/display separation.

Jystin on February 5, 2009 7:48 AM

Isn't the idea to mix the HTML and code together just reinventing old style ASP? Wasn't that complained about precisely _BECAUSE_ of the mixing of code and markup?

There is no perfect answer other than to try to make your code and markup as clear and straightforward as possible.

Jeff Cuscutis on February 5, 2009 7:49 AM

XSP[1] was doing that around a decade ago. For my money it's represents too little layering. I don't want code belonging to an application fiddling about with HTML tags.

[1] a href=http://en.wikipedia.org/wiki/EXtensible_Server_Pageshttp://en.wikipedia.org/wiki/EXtensible_Server_Pages/a">http://en.wikipedia.org/wiki/EXtensible_Server_Pages/a">http://en.wikipedia.org/wiki/EXtensible_Server_Pageshttp://en.wikipedia.org/wiki/EXtensible_Server_Pages/a

Tom Hawtin on February 5, 2009 7:51 AM

The best (tm) way to render HTML within languages is to define functions, I think. Here an example in Perl (also possible in Ocaml, C, Python, Java...):

sub a {
my $url = shift;
return a href=$url, @_ , /a;
}
..

#render it
render(
html(
head( ..#headoptions
),
body(
a( http://codinghorror.com, $text ), #...
)
)
);

this approach works in nearly all languages and if the functions encapsulated in a generic html library, all is fine.

art1 on February 5, 2009 7:54 AM

I absolutely hate embedded code in HTML. And XSLT is about as write-only as APL or bad perl.

Ruby on Rails has the delightful haml (with its CSS sister, Sass) which does a reasonable job of DRYing up some opf the nastiness. I believe there's a .Net equivalent (http://andrewpeters.net/2007/12/19/introducing-nhaml-an-aspnet-mvc-view-engine/) but I don't know how mature it is. OK, there's a need to accept Python-like (pythonical?) Significant White Space, but who doesn't indent these days?

It's the best solution I've seen so far, actually not a horrible experience, unlike the vanilla embedded alternative.

Mike Woodhouse on February 5, 2009 7:56 AM

If you're using ASP.NET MVC, then they have a cool feature where you can replace the default ASP.NET template engine with one of many alternate ones that are developed by third parties and Open Source project groups. They do much of what you think is the ideal. Some of the more notable ones are:

- a href=http://dev.dejardin.org/trac/sparkSpark/a
- a href=http://code.google.com/p/nhaml/NHaml/a
- a href=http://www.castleproject.org/MonoRail/documentation/trunk/viewengines/brail/index.htmlBrail/a

Nick on February 5, 2009 7:59 AM

Or use HAML. Took me some time to get used to it… now I love it!

http://haml.hamptoncatlin.com/

niko on February 5, 2009 8:00 AM

Or you could add your strings in as labels and use repeaters. You know, the way you're supposed to do it with .Net web forms. Your propsed solution brings back the horrors of the worst PHP and ASP designs.

bob on February 5, 2009 8:01 AM

wicket is does something fairly similar to what you are talking about jeff if you can stomach java...

tim on February 5, 2009 8:01 AM

Wow i misspelled my name in the last post? Must be too early.

@art1 - defining functions that 'render' HTML is probably the most horrid thing ever. Its totally unmaintainable, and diverges so far from the actual representation that you're ensuring that nobody but you will ever really know whats going on. Plus, what happens when your function doesn't support all the attributes you want to use? How might you add XFN notation? Its just not viable. I'd go with string replace/concat WAY before thinking about functions like that.

Justin on February 5, 2009 8:02 AM

If you'll excuse me, I must make a comment about the following sentence Templating tends to break down because it forces you to treat code and markup as two different and fundamentally incompatible things.

See, I feel that you are simply turning the tables here: Instead of breaking from HTML-land to code-land, this method would make you break from the code-land to HTML-land. Actually, if you add some quotes and braces and semicolon, and what you've got on your hands is the traditional way of producing a webpage in PHP.

I won't go into further details, but I have also objections concerning (X)HTML-validation and also parsing the whole thing (e.g. getting something that could be interpreted as code, output to the resulting document).

On the other hand, I'm always up for diversity. If someone implements this 'backwards templating' in a successful way, I might as well adopt it. It's a no-lose situation for me :)

Henrik Paul on February 5, 2009 8:07 AM

I mostly agree with art1. You've already lost at the moment you start mixing HTML and logic or content. (exluding the wrapper functions)

Ideally though, enclosing HTML tags would be code blocks, rather than functions. That way, an error in a link doesn't report from body(). Each tag would have its own scope as well.

Actually, that sounds like something that would be interesting to try to implement myself...

Ryan Fox on February 5, 2009 8:08 AM

@art1, you've just reinvented a href=http://search.cpan.org/dist/CGI.pm/CGI.pmCGI.pm/a. eek.

Justin Mason on February 5, 2009 8:09 AM

One proofreading comment, you got the then and else blocks of User.IsAnonymous reversed (in both cases). As for the VB.NET example, could you change it to do the same as the previous examples?

Motti on February 5, 2009 8:09 AM

heh. http://search.cpan.org/dist/CGI.pm/CGI.pm

Justin Mason on February 5, 2009 8:09 AM

why not keep the HTML template simple and prepare your data for view before sending it to be rendered? then all you really need are simple to read iterate and placement tags. I primarily work with Java/Jsp and cringe each time i see a view with complex formatting logic.

BTW long time reader first time poster, great site thanks!

meatpopsci on February 5, 2009 8:11 AM

NHaml clears up a lot of the ugliness of templating. While it doesn't fix everything, I think it clears up a lot.

And if you use ASP.NET MVC, using HtmlHelper extension methods + NHaml allows you to treat those tricky templating problems as code problems.

http://andrewpeters.net/2007/12/19/introducing-nhaml-an-aspnet-mvc-view-engine/

Brian Hartsock on February 5, 2009 8:12 AM

Am I the only one who spotted what's really wrong with this picture?

if (User.IsAnonymous)
{
(render gravatar)
}
else
{
(print anonymous)
}

Either User.IsAnonymous returns a counterintuitive result or the if/else cases are backward...

Sebastian on February 5, 2009 8:12 AM

I have a custom templating system I use with only the following commands:

output variable, foreach loop, if/else (with only if x and if x == y), and include file.

The way I see it, if you are using more than that in your template, you are doing something wrong in your code.

Furthermore, my code which lets you set template variables escapes all HTML sent to it, forcing me to actually stick to putting all the html in the template where it belongs.


Beats the hell out of every bizarre combination of code/html I've ever seen.

anonymous on February 5, 2009 8:13 AM

The reason for using templates is to allow designers (non-coders) to work and modify them.

There are several templating options that are parseable html with reasonable defaults.

Tooty on February 5, 2009 8:14 AM

Mako ( http://www.makotemplates.org/ ) also works that way, and is the best templating language I've ever used. It also has cool features like inheritance (that don't really make sense until you read up on them and use them, and then they're great) and function definitions within the templates.

-Max

Max Kanat-Alexander on February 5, 2009 8:15 AM

FWIW, what little HTML generation I do these days, I do using Linq to Xml, producing XHTML. It works very well for me; and I don't think that the way C# implements it is useless. My streams of data to be inserted are in the form of IEnumerable instances. The fact that what would otherwise be repeaters can be trivially abstracted as methods, and other familiar code-oriented idioms - including view inheritance - adds up to quite an advantage for the developer trying to produce some output.

Re designers, it's probably best to try and produce a well-defined hierarchy of divs etc. with appropriate classes and ids, and let the designer style them via CSS.

Barry Kelly on February 5, 2009 8:21 AM

That's taking a step backwards, surely?

Stage 1) Learn HTML. phello world/p
Stage 2) Stumble around in PHP. p?=$message;?/p
Stage 3) Learn templating. p{VAR:message}/p and strreplace()
Stage 4) Mix template and code?

Is stage 4 not identical to stage 2? What's the practical difference?

I have two types of markers in my home-brew templating system, one for variables and one for looping/switching. The template class is recursive, and I can do anything in the above examples without abandoning the principles that made me switch to stage 3 in the first place... ie, I can give the template only to the designers without them borking the code, and they can see it rendered in a browser without needing it to be parsed by the PHP. What am I missing?

(forgive any layout issues/missing examples - I'm assuming the big red 'no HTML' means that it'll be converted to HTML entities rather than removed and if I'm wrong, meh, read the text :) )

Schmoo on February 5, 2009 8:22 AM

I think that one missing point is DRY: Having templates handling the HTML, even if it's a mess of spaghetti code, leaves the html building functions in just one place.

As for the uglyness of the logic/conditionals/iterations mixed with the HTML, I see the point there, one elegant solution is the one propose here, and implemented in Haml: http://haml.hamptoncatlin.com/

Angel on February 5, 2009 8:29 AM

I'm not sure intermingling html with code is all that much better than intermingling code with html - even if it's native in the IDE. Most solutions seem to amount to some bastardized balance of the two - usually with an added syntax (new tags, comments for vars and loops, etc). Namespacing like TAL seems interesting, but there's still an entire set of added syntax.

It's always seemed to me that the most ideal HTML template would be entirely based on HTML itself, using classes and ids - or better yet, selectors a la jquery or prototype, where you would have something like:

?php
$aOutput= array(
'employees' = array(
array(
'employee' = array(
'name' = 'Joe',
'age' = 30
)
),
array(
'employee' = array(
'name' = 'Sue',
'age' = 25
)
),
)
);

$oTemplate-load('employees.html', $aTemplate);
?

And then your template would look something like:

div class=employees
div class=employee first
b class=name/b
span class=age/span
/div
div class=employee odd
b class=name/b
span class=age/span
/div
div class=employee even
b class=name/b
span class=age/span
/div
div class=employee last
b class=name/b
span class=age/span
/div
div class=employee last even
b class=name/b
span class=age/span
/div
div class=employee last odd
b class=name/b
span class=age/span
/div
/div

The loops would be handled automatically. The extra classes (even, odd, first, last) would only show for meta information, so for the first iteration, it would show the first div, and so on. If employees were empty, it wouldn't parse the div. All conditions would be handled in the code that generates the $aTemplate array.

I started this endeavor a couple years ago and did alright using the horribly documented PHP DOM Objects, but never found the time to take it very far. At the very least I had the implied loops and meta conditions working.

Mark Armendariz on February 5, 2009 8:35 AM

If you are using css for all the styling then the html is just the data layout and so should be in code.
The objections to html in code are from back in the day, when you had to check through 1000s of lines of C++ to find out why a font was changing or call in the programmer to change a background color.

mgb on February 5, 2009 8:35 AM

Jeff, if you've got ASP.NET code that looks like this:

%= RepSpan(User)%br/%= Flair(User)%

I think the real question is: why aren't you using ASP.NET custom controls? They're not terribly difficult to develop, and once you've got them they're a lot more consistent with the rest of your ASP.NET site:

so:Flair runat=server id=userFlair /

Then during your databinding handler you simply assign the user to your userFlair object via a property. You could even databind it declaratively:

so:Flair runat=server id=userFlair User='%# Eval(User) as User %' /

The same thing goes for the user's gravatar, action, reputation. Obviously, writing the custom control means you're going to have to write HTML procedurally. But the benefit of using an OO language behind ASP.NET is that you're going to be able to hide the details of it - once you've created your Flair control, you don't need to even acknowledge its presence except declaratively. There's no special call to a parent's RenderFlair() method. It's encapsulated inside of its own bubble of awesome. ;-)

Rob Paveza on February 5, 2009 8:35 AM

(apologies for the typo, $aOutput should be $aTemplate)

Mark Armendariz on February 5, 2009 8:37 AM

what's so wrong with PHP that people hate it so much. Can anyone explain why PHP is bad? it is so flexible that you can use it as templates if you really want to but you have the option to mix the code with html or even keep everything as code... it is up to the programmer to decide.

Pawel on February 5, 2009 8:40 AM

Again, I think HAML is doing it wrong too. Why would you want to generate a language that looks NOTHING like the intended output if you can get away with it?

In 'real world' situations, you are likely going to work with a graphic designer, or 'UI' focused developer who doesn't know your backend language very well. They are NOT going to write HAML. They're going to write HTML (or generate it in goLive or something). HTML/XML based languages (wether its TAL or inserting language tags % % or ?php ?) then becomes somewhat trivial. I guess there is the 'html2haml', but then you'll get a change from the designer and have to redo it.

Its sort of bugging me that just in this small discussion scope, there is a lot of solutions that are quite anti-diverse-team. If you're getting far enough from both the likely input and likely output that you need a translator, you're doing something wrong.

I don't expect the designers to learn to write HAML, or even much PHP other than simple things, and I'm not going to have the time to teach them. The quicker they get work done, the quicker I can get work done.

Justin on February 5, 2009 8:43 AM

Rather than poking holes in HTML to insert code, we should simply treat HTML as code.

No thank you.

asdf on February 5, 2009 8:46 AM

@Mark Armendariz: Take a look at TAL - it is essentially doing exactly what you're talking about, without potentially mucking with intended output classes, etc.

I know I sound like a super-advocate of it, but I just find it the perfect blend of code and xml display - it forces you to write good XHTML too! Sadly, I've only used it in one of my personal projects, and never in a big site, so I can't tell you how it is 'at scale', but it does do template compilation and caching, so it'd be no worse than most of the other templating languages.

It came from the Zope project, and is available as modules for other languages. http://en.wikipedia.org/wiki/Template_Attribute_Language

Justin on February 5, 2009 8:47 AM

All code, including HTML, is just code. Using templates lets you refactor the HTML out of your main programming language. It also limits the amount of damage designers can do when they poke around.

The point isn't to use/don't use templates. The point is to use whatever works for you, preferably the simplest possible method.

BTW, while I can't be bothered to care about all the PHP-hating amongst proponents of lesser languages ;), it's worth noting, that it's by far the most popular server-side scripting language, and it's been so for many years now. Don't dis the language because _you_ suck at it :)

MichalT on February 5, 2009 8:48 AM

Oh God, several dozens of comments and no-one mentioned Lisp yet. Just look at how cl-who works and be enlightened.

rassie on February 5, 2009 8:50 AM

That it is a good idea not to distinguish code from data has been known for a very long time. Kind of way back to the Lisp-days...

JesperE on February 5, 2009 8:51 AM

How is your suggestion any different than what is currently accomplished with PHP? Is adding XML structural validation the only advantage?

php? on February 5, 2009 8:52 AM

Templating languages handle the important task formatting the output. For example, XSLT handles aspects such as encoding, content type, and indenting. While most templating languages focus on allows small manipulations in the content, the big win is having a reliable layer that translates the programming language data into actual content. As Americans, this is pretty tame since our programming languages are effectively English. But, when you consider other languages, a templating language and layer is the only way you can handle the disjoint between programming data and actual content.

Eric Larson on February 5, 2009 8:52 AM

A lot of people have shown ways to include code in the markup. PTL (Python Template Language) does what Jeff illustrated with Visual Basic XML Literals and puts the markup into the code. Not quite as slick as XML literals but pretty close, and it's been around since 2002.

http://quixote.python.ca/quixote.dev/doc/PTL.html

Another templating approach is taken by the Meld family, which injects Python code into an existing vanilla-HTML template in a way similar to javascript's DOM manipulation:

http://entrian.com/PyMeld/

Ian Jones on February 5, 2009 8:55 AM

That's exactly what Seaside (www.seaside.st) does (indentation will probably be lost):

renderContentOn: html
html table
id: self ajaxId; class: 'report';
with: [ self renderTableOn: html ]

This generates:

table id=theAjaxId class=report
...(the result of [self renderTableOn: html] goes here)...
/table

sroccaserra on February 5, 2009 8:56 AM

Awesome awesome awesome. THATS exactly how it SHOULD be and I agree with the one commenter who mentioned coldfusion's been doing it right for a long time.

One of your best articles.

craig on February 5, 2009 8:57 AM

@anonymous (08:13 AM):

Sounds like you are describing StringTemplate (http://stringtemplate.org/).

I recently reviewed my options for generating HTML in Haskell (http://blog.uncommons.org/2008/12/03/generating-html-with-haskell/). Haskell Server Pages does a good job of the HTML-as-code approach, but I ultimately dismissed it in favour of the Haskell port of StringTemplate.

Mixing logic and presentation mark-up in one place rarely ends well.

Dan on February 5, 2009 8:58 AM

Jeff, as others have said before, this is no different from the PHP/Jurassic ASP code-in-html soup which we've been struggling to get OUT of for the last so many years...

shash on February 5, 2009 8:59 AM

Excellent post Jeff. This is a great observation that you've come up with that could make ASP.NET MVC at least somewhat palatable for me. The big problem though is the developer has to maintain all the state of the controls in MVC unlike ASP.NET web forms where its all maintained in the viewstate if I recall correctly. That's why I dislike MVC (plus no designer support) and because of at least one more reason:

The three chief virtues of a programmer are: Laziness, Impatience and Hubris.
-Larry Wall

o.s. on February 5, 2009 9:00 AM

i agree

theman on February 5, 2009 9:03 AM

When I start to run into problems like the one you've hit, it's usually a sign that I'm Doing it Wrong. Everything in a template needs to resolve to either:

* Another template
* A variable
* A function in code that spits out HTML (last resort, do not use without breaking glass)

Everything else is markup.

As soon as you start using JSP tags to do conditional statements, for example, you are creating a black hole that will shortly consume the sun.

asdf on February 5, 2009 9:14 AM

In Scala you can also mix HTML and code, just like in your example.

Joe on February 5, 2009 9:18 AM

I hear that Asynchronous JavaScript and HTML is handy for this type of thing.

*takes tongue out of cheek*

Vance on February 5, 2009 9:35 AM

I would agree that there is no way to separate code from html.
Code in html of html in code, there is still a problem.
The whole concept is a messy, unclean design.

If the criteria used to decide what belongs in what is how messy it looks (instead of higher level architecture or design), the technology is flawed.

Add here another layer (let's say localization, where you should have localizable stuff in a 3rd place) and you realize this is a junk technology held together with duck-tape (and this also applies to JSP, PHP, ColdFusion and all the other technologies in this family).

Mihai on February 5, 2009 9:35 AM

I must agree with the templating problem. After developing in “classic” ASP for what seems forever, using ASP.NET to seperate the content seemed nice. The main problem we had was that we work on a local government site in the UK which is inspected annually for various things (including markup and accessiblity). For us it is very important to pass this inspection, and as the standard .NET controls do not produce standard XHTML code, I went with XSLT to produce all of the markup.

I know that XSLT can make hard things easy, but can also make easy things hard (it not being procedural and all), so to solve this problem, I pass into the XSLT a compiled C# library with some common functions written in C# which can be called directly from the XSLT. And for any bespoke functions for a page, you can create C# functions directly in the XSLT.

Combine the above process with master pages, ASP.NET caching and the result is speedy, compliant pages.

Paul on February 5, 2009 9:42 AM

1. execute code which calls db via sql
2. output into html

we're using an intermediary language to connect two completely different languages. does this make sense *at all*? the whole paradigm is broken and its not only the presentation layer.

Ivan on February 5, 2009 9:46 AM

+1 for Haml. It's not for everyone, but it sounds like you are ready for it. Seriously. Check it out. It is available for many for many frameworks.

Daniel on February 5, 2009 9:50 AM

Generating HTML is like having a compiled language and then including assembler in the source code, yes you can do it, yes sometimes it is required, but you should not have to....

Either take a step away from HTML and use a language powerful enough so that you never have to see HTML ever again, and let the HTML generator in the language do the work .... or put up with one of the compromise solutions above

HTML is for laying out text, it had been stretched to do more and more and should now be either dumped for something better or hidden away as something people no longer look at (like machine code)

Jaster on February 5, 2009 9:55 AM

As wise commenters before me have said: A templating language is the answer.

Your examples are weak. There is no conceptual difference between your 1st tag based and your 2nd code based example. Lets replace the foreach loop with a... foreach loop!?

Your argument is the code based one is cleaner? Get a clean templating language then... there are plenty out there. XSLT is not one of them.

The point of of templating is division of labour, You don't want to give a designer/javascripter capable of writing simple templates with loops a whole programming language to shoot himself in the foot with. Also way easier to compile and give meaningful errors if you remove everything except looping constructs, and filter operators that do stuff with the data supplied to the template like... sanitize, enumerate, slice, paginate, translate, uppercase, lowecase, capitalize, date format, time format, unit conversion.

Are you both doing templates and back-end programming? Do whatever you want. Just make sure you charge enough to put a designer through programming school should you ever need one to work on your templates.

monowerker on February 5, 2009 10:10 AM

Motti and Sebastian called it: You've got the then and else blocks reversed in both examples.

And, do please update the Visual Basic XML Literals example to do the same anonymous user display task as the previous examples.

Zack on February 5, 2009 10:21 AM

Can you create custom MVC UI Helpers?

%=Html.Image(~/images/baseball.jpg)%br /

Would your Visual Basic XML Literals example match up to one of those?

Zack on February 5, 2009 10:22 AM

Oh, and also...

Ha! Suck it, C# fanbois!

Zack on February 5, 2009 10:22 AM

Take a look at the Spark View Engine. Code + Html all in one.

www.sparkviewengine.com

Donn Felker on February 5, 2009 10:29 AM

Do you really want to have to recompile the entire Web site when a designer just wants a class name diddled with?

I've always thought that building HTML strings directly in code is impractical for certain kinds of environments where you have a designer/developer split.

And I guess NHaml is cool, but I don't really see the point. If I'm outputting HTML, and I'm having to do all sorts of weird hacks to get things to render consistently in Firefox/Opera/Safari/IE6/IE7/IE8, why don't I just write HTML directly? The last thing that I want is to have to compile and run my template just to see what magical HTML it has output. Oh no--it spit out a line break after that tag, but IE6 renders an incorrect line-height if there's a space there--how do I get around that? I guess I'm just being old-fashioned, but people tout NHaml for its simplicity, but I just don't see how adding another level of indirection to HTML generation makes things simpler.

The processes that we invent just to emit a string to a browser is sometimes amazing.

Nicholas Piasecki on February 5, 2009 10:37 AM

For HTML templating in Lua I've developed Tempel:

http://code.google.com/p/tempel/

I came to the conclusion recently that for templates to be powerful enough to be really usefully they need to bound closely both to HTML and to a programming language. The goal of the project is to create a DSL powerful enough to do all presentation related manipulation of data inside the template itself rather than the code calling the template.

nrich on February 5, 2009 10:38 AM

I think you're doing this example wrong:

%foreach (var User in Users) { %
div class=action-time%= ActionSpan(User)%/div
% if (User.IsAnonymous) { %
div class=gravatar32%= RenderGravatar(User)%/div
div class=details%= RepSpan(User)%br/%= Flair(User)%/div
% } else { %
div class=anonanonymous/div
% } %
% } %

In proper enterprise ASP.net that should be:
[ascx]
asp:repeater id=rpt_users databind=blah
div class=action-time%= ActionSpan(User)%/div
asp:panel id=pnlLoggedIn visible=false
uc1:gravatar id=myGravatar ... /
div class=details....br/uc2:flair id=myFlair ...//div
/asp:panel
asp:panel id=pnlAnonymous visible=false
div class=anonanonymous/div
/asp:panel
/asp:repeater

The repeater databind code should then ipck the correct panel to display and stick in the correct values.
You could take this one step further by creating your own UserDisplayPanel control which will do the thinking and render the avatar and flare correctly for a user, anon or not.
That would mean your final code will be nothing more than a repeater around a control which renders user banners or whatever.
I've never been a huge fan of using %= % syntax.


Vanja O. on February 5, 2009 10:39 AM

And now, for the 378th way to skin the cat...

Practicality on February 5, 2009 10:44 AM

There are a few problems that I see with this idea of having no distinction between code and HTML:
1) Maintaining a good separation between view code and controller code requires more effort than slapping everything together. While I love me some PHP, that's one of its warts.
2) Web designers complicate the picture. If you've got a workflow where the web designers are expected to deal with the templates directly, then you want a very minimal amount of code in the template. In the example with the functions doing helper rendering, I don't see why you couldn't replace them with special read-only properties on the code-behind's class that does the dirty work there. That gets you back to the original ASP.net example.
3) I don't see how this is inherently better than ASP.net's templating. Again, my inclination is to try to keep the view code seperate, and doing that with your system still means doing something very much like ASP.net templating.
4) This would be a not-insurmountable implementation problem, but the idea of mixing server code with client HTML feels wrong from a security standpoint. It would have to be implemented in a way that there is still no ambiguity as to what is run on the server and what is run on the client. *That*, IMHO, is the main driver the current separation between code and HTML.

Nathaniel on February 5, 2009 10:57 AM

DEAR LORD NO.

Why do you separate HTML and CSS? Because document structure (HTML) should be separate from document style (CSS). For a lot of reasons I won't list here, because anyone reading this comment should already know them.

Many of the same things apply when you talk about keeping code and HTML separate. If you're finding that you're doing more than a few simple loops inside your template, then you're probably doing it wrong.

Example:

%foreach (var User in Users) { %
div class=action-time%= ActionSpan(User)%/div
div class=%= UserInfoClass(User) %%= UserData(User) %/div
% } %

You then have UserInfoClass() return the class needed, and UserData() return the needed *snippet* of markup to go in the DIV.

Ideally, you'd do this latter through simple nested template so that *no* HTML was in your code proper.

Darren on February 5, 2009 10:58 AM

Treating HTML or XML as a big string or text stream or file or whatever is Doing It Wrong. It's an easy tree. Declare a bunch of objects, let them figure out how to output text to a TCP socket or to a file or whatever.

Reed on February 5, 2009 11:00 AM

The current version of ECMAScript also supports inline XML, almost identical to what you describe (they call it E4X); it works in Firefox 3, and also in ActionScript, the language used by the Flash player. For example, try this in Firefox 3:

html
head script
function gethtml(name) {
return pHello, b{name}/b/p
}
/script /head
body
button onclick=document.write(gethtml('Jeff'))click here/button
/body
/html

Mike Morearty (Adobe) on February 5, 2009 11:02 AM

I think the best circumstance is to just have the designers write html, since that's what they can handle, and then they can give it to you and you make it actually work.

The language you prefer to use to add the actual content is an issue of preference, a BIG preference, but the idea that any of them are the best is silly. They all have too many problems to be the best.

Practicality on February 5, 2009 11:06 AM

You're still doing it wrong, since you are NOT ESCAPING THE GOD DAMN TEMPLATE SUBSTITUTIONS. Someone sticks a script in one of the input paths you forgot to validate and your users are fucked.

Ironically, XSLT solves this problem (unless you concatenate XML, too, instead of using DOM, XLinq or XmlTextWriter to write the data XML).

DMB on February 5, 2009 11:08 AM

@Darren, Mike Mohearty
Both of yours' and just about everyone else's solutions I've seen so far still all look like the original tag soup Jeff started with. The thing is that Jeff's latest example eliminates the tag soup property but your solutions don't.

o.s. on February 5, 2009 11:16 AM

More comments»

Verify your Comment

Previewing your Comment

This is only a preview. Your comment has not yet been posted.

Working...
Your comment could not be posted. Error type:
Your comment has been posted. Post another comment

The letters and numbers you entered did not match the image. Please try again.

As a final step before posting your comment, enter the letters and numbers you see in the image below. This prevents automated programs from posting comments.

Having trouble reading this image? View an alternate.

Working...

Post a comment

Content (c) 2009 Jeff Atwood. Logo image used with permission of the author. (c) 1993 Steven C. McConnell. All Rights Reserved.