- 1 Beginning
- 2 Writing Code
- 3 Observation
- 4 Documentation
- 5 Developing
- 6 Accident Prevention
- 7 Tips for Reducing Complexity
3.6 Accident Prevention
These tips fall into the category of installing sprinklers instead of polishing your fire hose.
3.6.1 Be Strict
Put the directive use strict as the first line (after the #! line if there is one) of every file (including modules you write; strictness is lexically scoped, not program scoped). Especially if you don't understand why. This makes Perl, well, stricter about things that you could get away with without it that are nevertheless usually mistakes. It is telling that the one group of people whose expertise would most allow them to get away without using strict (the uppermost echelon of Perl experts) is the most adamant about its indispensability. 8
Don't think it's faster to get your program working, then go back and insert the use strict, and clean up the resulting errors. It's much slower, for two reasons: first, developing without strictness results in errors being harder to find and taking longer to fix. Second, when you add strictness to a lengthy program that has never been strict before, the number of errors printed is likely to be enormous, and fixing them will probably not be trivial.
This is not an exaggeration, particularly if your non strict code has graduated to an operational environment. You may not have the option to shut things down while you recode and retest.
What makes use strict our friend is that most of the objections it raises prevent a program that is not following good practices from ever running. (This is called raising a compile-time exception. Although there is one class of errors it catches only at run-time.)
The biggest favor use strict does for you is to force you to declare all your variables with a my statement, or it will complain that you've referenced a variable without an explicit package name. In other words, variables not declared with my belong to a family of variables you seldom need to use; so seldom, in fact, that use strict requires you refer to such variables by their full names, which include the packages they live in.
Why is this such a huge favor? Because it guards against the ravages of the common typo. Consider this code:
my $enrolled_so_far = 0; foreach my $student (@students) { foreach my $class (keys %registry) { $enroled_so_far++, last if exists $registry{$class}{$student}; } } print "Number of enrollees so far = $enrolled_so_far\n";
Without use strict, this happily runs, producing the answer "0" no matter what the data. Because of the tiny typo in the innermost loop, perl increments a different variable called $enroled_so_far, which it automatically creates in this different family of variables we've been talking about. But under use strict, perl will refuse to run this code since $enroled_so_far has neither been introduced with a my statement nor is it qualified with a package name. 9
Using use strict insulates you against a host of errors and parts of Perl that you may never need to learn.
Declare as many of your variables as possible to be lexical.
Many snippets of code in documentation or articles don't declare their variables with my; the authors consider it too encumbering for their examples. The code may work fine without use strict, but each variable is created automatically as a dynamic or package variable, which has slightly different behavior from a lexical variable and for which temporary versions are created using the old local keyword.
use strict forces you to distinguish between lexical variables and dynamic variables. There is very little reason to use the latter, or local, any more in Perl programs, with the exception of
Special per-package variables like @ISA
Localizing special variables like $_ that can't be made lexical
Package variables that you create and want to access from other classes for inheritance purposes
You will usually know what to do when you encounter one of these situations.
3.6.2 Let Yourself Off with a Warning
Always run your programs with the -w option to enable warnings. Some of these warnings come at compile time (for instance, declaring a my variable already declared in the same scopeyou might think this would be reason enough to fail use strict, but Perl is curiously benevolent in this respect), and some of them come at run time because they can't be detected any earlier. (For instance, a warning that you used the value of a variable that was uninitialized or in some other way acquired the sentinel value undef. 10 Perl happily assigns a default value of 0 in numeric context and "" in string context to this variable, but chances are, it's a mistake for you to be reading an undefined variable at that point.) 11
Now, opinion is somewhat divided on the matter of leaving the -w flag on in operational, or delivered, code. The ayes contend that since you designed your program not to generate any warnings under -w (referred to as "-w clean"), if it ever does so, that is an error, and it ought to be visible as such. The nays retort that even if you've eliminated these possibilities, one day new warnings that your program triggers may get added to Perl, and you wouldn't want your customers' delicate sensibilities offended by Perl's sometimes off-the-wall remarks. Besides, sometimes the warnings can go to an output filter of some kind (like a Web serverwe'll show how to work with errors in CGI programs in Chapter 13) and confuse it.
We squirm on the fence and eventually fall down on the side of the ayes. The best-written code can go wrong in ways we never anticipated, 12 and the best tools are those that trap all kinds of errors and package them up for the maintainers like a drawstring cat litter box liner. Find ways of redirecting warnings in production code so that the information is saved but not necessarily exposed to the user, because if something that you're doing today generates a warning in a later version of Perl, it may cause a failure in the version of Perl that follows.
Perl 5.6.0 added a feature that greatly extended the -w functionality: lexical warnings. perldoc perllexwarn tells you how you can insert variants of the use warnings pragma to selectively enable and disable classes of warning in lexical scopes. Because the capability does not work with versions older than 5.6.0, and this book is not concerned with fine control over warnings, we stick to the -w syntax.
Use -w and use strict in all your programs.
Sometimes the one-liners perl spits out courtesy of -w are too succinct to figure out at first glance. You can find a longer explanation of the message by looking it up in the perldiag manual page, or you can insert the line use diagnostics; in your program, which causes the longer explanation to print along with the one-liner.
Use use diagnostics to explain error messages.
An alternative to changing your program or browsing through perldiag is to use the splain program distributed with perl. Just filter your program's output through splain, and it appends the longer explanation to each error message as though you'd used diagnostics in the first place.