< C Coding Style | Russ Allbery > Technical Notes > Coding Style |
Perl should only be studied as a second language. A good first language would be English.
Larry Wall
In general, follow the rules in the perlstyle man page, except we use
cuddled elses (else
on the same line after }
). And, of
course, follow rules below rather than perlstyle if they conflict.
All scripts must have POD documentation including a NAME section suitable for turning into a man whatis entry, a SYNOPSIS section giving the options for invoking the script, and a DESCRIPTION section that explains what the script does. Any script that takes command-line options must have an OPTIONS section documenting them. Follow the layout in the pod2man man page.
Similarly, all modules must have POD documentation including NAME, SYNOPSIS, and DESCRIPTION sections. Preferrably, modules should also have a METHODS or FUNCTIONS section describing each interface provided. POD documentation for modules may be collected at the end of the module or interspersed with the function or method definitions as preferred.
If not using interspersed POD to document functions, each function should have a leading comment that briefly describes what the function does and what arguments it takes. There's usually no need for fancy formatting; English sentences are usually sufficient (and take up less space on the screen).
Unless there's some exceptional reason not to do so (such as needing to pass unknown partial parameters on to another function, or when implementing AUTOLOAD routines), the first line of any Perl function should be of the form:
my ($var1, $var2) = @_;
for whatever variables that function takes. This documents the
parameters in a consistent way. Some of my older code uses
shift
, but I change it when I touch it to follow this style.
Prototypes may be used if you believe they would be helpful, although normally I don't bother.
Always explicitly check the results of operations. Normally this
means adding or die "some error: $!\n"
to the end of calls to
functions such as open
which may fail.
Enable warnings (by adding -w
to the #!/usr/bin/perl
line or via use warnings
) for any script that's only run by
administrators or where the warnings will go to somewhere harmless
(such as to the Apache log for CGI scripts. Do not enable warnings if
the warnings would go to end users (such as for generally accessible
remctl backends), since they may expose secure information.
Use Getopt::Long for option parsing in any script that takes options.
Give each option a corresponding single-character option unless it's
rarely used. Normally you will want to call Getopt::Long::Configure
with the options bundling
and no_ignore_case
. When
listing the options, give the short option first, then |
, and
then the long option, as in:
GetOptions ('d|delete' => \$delete, 'e|exclude=s' => \@excludes, 'f|filter' => \$filter, 'h|help' => \$help, 'o|overrides=s' => \$overrides, 's|style-url=s' => \$STYLES, 'v|version' => \$version) or exit 1;
All options must be documented in the OPTIONS section of the POD documentation. List the short and long options in the =item header separated by a comma and space.
for my $var
is preferred to using the implicit $_
unless
the body of the loop is short. Similarly, using the implicit
$_
variable for large blocks of code is not recommended.
Functions that use $_
except in for loops must protect their
callers against unexpected modifications with local $_
before
setting it.
Global variables should be set at the top of the script and have names
in all caps. They must either be declared with our
(recommended) or with use vars
(to support older versions of
Perl). All other variables should use my
to restrict their
scope as appropriate.
Use an explicit return
statement to return a value rather than
taking advantage of the implicit return of the value of the last
expression. It's less confusing for people coming from other
languages.
Use return
rather than return undef
to return a false
value.
Don't use the ternary operator (?:) except on the right-hand side of an assignment. Specifically, it is not a replacement for an if/then block. It's harder for inexperienced programmers to read when used that way and it looks odd.
All Perl code should pass perl -wc
cleanly.
Don't use use English
; it confuses experienced Perl
programmers.
I consider these optional rules that I may break when I have good reason, but which I try to adhere to whenever possible.
Scripts should support -h
and --help
options that
displays the documentation for the script, generally by running
perldoc -t
on the script but alternatively by displaying a
shorter option summary if the script is installed by a package and
also installs a man page. If the script isn't normally installed with
a man page (such as scripts run out of AFS), it should always display
the full documentation using perldoc -t when run with -h. Otherwise,
it's hard to find the documentation.
Include the name of the script in error messages. This is particularly important for scripts run from cron or other scripts, although it's useful to have in general and never hurts. The easiest way to do this is to put something like:
my $fullpath = $0; $0 =~ s%.*/%%;
near the top of the script and then prefix all warn
or
die
messages with $0:
. If you use this format, the
first character of the rest of the message should not be capitalized.
You can then use $fullpath
as the path to the script for
perldoc.
When writing SQL code, set AutoCommit to 0 and RaiseError to 1 and then use the following pattern:
eval { my $sql = '...'; $dbh->do ($sql, undef, $param1, $param2); $dbh->commit; }; if ($@) { $dbh->rollback; # Other error handling goes here. }
Always use placeholders and bind values (see the DBI man page) whenever possible so that variable values will be escaped properly, preventing SQL injection attacks.
It's generally a good idea to set $| = 1; near the top of the script to flush output after every print so that regular output and error messages are intermixed in the proper sequence. This should be omitted, however, if the script produces copious output and benefits from system I/O buffering.
Include an AUTHOR or AUTHORS section as the final section in the POD file to document the maintainer and previous authors of the script or module.
Don't leave commented-out code in production scripts or modules; instead, just delete it. Retrieving no-longer-used code that may be needed again later is what the revision control system is for. An exception may be places where the code is useful as part of a comment, in which case indent it four spaces relative to the surrounding text.
my $o = Module::Name->new
, not my $o = new
Module::Name
. new
is a method and the second form uses
magical barewords and lots of other squirrelly areas of Perl syntax
and tends to break in odd and surprising ways if you need to pass
arguments and have more complex syntax. The first form always works
and is clear that you're calling a class method.
Prefer three-argument open (open (FOO, '<', $file)
) to
two-argument open (open (FOO, $file)
) unless you really have to
support pre-5.8 Perls. It has far fewer weird behaviors.
Don't use tabs in perl scripts, since they can expand differently in different environments. In particular, please try not to use the mix of tabs and spaces that is the default in Emacs.
Please follow these guidelines for spacing and formatting:
Each block is indented four spaces. Continuations of commands should be indented four spaces unless parenthesized, or indented to line up one space after the opening parentheses if parenthesized.
Lines should be 79 characters or less (preferrably 78 or less so that patches won't wrap). Continue long lines on the next line. Continue long strings by breaking the string before a space and using string concatenation (.) to combine shorter strings.
Use a space between keywords (if, elsif, while) and functions and parenthesized arguments. Do not put a space between the opening or closing parentheses and the contents. For example:
if ($foo) { bar ($baz); }
As mentioned in perlstyle, when derefencing, add a space between curly
brackets and a complex expresion, such as @{ $foo{bar} }
. Also
add a space around operators (+
, =
, and so forth).
Parentheses are optional around the arguments to Perl built-ins such
as print
or push
and normally should be omitted unless
they add clarity. Parentheses should normally be used around
arguments to locally defined functions and methods (and are often
required by Perl), but exceptionally may and should be omitted around
a single argument to an error reporting functions that behave
equivalently to die
or warn
. The empty parentheses
should be omitted from function calls taking no arguments.
map
, grep
, and sort
are a special case; their
first argument is a code block and should be set off by { }
with spaces between the brackets and the code. This code block should
never be within parentheses.
Break long if statements before an operator such as &&
or
||
, not after as suggested in perlstyle. Starting the line
with an operator makes it easy to see its relation with the previous
line without excessive eye movement.
Prefer:
bar ($baz) if $foo;
or writing the statement on three lines as above to:
if ($foo) { bar ($baz) }
unless there are multiple consecutive conditions and actions that
you're aligning vertically. Whether to put if
before or after
the statement depends on the logical flow of what you're testing; see
perlstyle for some guidelines.
Section headings should be 78 #
characters, a line starting
with one or more #
s and a space giving the contents of the
section (no need to capitalize every word here), and then another line
of 78 #
characters.
This heading style doesn't require adjustment or realignment after changing the text of the heading.
The recommended Emacs configuration, suitable for including in your .emacs file, is:
(setq cperl-indent-level 4) (setq cperl-lineup-step 1) (setq cperl-continued-statement-offset 4) (setq indent-tabs-mode nil)
The section headings may be generated with the following Emacs function.
;; Insert a header for a Perl program (using # comment notation). (defun rra-insert-script-header (header) "Insert my Perl section header, prompting for the header content." (interactive "sHeader: ") (insert (make-string 78 ?#) "\n# " header "\n" (make-string 78 ?#) "\n"))
You may want to bind that to a key.
The recommend vim configuration, suitable for including in your .vimrc file, is:
set tabstop=4 set expandtab
< C Coding Style | Russ Allbery > Technical Notes > Coding Style |