It's time once again for a programming tips grab bag. As with the previous grab bag, I'll focus on Perl tips since I've been doing some Perl coding recently. Next time, I'll present some tips for PHP.
1. Always use the 'strict' and 'warning' pragmas for production code
This tip is pretty much a no-brainer. Whenever you write production level code, you must make use of the 'strict' pragma (enabled with 'use strict;
'). Not only will it save you from a lot of pain in the long run, but it also forces you to write cleaner code. You should also enable warnings, just for good measure. And don't do this at the end of your development cycle; do it right from the beginning. Always start scripts that you think will be used by others with the following two lines:
#!/usr/bin/perl
use strict;
use warnings;
I can't tell you how many times turning on strict checking has saved me from some goofy problems (such as using square brackets instead of curly braces for a hash reference).
2. Use 'our' to fake global variables
Global variables are generally considered to be bad practice in the world of programming, and rightfully so. They can cause untold amounts of trouble and can be quite dangerous in the hands of novice programmers. Out of the box, Perl only uses global variables, which is both a blessing and a curse. For quick and dirty scripts, globals are fine (and encouraged). But for production level code (which uses the 'strict' pragma mentioned above), globals aren't an option.
But sometimes, you can't avoid having a global variable (and they even make more sense than locals in some instances). I recently made use of the File::Find module in one of my scripts, calling it like this:
#!/usr/bin/perl
use strict;
use warnings;
use File::Find;
my $inSomeState;
find(\&mySearchFunction, $somePathVariable);
sub mySearchFunction {
if ($inSomeState) {
# Do something
}
}
The find()
call will execute the mySearchFunction
subroutine, operating in the $somePathVariable
folder. I cannot pass any parameters to the mySearchFunction
subroutine, but it needs to be able to check the value of the variable $inSomeState
. We previously created this variable using the 'my' construct, but since this subroutine is out of that variable's scope, Perl will complain. We can fix this by forcing the $inSomeState
variable to be global, using the our call instead of 'my':
#!/usr/bin/perl
use strict;
use warnings;
use File::Find;
our $inSomeState;
find(\&mySearchFunction, $somePathVariable);
sub mySearchFunction {
if ($inSomeState) {
# Do something
}
}
By declaring the variable with 'our,' we essentially force the variable into a global state (for the current scope, which happens to be the script itself in this case). Very handy!
3. Capture matched regex expressions inline
The parenthesis capturing functionality in regular expressions is extremely useful. However, I found that I always wrote my capture statements as a part of an if block:
if(m/(\w+)-(\d+)/)
{
my $word = $1;
my $number = $2;
}
I recently learned that this same code can be shortened into a one liner:
my ($word, $number) = (m/(\w+)-(\d+)/);
Of course, the match may not occur, so you'd have to test that the values of $word
and $number
aren't null, but it's a cleaner way of capturing stuff from a regular expression.
4. Make sure to shift by 8 for return codes
If you're trying to automate something (which I have been doing a lot of recently), the return codes from external processes are generally of great interest. The system call makes executing a process very easy, but getting the return code is (to me at least) a little non-intuitive. Here's how to do it:
system ("some_process.exe");
my $retval = ($? >> 8);
The return code from the some_process.exe program will be stored in the $? variable, but you have to remember to shift the value right by 8 to get the actual return value.