Monday, June 25, 2012

Perl and my Coding Practices

  • Underscore and underscore. No dot or hyphen or Capital letters. Use underscore to separate words in variables.
  • Name variables starting from general words and move towards more specific ones. For example, dir_models, dir_models_refined, file_score_contacts, file_score_total, etc.
  • While calling another program or running another perl script, always redirect the STDOUT and STDERR as well. Example, “perl calc_total_score.pl >> log.txt 2>&1 ”, “perl calc_total_score.pl > log.txt 2>&1 ”, etc.
  • Use a subroutine for log and exit instead of the writing three lines of code: log message, close log and exit or die. The subroutine can be something like this:

sub log_and_exit{
     my $message = $_[0];
               log_this("\nError! $message");
     close LOG;
     exit(42);
}
  • The main program that will call all other programs should maintain a log file. So, that we can know where our program is at a given moment. All subprograms/scripts need not maintain a log file. Printing to STDOUT is fine. That way we can test the program individually as well.
  • For reading files from a directory, this could be one of the easiest way: 
my @file_list = <$dir_models_selected/*>
foreach my $model (@file_list) {
     next if ($model =~ m/^\./);
     system_cmd ("cp $model $dir_models_for_3Drefine/") if($flag_run_3Drefine);
}
  • Always give examples while accepting command line arguments. Here is an example.

my $dir_models            = $ARGV[0]; # jobs/Tc658/models
my $file_contact_info     = $ARGV[1]; # jobs/contact.txt
my $file_ranked_models    = $ARGV[2]; # /tmp/result.txt
my $dir_working           = $ARGV[3]; # /tmp

  • Instead of using system($myprogram) command, use a subroutine to run commands. It can be like this. It is cleaner and saves a lot of time.
sub system_cmd{
     my $command = $_[0];
     $command = $command." >> $log_detailed 2>&1";
     open DETAILEDLOG, ">>$log_detailed" or exit(11);
     print DETAILEDLOG "\n\nExecuting $0: [$command]";
     close DETAILEDLOG;
     my $status = system($command);
     if($status != 0){
           log_and_exit("Failed [$command] $status");
     }
}