Jeff Atwood’s latest post (at the time of writing this) talks about mixing HTML markup and server-side code, àla
<table> < ?php foreach($foo as $bar): ?> <tr> <td>< ?php echo $bar; ?></td> </tr> < ?php endforeach; ?> </table> |
He also throws in the question: Is there a better way? – However, it seems there’s at least as many ideas of a better way as there are programmers…
Three categories
I think most of the solutions offered seem to fall in three categories:
- Embedding <language> code in HTML
- Template engines
- Using helpers/controls
Advantages and disadvantages
All of the above have some good points and some bad points.
Embedding the language, template engines and XSLT
Generally speaking, template engines are similar to embedding x-language code but more restricted. As I mentioned in my previous post, this restriction may help in keeping things separate from the rest as you can’t glue in non-view code.
On the other hand, it may turn a common task into something tedious because the template engine guys didn’t think of it.
As we can see from the examples in the Coding Horror blogpost and the one in this, most template engines and embedding the language are exactly what the “problem” is: it makes HTML more confusing and so on. Note I quoted the word “problem” since this isn’t necessarily a real problem – it’s merely a disadvantage of this approach, and with some good use of white space it can be quite readable.
I think we can group XSLT under template engines, since it functions in a somewhat similar fashion. XSLT might be an answer, since it avoids the issue of putting in non-HTML tags, but is XSLT actually any more readable?
XSLT tags are usually quite long, and you would essentially be mixing XSLT and HTML, possibly ending up with a quite confusing mess. However, there are XML editors that are capable of editing XSLT as well, which can make the task easier. With XSLT, you would also have to learn a new language, which is a lot more complex than most template languages. XSLT also may impact performance slightly, since you have to apply the translation before it can be sent to the client, though modern browsers can also perform the translation themselves on the client, so you can simply push them XML and tell what XSL translation to use, which may in some cases even speed up page rendering time.
XSLT does still have one advantage no other approach does: It is the only approach that’s fully portable as-is. XSLT works the same in most programming languages, so if you decide (for whatever reason) to change from say PHP to Java or .NET, you should still be able to utilize your XSLT files.
There’s also an in-between option: XML based template engines. For example, PHPTAL lets you use syntax like this:
<ul> <li class="listing" tal:repeat="item items" tal:content="item"> Default value </li> </ul> |
The above would loop over $items array and assign each value to $item, which is then outputted into a li like that. This kind of templating avoids messing up the HTML, but it’s again a new language to learn, or at least a new set of attributes. It is possibly the cleanest option.
Helpers and controls
The idea with both is basically the same: Build HTML programmatically, so you won’t have to write it yourself.
Helpers are usually more lightweight than controls: They simply output some specific HTML snippets, while controls may display something bigger such as a complete calendar, and maintain its state between reloads.
Depending on the flavor, they are usually either custom tags or just outputted with a snippet of… you guessed it, template code or just code.
While they can perform quite large tasks with very little code, they can cause problems when you want to change the markup they generate. Since they are generating in inside the class methods/functions, you would need to change those or create a child class. The code inside the classes may even be worse than the clutter caused by template code, since not all languages let you write strings in multiple lines and embed variable names inside them etc.
Controls and helpers can, however, be useful for a specific project. With them, it should be easier to maintain a specific look on all pages, since you would use them to generate most of the markup, so changes would also affect most pages.
Others
There are also some other approaches for tackling this problem. One is HAML, which is essentially an abstraction of HTML, aiming to make everything nicer and easier to read… the result is a weird mess of characters, see the HAML example in Wikipedia.
There’s also a library for Ruby called Amrita. Amrita uses CSS identifiers in the HTML markup to assign data to the correct elements, which I think is a very elegant idea. You can keep the logic in your controllers, and keep the HTML markup free of clutter. As a bonus, you can assign CSS styles with the ID’s.
Conclusion
It’s very difficult to say what’s the best approach.
If you want to look at pure code-related features, XSLT is possibly the winner: It’s a general purprose language not just limited to this task, it can be used in other languages, it can be rendered on the client possibly speeding things up. However, from the standpoint of someone who has to write/read it, it may not be as great, and it is an extra step with complexity.
ASP.NET style controls are good for containing things that use much logic, but if you want to change the way they output themselves, you may be in for some trouble.
Embedding code/template stuff into HTML can be thought of a two sided sword: while it can make things ugly, it’s easy to modify since you would use them in a similar manner as plain HTML files. It also doesn’t hide away anything: you can immediately see what kind of markup you’re going to get, unlike with controls where you would need to go look at their source code or the resulting page.
For the two other approaches I’ve mentioned, HAML and Amrita, Amrita is probably something that could prove to be very useful in separating code from content. HAML on the other hand seems like a bit pointless abstraction of HTML – is HTML really so annoying to write that you’d need something like that?
In the end, I think this may very well be one of the things like Vim vs Emacs, Tabs vs Spaces… A matter of opinion. Of course, you are free to try pointing out why your way of doing it is superior, but I think you’ll have a hard time thinking of good points that outweigh all others.