< Coding Freedom | Russ Allbery > Reviews | In Pursuit of the Traveling Salesman > |
Publisher: | O'Reilly |
Copyright: | July 2005 |
Printing: | April 2011 |
ISBN: | 0-596-00173-8 |
Format: | Trade paperback |
Pages: | 492 |
I had a rather bad first reaction to this book — or, rather, the existence
of this book. Some time ago, I started hearing about a new program named
perlcritic that served as a lint program for Perl and decided to give it a
try. I was taken aback by the flood of diagnostics, but even more taken
aback by the fact that most of them were apparently explained only by a
reference to a book that I didn't own. It struck me wrong in an open
source project and gave me a negative reaction towards the book, which
lingered for years. That was exacerbated by discovering that it
recommended using use English
in some circumstances, something that
I consider to be a horrible idea. So, when a coworker recommended it and
suggested I really should read it, I was dubious.
I'm glad I gave it a chance, since it turns out that nearly all of my
objections were based on misunderstandings or false information. (Well,
except for the use English
part, but more on that in a moment.)
Perl Best Practices does provide a lot of advice, explaining
that flood of diagnostics, but perlcritic also warns about the same thing
repeatedly, inflating a handful of issues into a lot of messages. Most of
the recommendations in Perl Best Practices were things I was doing
already; most of the rest are entirely sensible. Also, perlcritic does
come with complete explanations of its diagnostics once you know where
they're hidden (the perldoc of Perl::Critic::Policy modules whose names
you can get at by insisting perlcritic divulge them). And, even more
delightfully, once I got past my objections, I discovered that Perl
Best Practices is one of the best books on coding style that I've read.
Coding style is a notoriously difficult subject, since nearly everyone is convinced their personal style is the best (or at least that they don't want to change). Conway acknowledges that up-front, and acknowledges that some things are just arbitrary and consistency with any rule set is better than following some specific rule set. He then spends surprisingly little time on the sorts of things that dominate most coding style discussions (indentation, spacing, commenting, etc.). Instead, this is primarily a book about how to write efficient and transparent Perl code, one that focuses much more on the content and structure of that code than on how it is indented.
The best part is that there are no undefended rules here. Perl Best Practices contains 256 separate guidelines, some quite general ("Provide an optimal interface, rather than a minimal one") and some quite specific ("Pass constructor arguments as labeled values, using a hash reference"), but every one of them has a supporting argument and specific reasons behind it. Conway backs up every recommendation with code samples and practical scenarios showing the pluses and minuses of different approaches. This is a book unconcerned with being an authority; rather, it reads like optional advice from a good mentor, complete with insightful discussions on each point raised. You may come away from it disagreeing with Conway's specific recommendation (and I did, in several places), but you'll almost certainly be better-informed about the problem for having read it.
Plus, this book is just fun to read. Admittedly, I love this sort of thing; I spend lots of time thinking about coding style in any language, and a lot more time refactoring coding style when working on my own projects to try to achieve clarity and simplicity. But even without sharing my love of the material, I think this book will be a delight for any practicing Perl programmer who hasn't yet read it. Conway clearly has a wealth of experience and years in the trenches of working with other people's Perl code. The examples he draws on are brief, comprehensible, and illuminating.
He also gave me a tour of a variety of helper modules and libraries that I
didn't know existed. List::Util is the most prominant example; this
incredibly helpful supply of list manipulation functions that I've always
half-known I wanted but never bothered to write is now part of Perl core
(as of 5.7.3), so there's no reason to avoid it. You too can stop using
grep
when you actually mean first
, or rewriting max
in ad hoc ways.
That does raise two of the rare flaws in this book, though. One is that I
disagree (partially) with Conway's willingness to recommend non-core
modules. He is a particular champion of the Readonly module over either
normal file global variables or use constant
, for very good
reasons. But making Readonly a prerequisite for all other Perl code that
one releases seems a bit annoying (speaking as someone who used to
maintain local Perl installations). Maybe this isn't as big of a deal in
these days of ubiquitous Linux distributions and willingness to use the
CPAN shell, but I still dislike releasing code that depends on a
half-dozen (or more) other CPAN modules for reasons of coding convenience
and minor readability rather than core functionality. (His advocacy of
Sub::Install raised similar objections.)
The second flaw is not something Conway could have done anything about:
this book is from 2005, and it's now 2012. Now, the Perl ecosystem is now
quite mature, so that hampers the book much less than it would a
corresponding book about Ruby or even Python. I also aim for
compatibility with the oldest thing out there I know someone is still
running, so I'm still hesitant to require anything newer than Perl 5.8.
But still, this book was written seven years ago, and Perl is now at 5.14.
In the meantime, we've seen core language features like
given
/when
added, the addition of state
variables,
the need for substantial reworking of how Unicode I/O is handled, the
addition of the new //
operator, and the new package
syntax,
among many other things. The Perl taught here is a bit dated, and I would
love to hear Conway's opinion about when (or if) to use say
. Maybe
someday we'll get a second edition.
There are two other points that I do have to argue with. One is that
Conway does advocate, in a limited way, use English
. I could
almost go along with his recommendation to use it only for those variables
that one has to look up, except that in nearly every case there are other
options and one can take the much better approach of simply not using
those variables at all. But he then writes the remaining examples in the
book using $EVAL_ERROR
rather than $@
, and I'm sorry, but
no. One could not construct a more frustrating annoyance for an
experienced Perl programmer than sending them on a futile hunt for where
the global variable $EVAL_ERROR
is defined. One can debate the
merits of Larry Wall's original decision to use variables like $_
,
@_
, $?
, $!
, and $?
, but for better or ill this
is Perl, and marginal readability gains for inexperienced programmers do
not warrant confusing experienced programmers. This is particularly true
when the use English
variables are completely indistinguishable
from normal global variables, and not infrequently look like a global
variable that a programmer might choose.
The second is more of an amusement that a real disagreement. Conway rightfully points out that Perl OO, and particularly the way that Perl stores object instance data, is awkward, and none of the commonly-used techniques are particularly satisfying. He then introduces a completely new way of doing instance data that, while having some advantages, has a very strange syntax and is utterly unlike how any OO code one finds in the wild is written. While the discussion of the problem that he's trying to solve is still interesting, I think the solutions he proposes will be more of a curiosity than a style that most programmers will adopt.
But, those disagreements aside, I thoroughly enjoyed this book. I found it so engrossing that I kept reading it straight through a long train ride rather than switching to fiction halfway, like I do with most programming books. I've since recommended it to several other coworkers, and we're in the process of revising our internal Perl coding style based heavily on it. It's the sort of book that I expect to re-read several times to refresh my memory of Conway's analysis.
If you've been avoiding this one due to misconceptions like I had, or because you think it might be too dry, or even just because you're afraid it's outdated, I strongly recommend it. If you're worried about the price of a printed (or electronic) book on this topic and you do Perl programming as part of your job, see if your employer will buy you a copy as training. It's worth it. I've been writing Perl professionally for more than fifteen years, and I learned a ton from this book.
(And if it inspires you to change your coding style, take a look at perlcritic. It requires some configuration, and getting started is quite frustrating, but it reliably detects a surprisingly high percentage of the issues discussed here and can help a great deal in making the coding style shift stick until you can build new habits.)
Reviewed: 2012-12-27
< Coding Freedom | Russ Allbery > Reviews | In Pursuit of the Traveling Salesman > |