Web Development as Tag Soup
codinghorror.com
codinghorror.com
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.
(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).
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.
Check out ParenScript (http://common-lisp.net/project/parenscript/).
renderContentOn: html
50 timesRepeat:
[ html div
class: #SomeStyle;
onClick: (html element hide);
with: 'Who needs HTML?' ]- embedding client-side markup as a DSL in the language to generate HTML (Markaby/Seaside)
- component/control-based systems (ASP.NET, JSF I guess)
I prefer the first.
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.
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.
Overall, I guess web development is always ugly :-(
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).
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.
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).
It's "Markup as Ruby". Quite an elegant hack I must say. :)
From what I understand, that super-impressive Dabble DB demo used Smalltalk and Seaside. Have you seen it?
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.
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
x.html {
x.head
x.body {
for i in 1..5 {
x.div(:id => i) {
"yo"
...but my designer likes the templating stuff better. With a good IDE, it does become pretty easy to tell the code from the template.