Callender (2002) Perl for Web Site Management, O'Reilly, Sebastopol

John Callender's Perl for Web Site Management professes to adopt the laudable aim of presenting, not Perl itself, but a variety of techniques for getting your job done. The particular set of jobs in question relate to storing and managing collections of data on web sites — and, since Perl is an excellent tool for accomplishing such jobs, Perl is the vehicle that Callender chooses.

This seems a very wise approach. There are currently many people in the position of having to babysit one or more websites, but whose background is in some field other than an explicitly technological one. These people tend to find themselves in one of only two positions, neither of which is desirable:

A generic programming tool such as Perl can offer solutions to these problems, but the difficulty here is that there is little or no guidance available that informs non-programmers on how to get the best out of Perl.

Enter John Callender.

Callender's book is explicitly aimed at proficient computer users who are typically from a Windows or Macintosh background, and who find themselves needing to use Perl (especially under Unix) to get stuff done on the web. It assumes that the reader has a basic understanding of web technologies, and now needs (or wants) to extend his or her abilities to include larger websites, especially those that require some degree of automation or server-side scripting. It doesn't aim to teach programming; on the contrary, Callender recognises that learning to program is a an undertaking which cannot be accomplished quickly. That said, though, Callender must make some nod to describing programming techniques in order to make his examples comprehensible.

The text is organised around a number of comparatively large examples, each of which demonstrates some real-world problem and a possible solution. These examples do indeed have obvious applications to building large websites; he discusses, among others:

Callender claims that all the examples are based on actual programs that he has written for real websites, and this claim is entirely believable. Certainly this approach of presenting the material through the medium of the reader's problem domain, rather than that of Perl, the solution domain, is one I whole-heartedly endorse. My experience teaching Perl training courses in the UK for GBdirect has shown time and again that students pick up material far more readily when they can relate it to their daily work, or to a problem that they have already encountered.

Sadly, however, it seems that in few cases does Callender present the easiest ways of getting your job done. In particular, he seems to reinvent any wheel he can lay his hands on. One of the distinguishing features of Perl qua culture is CPAN, the Comprehensive Perl Archive Network. CPAN is an enormous archive of (among other things) ready-to-use, off-the-shelf modules of reusable code for accomplishing — well, almost anything you can think of. Given the perception of Perl as ‘the language of the web’, it is unsurprising that there are many CPAN modules which perform web-related tasks. We might expect, therefore, that much of Callender's text be a presentation of how to get the most of the available CPAN modules.

Unfortunately, this does not seem to be the case. There are several occasions where the task Callender is describing is precisely one solved by a CPAN module. For example, Callender's chapters 8, 9, and 10 present a detailed example of extracting information from Apache log files. He uses Perl's flexible input/output facilities to read in each line of the log files, and parses each line with Perl's powerful regular expressions. This is all very well, but there is a convenient CPAN module named Apache::ParseLog which does the parsing (correctly handling the Apache web server's CustomLog/LogFormat directives) and can even do some analysis work. Writing equivalent code to do the same tasks does not seem like a good way of ‘getting one's job done’.

This is not the only example of this sort. In another large example, Callender demonstrates the use of a templating system for generating HTML in a large web site. Callender's earlier examples of generating HTML from Perl code involve simple print statements to write out HTML tags and text. Consistent use of a templating system in a task like this promotes separation of the code that generates the actual content from the HTML that imposes a layout on the code. That separation is enormously valuable: it makes it possible to significantly change the look and feel of a web site without actually altering any of the code that does the real work. For example, for one project I have worked on at GBdirect, we needed to completely change the look of the site, very close to the delivery date. We were using the HTML::Template Perl module for templating. We spent a day designing the new look, and implementing that look in HTML 4 and CSS 2. Our use of HTML::Template meant that imposing the new look on the site took only half an hour.

With experiences like that, I was interested to see what Callender would say about using templates to generate HTML. There are many Perl modules on CPAN which provide some form of templating system; they adopt different philosophies, and to some extent therefore, the way one chooses to build a web site depends on the templating system in use. Callender presents a sidebar listing some of these various Perl templating facilities. I was disappointed, though, to see that the one he demonstrates in the body of the text is yet another home-grown instance. Many templating systems, including HTML::Template, deliberately avoid ‘programming’ features in the template language, while still allowing for loops to present lists or tables of information. Callender's, like many other such systems developed for one-off tasks, offers nothing more than simple variable substitution. While this is reasonable for his specific example, I feel it is a poor way of demonstrating good ways of ‘getting your job done’, especially given how many genuinely good template systems exist.

Even worse than this, though, there are some outright errors in the examples. The log analysis example must convert times in the well-known CLF format to a representation that can be used for internal calculations. Callender presents one version of this (using the standard Time::Local Perl module) that works perfectly correctly. He then presents an ‘optimised’ version that he has measured as reducing the time taken to process a given log file from 387 to 183 seconds. Unfortunately, in so doing, he introduces an error: the fast version of the code will give the wrong results during a daylight savings time switch.

Callender's material on ‘getting your job done’ is not, then, entirely satisfactory. Since, however, he must make some attempt to teach enough of Perl to make the ‘getting your job done’ material comprehensible, our next question is whether this material is any better. Fortunately, it is: Callender has clearly put a lot of thought into how to teach individual parts of the language, and how to present parts of the language in a context in which they can be readily understood. For example, many Perl texts describe how to write Perl modules as part of a larger reference section on packages, modules, and object-oriented programming in Perl. Callender successfully avoids this trap: he demonstrates a simple (non-OO) module as a way of sharing code relating to an entire project between several Perl programs.

This is one of the best things about Callender's book. All too many Perl books, even those which claim to be aimed at beginners, present Perl in the same order you'd find in a reference manual, describing (for example) all the operators in one place. Callender almost always manages to present just enough to be understood, and in an order which relates to the problem domain rather than the solution domain. Even here though, Callender manages to fall at some hurdles, and drops back to the tired order of presentation found in all the reference books. The material on regular expressions was particularly incongruous. He begins by demonstrating almost (but not quite) enough regular expression syntax for beginners to understand simple regexps. But at the same time, he describes in all its detail the rule about the use of backslashes in front of alphabetic or non-alphabetic characters in regular expressions. In chapter 7 he actually describes the remainder of regular expression syntax. Again, this is too much: there is such a huge amount that can be done with regexps that, in my opinion, this chapter becomes barely comprehensible to a beginner.

Conclusions

Callender's book is more successful than any other beginner's Perl text I have seen at actually teaching the language in an appropriate way. All too many Perl books are aimed at people who can already program proficiently in at least one of the languages that Perl draws heavily from. Callender's book usually manages to teach the language in just enough depth and in a sufficiently meaningful context for it to be understood by a beginner.

Callender also claims to present ‘Perl to get your job done’, and he does successfully present a variety of real-world techniques for web programming. However, though both the educative and the pragmatic portions of the text are at least as good as anything else I have encountered, it is my opinion that neither is as good as it should be. In summary: though Callender's book is worth buying, there is still a niche in the market for an author who can teach Perl appropriately.