Приглашаем посетить
Клюев (klyuev.lit-info.ru)

4.6 Variable Renaming

Previous Table of Contents Next

4.6 Variable Renaming

Easily vying with misindendation for unintentional obfuscation is cryptic variable naming. If you look at a piece of code and can't tell what a variable is for, it has the wrong name. A brief mnemonic is usually sufficient: $func is as good as $function, and unless there are other function references nearby, as good as $function_for_button_press_callback. On the other hand, $f is not good enough.

Names like $i and $n are fine if their variables enjoy the commonly accepted usages of an index and a count, respectively, but only over a short scope. Single-letter or otherwise cryptic names can otherwise be acceptable if they are recapitulating a formula that is well-known or included in official documentation for the program, for example:


$e = $m * $c ** 2;



# Weighted average contribution, see formula (4):

$v_avg = sum(map $v[$_] * $v_w[$_] => 0..$#v) / sum(@v_w);

However, single-character variable names should be confined to small scopes because they are hard to find with an editor's search function if you need to do that.

Don't use $i, $j, and so on, for indices in hierarchical data structures if the structures are not truly multidimensional; use names representative of what's stored at each level. For instance:


$level = $voxels[$x][$y][$z];

Okay; these really are x, y, z coordinates.


$val = $spreadsheet[$i][$j];

Okay; accepted usage.


$val = $spreadsheet[$row][$col];

Better; more common terms.


$total += $matrix[$i][$j][$k];

Fine, if we don't know any more about @matrix (perhaps this is in a multidimensional array utility method).


$e = $o{$i}{$j}{$k};

Bad; you have to look up what those variables mean.


$employee = $orgchart{$division}{$section}{$position};

Much clearer.


$emp = $org{$div}{$sec}{$pos};

Equally useful; the variables are sufficiently mnemonic to suggest their meaning immediately.

perlstyle has some excellent recommendations for formatting of variable names:

  • Use underscores for separating words (e.g., $email_address), not capitalization ($EmailAddress).

  • Use all capital letters for constants; for example, $PI.

  • Use mixed case for package variables or file-scoped lexicals; for example, $Log_File.

  • Use lowercase for everything else; for example, $full_name. This includes subroutine names (e.g., raid_fridge) even though, yes, they live in the current package and are not lexical.

Subroutines that are internal and not intended for use by your users should have names beginning with an underscore. (This won't stop the users from calling the subroutines, but they will at least know by the naming convention that they are doing something naughty.)

4.6.1 Symbolic Constants

I seldom use the constant pragma, which allows you to define symbols at compile time; for instance:


use constant MAX_CONNECTIONS => 5;

.

.

.

if ($conns++ < MAX_CONNECTIONS) ...

It has some advantages:

  • You cannot overwrite the value assigned to the symbol. (Well, not easily: The constant is actually a subroutine prototyped to accept no arguments. It could be redefined, but you wouldn't do that by accident.)

  • The use of a constant is (usually) optimized by the Perl compiler so that its value is directly inserted without the overhead of a subroutine call.

  • The symbols look constant-ish; identifiers beginning with a sigil ($, @, %) tend to make us think they are mutable.

It also has some disadvantages:

  • Constants are visually indistinguishable from filehandles.

  • A constant can't be used on the left-hand side of a fat arrow (=>) because that turns it into a string. You have to put empty parentheses after the constant to ensure that Perl parses it as a subroutine call.

  • The same is true of using a constant as a hash key.

  • Constants do not interpolate into double-quoted strings, unless you use the hair-raising @{[CONSTANT_GOES_HERE]} construction.

  • Being subroutines, they are package-based and cannot be confined to a lexical scope; but they go out of scope when you have a new package statement (unless you fully qualify their names).

  • Being subroutines, they are visible from other packages, and are even inheritable. You may consider this an advantage if you wish but it is not intuitively obvious.

So I tend to define my constants as just ordinary scalars or whatever they might be:


my $PI      = 3.1415926535897932384;

my @BEATLES = qw(John Paul George Ringo);

Purists argue that constants should be unmodifiable, but Perl's central philosophy is to let you assume the responsibility that goes along with freedom. Anyone who changes the value of p deserves the consequences that go along with altering the fundamental structure of the universe. On the other hand, you might have good reason at various times to add 'Stuart' or 'Pete' to @BEATLES.

    Previous Table of Contents Next