Most projects that use a template based approach to layout end up looking like this. The example in the article is relatively straightforward, in my experience. Things get even uglier when your hot AJAXy javascript gets tossed into the template.
We ended up here because for the past 10 years the imagined process for web app development was that you had a programmer working on the "back end" and this back end spit out stuff to some templates, which a "web designer" could modify when you wanted to change the look and feel. Rails is a project started by people coming from the web design world, so the default approach is to use the typical division between back end and templates.
The workflow which splits things into back end + html templates, with differently skilled people productively contributing to each side of the app doesn't exist in reality. You'll eventually need some logic in the template. The web designers don't want to modify a template filled with logic, so what happens is the programming team gets "wireframes" from the designers, and then modify the templates themselves.
If you're a programmer, and you prefer to generate your html programatically, there are many tools that do this. A few have been mentioned already: seaside, markaby. This approach is great if the programmers have control over the development process from the back end to the front end. However, if you are working with an existing team, you've got 10 years of process inertia fighting against you. Thus, as is the usual answer on Hacker News, your best bet is to start your own company where you can apply the tools and processes with which you are most effective.
One advantage to the tag soup approach is that you can just take the templates the designer gives you. Usually they have been created with some WYSWG-software like dreamweaver and contain hundreds of nested tables and divs. Translating all that to a completely different language would be a nightmare. Much easier to identify the parts you have to manipulate programmatically and leave the rest of the code alone...
(This goes mostly for client projects, for my own projects I might have other standards. Although in fact for my moon calendar web site, I ended up doing the same).
The traditional view is that HTML is a messy presentational format with lots of repeated boilerplate and lots of subtle gotchas in the syntax.
In that view, it makes sense to separate HTML from the logic into templates, where the markup is basically handled as opaque strings by the template engine.
However, with semantic markup, each HTML element actually have a functional significance. The HTML is now the model, not the view.
This does not solve the labor division problem you describe, rater it turns it into a completely different problem. Now HTML is basically the domain of the programmers, and CSS (and perhaps some amount of XSLT) is the domain of the web designer. It it still not clear to me how these should work together.
The answer is a language that can use a unified syntax for both generating markup and server-side functionality at the same time. There's probably only one candidate at the moment, and that's Lisp with a special set of macros that translate to HTML tags on output. The beauty of it is that S-expressions nicely map to markup and can execute stuff on the server. This macro library does exist and I think I saw it here at YCnews. It was a video and unfortunately I can't find it now.
There's one bit missing in this solution though: the client side. Can Lisp be translated to JavaScript? Something suggests that's perfectly possible.
Lisp is hardly the only answer. Smalltalk does this just fine in the Seaside framework, which threw out templates to get rid of this exact mess. We write our html, server side code, and client side ajax code pretty much entirely in Smalltalk.
renderContentOn: html
50 timesRepeat:
[ html div
class: #SomeStyle;
onClick: (html element hide);
with: 'Who needs HTML?' ]
What I don't like about this approach is that it forces me to learn a new language just to create HTML. I don't mean Smalltalk, but the specific "HTML generation API".
I have to know HTML anyway (because eventually I will have to debug it), so it seems preferable to me to also code the output in HTML.
Another approach against tag soup I have seen is xmlc, which manipulates the DOM tree of the HTML template. The xmlc project doesn't seem to be very active anymore, though.
Every web framework uses some sort of template engine. You're going to need to know the way it works and what syntax it uses and any gotchas that are there.
Also, the logic is going to bleed over into the HTML anyway. Why burden yourself with ugly line noise?
renderContentOn: html
50 timesRepeat:
[ html div
class: #SomeStyle;
onClick: (html element hide);
with: 'Who needs HTML?' ]
vs.
<% for x in range(50) %>
<div class="SomeStyle"
onclick="javascript:hide(this);">
Who needs HTML?
</div>
<% endfor %>
In the above example, I'm mixing the JavaScript with the HTML and I also see Python code (the last template engines I've used were Python-based). Three languages mixed into one template.
The Seaside/Smalltalk example, on the other hand, has one language with code that generates another language (which I don't have to touch at all, it knows how to generate a valid DIV element). So I just have to analyze the logic of the Smalltalk code and not the HTML or JavaScript unless there is a specific reason for me to do so (such as adding a new type of HTML element).
Just curious: how is xmlc not an extra "HTML generation API" that you have to learn?
I mean, it seems we're stuck here. Either we use tag soup templates, or we use some abstraction to express the structure of the page in the language of the generator code. The former requires less training and discipline, but complicates maintenance. The latter is a framework to which you'll need to adhere. No free lunch.
You have a point. I guess whatever you do, you need something to output HTML, and something to code logic. What I like about xmlc is that it stays within the standards. DOM is maybe too much to know for HTML developers, but still. It actually worked quite well to have "designers" create HTML templates and manipulate them in the servlet. The designer doesn't need to know anything but HTML, except that he has to use id tags where values in the template have to be manipulated.
Overall, I guess web development is always ugly :-(
Seaside also has components. But they aren't as brain-dead as the ones in ASP.NET. It's much cleaner and better-designed (I haven't dug into Seaside completely yet, but so far, very clean)
macro-based alone doesn't imply one approach or the other, or does it? There could be macros for all the HTML tags (table => <table>), or there could be macros for "widgets".
And 20 years from now, when Microsoft releases an ASP.NET with the better way ("say goodbye to templates with the new Unity Code Components (UCC)™"), Atwood will be blogging about it.
Edit: Jeff is no doubt a nice guy and it's clear he means well. Yet every time I read his stuff I feel driven to burst out with sarcasm. I think it's an allergic reaction: I know the world he represents, I spent too much time in it for my own good, and now I'm hypersensitive.
Another option: get a language where markup itself is first-class syntax. JavaScript with E4X has XML built-in, which of course means XHTML if you like, which itself can be trivially translated to HTML if you prefer (as I do).
So just like regular expressions have first-class syntax, i.e., in JavaScript you can write either of:
myRx = /somePattern/g;
myRx = new RegExp('somePattern','g');
So with E4X you can write either of:
greeting = <b>Hello, {user.name}!</b>;
greeting = new XML("<b>Hello, "+user.name+"!</b>");
Though those really aren't equivalent since the second might be a XSS vulnerability, whereas the first is automatically escaped.
E4X only works in Mozilla-based browsers, but it also works just fine in Rhino, so you can use it in Helma (http://helma.org/) or any of the other Rhino-based frameworks or in Jaxer (http://aptana.com/jaxer).
F# and the WebDevelopment toolkit offers one language (OCaml) that can be used both client and server-side, including continuations and such across the client-server boundary. The OCaml code translates seamlessly into JavaScript.
Mixing HTML-generation and logic, no matter how nicely the languages mesh together, is still a mess. This is coming from someone who's done a few sizeable Common Lisp projects using tools like YACLML and CL-WHO, and then went back to using separate templates for HTML-generation. I'm not sure what Atwood is going on about in this article (probably he just felt he needed to write something, anything) -- separating out views/templates is not really much of a challange in my experience.
The code will not really be simpler just because you turn the pointy brackets into round parentheses. It would be made simpler however, by separating concerns: abstracting presentational and styling info from data. You can do that in any framework.
He is using convoluted presentational HTML interleaved with logic. This makes it a mess. For example, the upper half of the code seem to be some kind of tabular data, while the lower half seem to use table-markup without any reason at all. This could be made much simpler by using clear semantic markup. He is even mixing style info into the HTML by using things like and class="gray" - this shows a complete misunderstanding of the concept of separation of content and presentation.
Now, there may be legitimate reasons why you would use presentational markup - e.g backwards compatibility with old browsers, or very complex layout or effects. In that case a transformation should be done - using XSLT, custom tags, or whatever is appropriate for the framework. This markup transformation should be separated from the logical markup just like CSS is.
The code is a bit ugly too - the f and c variables see to be used to switch styles for the first row and for every other row. Again, this is presentational and should be handled by CSS or some kind of transformation system.
Lots of comments suggest that the code could be improved by using round or square brackets instead of pointy bracket. This does nor really reduce the complexity though, the important thing is to simplify by abstracting styling and layout away from logic and structure.
In order to put data into the output format you have to have some form of tag soup because that's the only way to put information and display logic into HTML.
The question in my mind is more, are you a developer or web sites or a developer of tools.
Something like .net components or JSP taglibs allows the developer to off load data/widget to a tool developer by just calling a widget.
The two problems I see with that a) historically the people building a lot of those widgets produced markup that _sucked_ b) it's kinda inflexible
We ended up here because for the past 10 years the imagined process for web app development was that you had a programmer working on the "back end" and this back end spit out stuff to some templates, which a "web designer" could modify when you wanted to change the look and feel. Rails is a project started by people coming from the web design world, so the default approach is to use the typical division between back end and templates.
The workflow which splits things into back end + html templates, with differently skilled people productively contributing to each side of the app doesn't exist in reality. You'll eventually need some logic in the template. The web designers don't want to modify a template filled with logic, so what happens is the programming team gets "wireframes" from the designers, and then modify the templates themselves.
If you're a programmer, and you prefer to generate your html programatically, there are many tools that do this. A few have been mentioned already: seaside, markaby. This approach is great if the programmers have control over the development process from the back end to the front end. However, if you are working with an existing team, you've got 10 years of process inertia fighting against you. Thus, as is the usual answer on Hacker News, your best bet is to start your own company where you can apply the tools and processes with which you are most effective.