Best Practices HOWTO

This page is a list of ‘‘best practices’’ for anyone contributing to Bioperl. Also see Advanced BioPerl and the Using Git HOWTO.



General coding practices

Error handling and debugging

I/O and cross-platform

my $FH; # 1st and unique declaration
open $FH, "<", $file or $self->throw("Cannot open $file: $!");
my @data = <$FH>;
# do something with @data...
open $FH, ">", $file or $self->throw("Cannot write to $file: $!");
print $FH @data;
close $FH;


# 1st declaration
open my $FH, "<", $file or $self->throw("Cannot open $file: $!"); 
my @data = <$FH>;
# do something with @data...
# 2nd declaration
open my $FH, ">", $file or $self->throw("Cannot write to $file: $!"); 
print $FH @data;
close $FH;

BioPerl Object-oriented programming and modules


Unloading method arguments, two args:

sub foobar {
    my ($self, $start, $end) = @_;
    #  ...

Unloading method arguments, more than two args:

sub barfoo {
    my ($self, @args) = @_;
    my ($start, $end, $score, $strand) = $self->_rearrange(
            [ qw( START END SCORE STRAND ) ], @args);
    # ...
sub new {
    my($class, @args) = @_;
    my $self = $class->SUPER::new(@args);
    $self->_set_from_args(@args, -methods => [@allowed_methods],
                                 -create => 1);
    return $self;

sub _setparams {
    # ...
    my $param_string = $self->SUPER::_setparams(
                   -params => [@settable_methods], -dash => 1);
    return $param_string;

Regular Expressions

my @strings = qw(hello goodbye start end flag score);

while (my $string = shift @strings) {
    for my $flag (qw(start end hello foobar)) {
        if ($string =~ m{^$flag}o) {
            print "Got $flag!\n";
if ( my ($start, $end, $strand, $score) = 
    $line =~ m{^(d+)s+(d+)s+(d)s+(d+)}xms) {
    # ...


sub foo {
    # ...
    @sorted = sort @unsorted;
    return @sorted;


sub bar {
    # ...
    return sort @unsorted;

The latter form has undefined behaviour if bar() is called in scalar context.

@sorted = map { $_->[1] }
         sort { $a->[0] <=> $b->[0] }
         map { [$_->method(), $_] }


@sorted = sort { $a->method() <=> $b->method() } @unsorted;

The latter form is inefficient and can cause subtle bugs if method() (indirectly) calls its own sort subroutine


Do this once, answering ‘no’ to script installation:

perl Build.PL

Then do this every time you want to run a test script where test.t is the name of the script:

./Build test --test_files t/test.t --verbose

Note that perl -I. -w t/test.t is NOT good enough, since it won’t catch all problems.

When you’re happy the script passes on its own, run the entire test suite:

./Build test

If everything passes, commit.


=head1 NAME

Bio::Tools::MyTool - parse MyTool gene predictions


# Synopsis code demonstrating the module goes here


A description about this module.

=head2 method_name

Title    : method_name
Usage    : Some small examples of method usage
Function : Some description about what the method does
Returns  : What the method does
Args     : What arguments the method takes


=head2 Mailing Lists

User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to one
of the Bioperl mailing lists.  Your participation is much appreciated.                  - General discussion

=head2 Support

Please direct usage questions or support issues to the mailing list:


rather than to the module maintainer directly. Many experienced and
reponsive experts will be able look at the problem and quickly
address it. Please include a thorough description of the problem
with code and data examples if at all possible.

=head2 Reporting Bugs

Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution. Bug reports can be submitted via the web:

=head1 AUTHOR