Nearly every Perl script I write follows this format:
#!/usr/bin/perl -w
use strict;
use Other::Modules qw< ImportedFunction >;
use vars qw< $Globals >;
Main( @ARGV );
exit;
sub Routine
{
...
}
BEGIN {
my $static= "Initial value";
sub usesStatic
{
...
}
}
sub Main
{
my $putMainVarsHere;
...
}
__END__
So you can prevent your subroutine from accessing your
"main" variables by putting them where I wrote
$putMainVarsHere.
This style has evolved for quite a while and there are
specific reasons for almost every aspect of it. I find it
catches quite a few errors for me.
I was going to explain my reasons for most aspects
of this style, but I decided that that would be more
appropriate elsewhere.
(updated twice)
Update: Here are some justifications for some of my decisions that I collected quite a while ago planning to write this up more formally. Instead I've just moved them from my scratchpad to here:
- #!/usr/bin/perl is the standard place for Perl as declared by
Larry himself. Even if you install /usr/local/bin/perl, please also put
a link in /usr/bin and please use #!/usr/bin/perl in scripts that you
make public
- Explicitly listing what you want exported from a module means
that when I read your code and see GnarfleTheGarthock(), I can search for
"GnarfleTheGarthock" and I'll find the "use Coneheads qw(
GnarfleTheGarthock );" line and know where to go find documentation
and/or code for that subroutine even if Gnarfle or Garthock appear to be
an "obvious" Coneheads reference to _you_ ;)
- Lets you distinguish file-scoped lexicals declared at the top of
your scripts that act as global variables from "sub Main" lexicals that
should not be directly accessed by other subroutines.
- Gives you a handy place for a break point ("c Main") when
debugging (stepping over module and global variable initialization can
get boring)
- Since Perl's "global destruction" phase doesn't obey reference
counts, it can cause problems when objects refer to each other. "sub
Main" can aid debugging of such destruction issues because you can break
after returning from Main()...
- Main(@ARGV) allows you to parse the command line via @_
which makes it easier to refactor that code later
- exit; means that no code outside of a sub below will
get executed. This can bite you, but I really like it because I know I
don't have to search the entire script looking for random bits of code.
- That previous item also forces you to use BEGIN to initialize
any "static" lexicals, which ensures that you never call a subroutine
before any "static" lexicals that it uses are initialized
- The BEGIN block also prevents "will not stay shared" warnings that break the use of file-scoped lexicals in subroutines with Apache::Registry under mod_perl
-
tye
(but my friends call me "Tye")