I've read a lot of novice Perl code over the past decade, often in response to requests for help.

One common feature of novice code is file-scoped variables:

#! perl use strict; use warnings; my @customers; # array of customers my $sth; # database statement handle my $i; # index variable # ... my %records; # hash of records

You're lucky if the code is this good; often it's face-palmingly worse, as in the case of Microsoft's awful Perl code for the 2008 Winter Scripting Games:

%dictionary = (); # create a hash table

The problem with the big block of variable declarations is that it fails to take advantage of the notion of scope -- that you can draw a little box around a unit of code and keep certain pieces of information inside that block private to the block.

If I went to my fridge and took out the leftover pizza you were saving in your fridge for lunch, you'd be confused and upset by our haunted magic refrigerators. Similarly (if less gastronomically pleasing to me), modifying a global variable somewhere where you didn't expect it to have an effect elsewhere is confusing and frustrating.

While advocates of certain dynamic languages decry the use of variable declarations as a relic of stupid static typing systems like you might find in the C, C++, and Java languages, Perl variable declarations have an enormous benefit in clarity: they help you see the scope of variables.

Yes, this means that sometimes adding syntax to a language can improve clarity.

There's a huge difference between:

my @customers; # array of customers my $dbh; # database handle my $sth; # statement handle ... find_customers(); sub find_customers { $sth = $dbh->prepare( 'SELECT ...' ); while (my $row = $sth->fetchrow_arrayref()) { push @customers, $row; } }

... and:

my $dbh; # database handle ... my @customers = find_customers($dbh); sub find_customers { my $dbh = shift; my $sth = $dbh->prepare( 'SELECT ...' ); my @customers; while (my $row = $sth->fetchrow_arrayref()) { push @customers, $row; } return @customers; }

The second code may look more complex, but it has several advantages:

find_customers() can modify the contents of the $dbh and @customers variables internally without affecting code elsewhere.

can modify the contents of the and variables internally without affecting code elsewhere. The $sth variable does not conflict with other statement handles elsewhere. As well, Perl will clean it up when the function returns.

variable does not conflict with other statement handles elsewhere. As well, Perl will clean it up when the function returns. find_customers() can work with several different database handles, if necessary: the code is more reusable.

can work with several different database handles, if necessary: the code is more reusable. The inputs and outputs to the function are clear: every variable used within the function has a clearly scoped lifetime.

This issue may seem like a minor quibble over style -- after all, in small programs, scope really doesn't matter -- but for programs over a few dozen lines, the decrease in the risk of error and improvement in maintainability and readability is substantial.