Programming Tips Grab Bag No. 2

Dec 14, 2007

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.

3 Comments

kip

3:05 PM on Dec 17, 2007
I didn't realize that's how the $? variable worked. I think it still works if you just want to determine if it exited successfully or not ($? == 0), but if you want to know which non-zero RC you got I guess that doesn't work..

DC Global

3:44 AM on Feb 18, 2008
Hi nice post! I am a junior programmer.. as our practice, we didn't declare variable as global.. it risky!

Jonah

3:52 PM on Feb 18, 2008
Global variables can indeed be bad programming practice. But sometimes there's no avoiding them. They can also be very beneficial as well (e.g. global mutexes to prevent more than one instance of an application from running).

Leave a Comment

Ignore this field:
Never displayed
Leave this blank:
Optional; will not be indexed
Ignore this field:
Both Markdown and a limited set of HTML tags are supported
Leave this empty: