12 Apr 2005, Rodrigo Barnes, rodrigo [at] kaleak.net
Most scripting languages for web applications are either client-side scripting (i.e.g JavaScript and variants) or templating languages on the server side, providing streamlined ways of generating HTML (and variants). This is a very quick fly-by of some the common approaches used in HTML generation scripting languages.
In what follows, the view is the part of the technology stack/combo that is closest to being streamed to the client (browser). Typically this is JSP, a template, or a PHP script.
xOne thing to remember is that it you look closely, most of what is being done in the Java space was already done in the Perl space. Essentially you get the following:
This is usually the starting point when a separation is sought between CGI scripts and presentation.
- Java: Velocity
- Perl: Text:Template
What usually happens in these systems is that a Hashtable is populated with variables that are going to be needed when rendering the view.
Sample (from Velocity documentation):
#if( $foo || $bar ) <strong>This OR That</strong> #end
Later iterations of J2EE web scripting have come back to this, with the introduction of the standard template library JSTL, which unfortunately doesn't allow proper method calls, just JavaBean accessor calls.
This style allows delineated blocks of the programming language to be interspersed with HTML. While you can often see the logic of presentation quite clearly in this style, in practice, this style is too expensive to maintain. It really does make sense to separate views from control!
- Java: old-school JSP
- Perl: ePerl, HTML::Embperl
- Windows: ASP, ASP.NET
- most of PHP and the like
Sample:
<% String username = request.getParameter("username"); if ( username != null && username.length() > 0 ) { %> Hello <%=username%>! <% } %>
The original CGI.pm library in Perl, and Java servlets tended to operate in a way that you had a code-oriented script, where an HTML document was constructed by appending elements to a buffer or an object tree, which would then be rendered. This suffers from the same level of mixing of code and output as scriptlets.
Sample (see perldoc cgi on an up-to-date Perl system):
use CGI qw/:standard/; print header, start_html('A Simple Example'), h1('A Simple Example'), start_form, "What's your name? ",textfield('name'),p, "What's the combination?", p, checkbox_group(-name=>'words', -values=>['eenie','meenie','minie','moe'], -defaults=>['eenie','minie']), p, "What's your favorite color? ", popup_menu(-name=>'color', -values=>['red','green','blue','chartreuse']),p, submit, end_form, hr; if (param()) { print "Your name is",em(param('name')),p, "The keywords are: ",em(join(", ",param('words'))),p, "Your favorite color is ",em(param('color')), hr; }
Design strategies and application architecture inevitably affect the style of scripting used.
Some design strategies help to enforce the separation of data (Model), presentation (View) and logic (Controller). This would allow you to choose the view technology (templates with Velocity, for example), while making the logic easier to unit test (using JUnit and mock objects, for example).
The Apache Cocoon system uses XML and XSLT to generate various forms of output (PDF, HTML, WML etc), based on one intermediate XML document.
Current versions of JSP encourage the use of custom tags and tag-based logic, so the view code looks more like straightforward XML.
A number of systems essentially provide a binding mechanism from database directly to the view. So they provide custom tags in JSP that bind to a database object (connection, table etc) defined elsewhere and provide standard ways to tabulate in HTML, sort, filter etc.
Often these strategies are chosen based on the availability of developers. If you only have HTML programmers, then stuffing the view with clever tags is a good strategy. If you have to develop a modular system for customization later, then strict MVC and unit tested Java code is a good idea.
Problems arise when a technology is developed that assumes simple architecture and so fails to allow for more complicated deployment scenarios. Traditional CGI tended to spawn a separate process that built everything from scratch, processed, and output with no reference to pooled resources, or shared data. Scripts could have all sorts of concurrency issues.
Some frameworks allow you to separate your concerns further by having aspect oriented features. You can designate code to run at different stages in the CGI pipeline across a number of components (See Spring for examples of this). These tend not be 'scripted' in the same way, though I think there's an argument for introducing customization via technology with less of a learning curve into these areas.
A notable recent re-introduction which brings JavaScript back into the discussion, is the use of client-side rendering on a big scale as seen in a number of Google offerings (gmail, google maps). These build a lot of the page up from client side scripts (JavaScript gives access to the object model of the HTML, DOM). This has been done before, but Google have made heavy use of pulling XML output into the document via RPC calls from the JavaScript. The effect can be quite good, though I feel it suffers from the code-mixing issues outlined above.
Perl Survey: http://perl.apache.org/docs/tutorials/tmpl/comparison/comparison.html
Jakarta Velocity: http://jakarta.apache.org/velocity/
Cocoon http://cocoon.apache.org/
Spring Framework http://www.springframework.org
Google Suggests http://www.google.com/webhp?complete=1&hl=en