Showing posts with label templating. Show all posts
Showing posts with label templating. Show all posts

Wednesday, 13 March 2013

Mason - A Template system for us programmers

Templating Modules are a bit like editors. Every web application developer has a favourite one. And every template system is someone's favorite.

Mine is Mason. But not because the Perl MVC tutorials are full of examples using Mason. Not because it's the fastest (use xSlate if you want to trade speed for flexibility). Not because it's the most popular. It's my favourite for a very plain reason: It makes me more productive and allows me to develop web GUIs using all the powerful features a programmer should biterly miss if they are taken away. That includes writing Perl code :P

I never heard of a business that went down because they didn't have fast enough CPUs, so I'm not fussy about trading a few CPU cycles for elegance, ease and speed of development.

Enough talking. Here's my contribution to the template holy war and Mason lobbying presentation:

Saturday, 2 March 2013

The only bad thing about Mason

At the moment, I'm writing a presentation about Mason2. The goal is to somehow convince my colleagues to consider using Mason. Instead of Template Toolkit.
As part of it, I thought I'd do a bit of performance benchmarking against Template Toolkit. So I put together a reasonably complex mini set of templates using both systems. Well, as complex as TT can take in reality. Which is not very much.

But anyway, let's jump straight to the bad news.

        Rate Mason    TT
Mason  901/s    --  -51%
TT    1852/s  106%    --


As you can see, with similar settings (code caching enabled) and over 10000 runs of two pages, Mason2 is twice as slow as Template Toolkit. Mason2 is still below the millisecond per page in my benchmark, but still that's quite a big difference.

As the common wisdom goes, CPU time is cheaper than programmer time, so it shouldn't be a big deal, given the huge gains of productivity you should get by using Mason2's very cool and powerful features.

Stay tuned for the full presentation to come!

PS: To follow up on the comments, feel free to have a look at the benchmark source https://bitbucket.org/jeteve/mason-pres/

J. 

Monday, 21 February 2011

Slice your HTML to Ajax anything. [Part 1]

There's roughly two ways of addressing Ajax on your website:
  • Designing your pages with Ajax in mind. This usually means you'll have a  growing number of features that require JavaScript to work. The W3C recommendation specifies that you should provide JavaScript-less versions of your features. So it means you will have to develop your features twice to maintain accessibility. Sounds a painful thing to do.
  • Designing your pages without Ajax in mind. This means you design only good old pure html/params & forms techniques to animate your features. This is good for accessibility, this is good for testability, this is good for search engines because all your features are accessible via plain links. The only problem is... well there's no Ajax coolness.
But we're going to fix that, and it's not going to be painful at all providing you:
  • have got zero business logic in your rendering layer. Meaning each part of it is idempotent. This is hopefully the case when you use a MVC model for your application.
  • use a rendering layer that's capable of manipulating its buffer, and renders the whole page in this buffer before sending it.
For this post, I'll be using Catalyst as the MVC and HTML::Mason as the View layer. We'll focus on implementing Ajax results paging. (Other ajax aspects will be dealt with in later posts).


Principle of ajax page slices.

The idea of page slices came to me when I was looking at jQuery's load function. It's got a very convenient trick called 'load page fragments' that allows you to do stuff like:

$('#container').load('page_url?offset=2 #result_id');

It will look for an element having the id 'result_id' in the returned document and replace the content of #container with it. Here's a full example of html/javascript that implements this:

<div class="container">
 <div class="result" id="result_id">
   <p>This is page 1</p>
   <p>item 1</p>
   <p>item 2</p>
   <a class="page" href="page_url?page=2">Go to page 2</a>
 </div>
</div>
<script>
 $(document).ready(function(){
    $('a.page').live('click',function(e){
        var a = $(e.target);
        var result = a.closest('.result');
        var container = result.closest('.container');
        container.load(a.attr('href') + ' #' + result.attr('id'));
    });
 });
</script>

This does the trick on the client size but it doesn't save much time on the server side.
Plus it requires DOM parsing of the whole document to find the result_id element. Altogether, chances are that your ajax paging will be slower that a simple whole page reload. To fix that, we're going make the server output only the required slice for us.

Let the server do the work.

First let's have a look first at the intended client side code:

<div class="container" id="result_id">
<!-- This is the slice 'result_id' -->
  <p>This is page 1</p>
  <p>item 1</p>
  <p>item 2</p>
  <a class="page" href="page_url?page=2">Go to page 2</a>
<!-- End of slice -->
</div>
<script>
 $(document).ready(function(){
    $('a.page').live('click',function(e){
        var a = $(e.target);
        var container = result.closest('.container');
        container.load(a.attr('href'), { page_slice: container.attr('id') });
    });
 });
</script>

On the server side, we need a technique to output only the required slice, discarding any previously generated HTML, and aborting the rendering so no more subsequent HMTL is rendered. In Mason, this is easily done by implementing a content wrapping component.
Here's how it looks in under Catalyst (the $c bit):

