There is a good post on Loud Thinking regarding Rails and its lack of a “templating” language.. which was one of my inital - I hate to use the word - complaints.
While I think that Ruby is certainly much better suited for co-existing inside the View than Java, I still think the approach that Tapestry uses (or even JSF) is preferable. It provides a nice decoupling in addition to helping during the prototyping phase. Of course, in most of my projects thus far, I’ve worn both the developer and designer hat—so I can’t speak to 37 signals’ workflow.
I stand by my claim that the less code in the HTML-portion of the View, the better—regardless of how readable the code is.
Update Read below for more thoughts on this—I tried to post this as a response the comments, but the HTML formatting was just too screwy…
When
I think templating, I think of Tapestry, so here goes: Let’s say I have a table that I want to populate. During the prototyping phase, I create the
HTML for the table in put in some mock-up data:
<pre><code>Employees.html
<table id="employees" jwcid="employees">
<tr><th>Id</th><th>Name</th><th>Position</th></tr>
<tr>
<td>123</td><td>Joe Smith</td><td>Programmer</td>
</tr>
<tr>
<td>456</td><td>Bob Jones</td><td>Designer</td>
</tr>
</table>
</code>
So far, it’s all
HTML - no code. The only thing that stands out is the “jwcid” attribute - that’s what ties the
HTML table to the implementation. Now, in Tapestry, there’s a page specification that corresponds to the
HTML page:
<pre><code>Employee.page
<component id="employee" type="contrib:Table">
<binding name="source" expression="employeeList"></binding>
<binding name="columns" expression="id,name,position"></binding>
</component>
</code>
In the Java code behind the page is a function, “getEmployeeList” that returns a collection of Employee models. The page, in turn, knows to use the id, name and position properties for the columns of the table. That’s it! And, we can leave the mockup data in place—everything between the opening and closing table tags is replaced at run-time.
Of course, this is a high-level explanation, but as you can see: there’s no code in the HTML and the View code itself just returns a List, it’s not concerned with how it is displayed, e.g. table or list or just a bunch of paragraphs! That’s pretty good decoupling! And it’s great during the prototype phase because you can tweak the layout (including mock-up data) outside of the application server and/or using WYSIWYG tool. And, even better, no major modification is necessary when the time comes to “wire” it up.
Lastly, to demonstrate your Rails example:
<pre><code>< % if @user.is_administrator? %>
# show stuff that's only for administrators
< % end %>
</></></code>
In Tapestry:
<pre><code>.html
<div jwcid="adminStuff">
stuff for admins only
</div>
.page
<component id="adminStuff" type="Conditional">
<binding name="condition" expression="isAdmin"></binding>
</component></code>
This is different from templating technologies like
JSP or Velocity and is probably more akin to Perl’s
HTML::Template.