Some languages don't allow you to put your variables where you need them, they force you to declare things up front. C is like this, but this was fixed in C++. Perl allows you to declare variables virtually anywhere, which keeps things neat and tidy.
My advice is to keep your variable definitions as close as possible to where they are used, or to group them together logically in a sensible location. These can sometimes be contradictory, though, so it's often a matter of judgement.
There are advantages to both strategies.
Each sub-routine is like a mini program. It has "globals", it has local variables, and it has sub-blocks that have their own variables. In a recursive sense, the same rules you use to organize your main program apply to each sub-block, all the way down.
Here's an example of what I would categorize as poor technique:
sub foo
{
my ($foobar, $frurab) = @_;
my @foo = split(/,/, $foobar);
my $bar;
my $x;
foreach $x (@$frurab)
{
$bar .= $x->foo();
}
foreach $x (@foo)
{
$bar = "<$x>$bar</$x>";
}
return $bar;
}
Something that can set people's hair on fire is these Omni-Variables, these things called $x or $i or $foo which take on completely different roles at different points. In this example, $x is an object, and then later, a scalar. Talk about a personality disorder. When debugging, there is no certainty about what $x is going to be. If, instead, each foreach loop had its own properly named variable, things would be quite clear.
Also, the @foo variable is not very useful, and seems to just take up space for most of the routine even though it is used only briefly. You could just inline the split and save yourself the variable and the associated memory overhead.
Here's take 2:
sub foo
{
my ($foobar, $frurabs) = @_;
my $return;
foreach my $frurab_entry (@$frurabs)
{
$return .= $frurab_entry->foo();
}
foreach my $tag (split(/,/, $foobar))
{
$return = "<$tag>$return</$tag>";
}
return $return;
}
Now you have two different variables, each named specifically according to what they are. Now, instead of wondering what your seecond loop was iterating over, and having to check back in the function to find out, it is presented right there for you to see.
It's kind of like a "Just In Time" delivery system, only for variables. You don't keep stuff laying around. You create it when you need it, and you get rid of it as soon as possible. Remember that as soon as your foreach loop ends, all the local variables are liberated, and with them, any memory used. In big, deep functions, this can really cut back on resource consumption.
In the second example, the split version of $foobar is created and used and destroyed in a relatively brief period of time. In the former, it persists for the entire duration of the function, which could be some time. You can imagine how lots of little things like this can add up to a really big thing.
| [reply] [d/l] [select] |
I think dvergin has pretty well covered it -- declare the variables right when you're going to use them.
The exception for that would be when you have quite a large subroutine (one module that I wrote and still maintain is 2000 lines long, and mostly consists of a single routine 1750 lines long) -- in that case I put virtually all of my variable declarations at the top of the routine. That way there was less searching for variable declarations scattered around.
--t. alex
"Nyahhh (munch, munch) What's up, Doc?" --Bugs Bunny
| [reply] |
I was brought up in programming on a strict diet of Pascal, PL/SQL, and COBOL, so I know all about predeclaring my variables. This was still my standard in the C, Perl, and Java code as well. After reading Refactoring, I decided that it was time to make the switch. The problem with having your variables someplace other than where your using them is that it make code maintanence nasty. Say you have a somewhat long function of about 60-80 lines of code (this shouldn't happen after refactoring, but I digress). If all your variables are declared at the top of your procedure, you generally have to scroll up and down to figure out what their doing. If the scope of your variables is narrow, then you should see everyplace its used on one screen. That makes the lives of the programmers that come after you much easier. | [reply] |
However,the problem of not being able to figure out what a variable is doing is handled by using sensible, descriptive variable names.
| [reply] |
| [reply] |