Component page_slice.mas:
<%args>
 $slice_id 
</%args>
<%init>
  my $requested_slice = $c->req->param('page_slice');
  if( ( $requested_slice // '' ) eq $slice_id ){
    # Discard any previously generated content,
    # output the content and finish rendering
    $m->clear_buffer();
    $m->out_method->($m->content);
    $m->abort();
 }else{
    # This component is transparent
    $m->out_method->($m->content);
 }
</%init>

Here's how to use this component in your page.mas:

% deal with param('page') to compute results and next page.
<div class="container" id="result_id">
 <&| /page_slice.mas , slice_id => 'result_id' &>
  <!-- This is the slice 'result_id' -->
% # Output the right results
% ...
  <a class="page" href="page_url?page=<% $next_page %>">Go to page <% $next_page %></a>
  <!-- End of slice -->
 </&>
</div>
<script>
 $(document).ready(function(){
    $('a.page').live('click',function(e){
        var a = $(e.target);
        var container = result.closest('.container');
        // Use the container ID as the slice ID.
        container.load(a.attr('href'), { page_slice: container.attr('id') });
    });
 });
</script>


When clicking a '.page' link, a request will be sent with the param 'page_slice'. Thanks to this, the component page_slice.mas will output only the requested page slice, and this will populate the container.

Your paging will obviously works without JavaScript. There's no Ajax specific code at server side. This is:
  • Good for accessibility. Try using your paging with lynx. It just works.
  • Good for SEO. Our beloved search engines will crawl these links, even if they don't do Ajax.
  • Good for testing. Because Ajax is not needed to use your application, you can easily unit test your features from your web test suite.
  • Good for reliability. If for some reason your JavaScript is broken, the feature will still be available.
Of course this technique can be applied to any kind of browsing features: sorting, faceting etc..
Next time we'll discuss performing an action in Ajax, and managing Ajax redirections.

I hope you enjoyed this post, thanks for reading!

Thursday, 6 January 2011

Perl: Avoiding the HTML::Mason/TemplateToolkit schism

As a Perl web developer, I've been using HTML::Mason intensely for many projects. Over the past year, I've also been working with Template Toolkit as a rendering layer for a web application.

As always, choosing between two similar technologies seems to be mainly a matter of taste and yet another occasion for an holy war. To pacify the situation, let's try to figure out what are these beasts good at.

TT feels more simple.

Consider the following code:

[% IF customer.is_in('GB') %]
We'll ship your order by Royal Mail
[% ELSE %]
Sorry [% customer.firstname %], delivery will take a while.
[% END %]

It's much easier to understand for a non-programmer than the Mason equivalent:

% if ( $customer->is_in('GB') ) {
We'll ship your order by Royal Mail
% } else {
Sorry <% $customer->firstname() %> ...
% }

So here clearly, TT wins, although as a programmer, and specially as a Perl programmer, Mason also feels just fine. However, a designer or a configuration person will feel more at home with TT, as it resembles infamous visual basic excel macros.

Mason simplifies page composition.

Let's implement a set of pages, each with a specific title and content, but with the same structure (here just a navigation box). In fact the common bread of web development

Let's do it in HTML::Mason:

autohandler:
<html>
 <head>
  <title><& SELF:title &></title>
 </head>
 <body>
  <div id="nav_box">...</div>
  <div id="payload">
% $m->call_next();
  </div>
 </body>
</html>
<%method title>A default title</%method>

content1.html:
  <p>content 1</p>
  <%method title>Page Content 1</%method>

content2.html
  <p>content 2</p>
  <%method title>Page Content 2</%method>

etc..

Now let's do it TT:

page:
<html>
 <head>
   <title>[% title || 'A default title' %]</title>
 </head>
 <body>
 <div id="nav_box">...</div>
 <div id="payload">
  [% content %]
 </div>
 </body>
</html>

content1.html:
[%WRAPPER page
          title = 'Page content 1'
%]
 <p>content 1</p>
[%END%]

content2.html:

[%WRAPPER page
          title = 'Page content 2'
%]
 <p>content 2</p>
[%END%]


From a programmer's point of view, HTML::Mason wins, as its inheritance mechanism allows much better simplicity, elegance and flexibility in page composition. In this example, I only considered a simple example that's possible to implement both in Mason and in TT, but for more advance use, the inheritance mechanisms (with call to PARENT (super) methods), and other Mason-isms largely beat the TT WRAPPER directive.

❧

From these two simple examples, it appears that HTML::Mason has got much more to offer to programmers, as it allows them to use Perl natively, use a fairly complete inheritance mechanism, and much more. On the other hand, what TT has to offer is definitely an easier and simpler solution for simple templating jobs.

To sum up:

- Use Mason where you need elegance and simplicity to build complex things.

- Use TT where the 'easier than Perl' feel is important, with a restricted set of directive to build simple things.