This page is a list of ‘‘best practices’’ for anyone contributing to Bioperl. Also see Advanced BioPerl and the Using Git HOWTO.
Bio::LocationI
Bio::SeqIO::genbank
use strict;
return;
instead of return undef;
our $x;
instead of use vars ($x); BEGIN { $x=... };
qq{error in "$file"}
not "error in "$file""
uc($s)
, lc($s)
, quotemeta($s)
rather than \U$s
, \L$s
, \Q$s
$self->throw()
instead of die()
or confess()
$self->warn()
instead of warn()
or carp()
or cluck()
$self->debug()
instead of print STDERR "...."
Bio::Root::IO->catfile(@dir)
or File::Spec->catfile()
instead of join('/',@dir)
File::Spec
functions for portability across platformsopen
, e.g. open my $FH, '<', 'filename.txt'
open my $OUT, '>', 'output.txt'
open()
modes and vice-versa):{
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;
}
Not:
{
# 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;
}
use base qw(Bio::Class);
instead of use vars qw(@ISA); @ISA=qw(Bio::Class);
Bio::Class->new()
instead of new Bio::Class()
method Bio::Class(@args)
: this simply doesn’t work on some systems.1;
as the last line@_
into named variables. If there are more that two arguments present, use named parameters and Bio::Root::RootI->_rearrange()
. In general, always use Bio::Root::RootI->_rearrange()
for maintainability unless there is a demonstrable and significant performance issue._rearrange()
takes two arguments. The first argument is an array reference containing the name of the parameters in upper-case letters. The second argument is the array of parameter-value pairs.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);
# ...
}
AUTOLOAD
is controversial for most core BioPerl developers but has been used for bioperl-runAUTOLOAD
in BioPerl.AUTOLOAD
in the core modules unless absolutely necessary, primarily for performance reasons but also because the UNIVERSAL
method $self->can()
will not work for AUTOLOAD
‘ed methods._set_from_args()
is recommended, most likely in combination with _setparams
: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;
}
eq
> index()
> =~
m{//}
not /\/\//
o
(compile-once) modifier when combining regular expressions with interpolated variables and loops, which will result in subtle errors. The following compiles the regex to only find ‘start’, so here the regex will always match, even with ‘foobar’: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";
}
}
}
qr/.../
rather than strings to pre-store regexps as they provide compile-time syntax checking(?:)
$1
into named variables (similar to what is done for methods, above):if ( my ($start, $end, $strand, $score) =
$line =~ m{^(d+)s+(d+)s+(d)s+(d+)}xms) {
# ...
}
return
from a sort
(for background see http://use.perl.org/~schwern/journal/28577):sub foo {
# ...
@sorted = sort @unsorted;
return @sorted;
}
Not:
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(), $_] }
@unsorted;
Not:
@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
t/Module.t
t/data/
in the version control repositoryDo 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
section with the fully qualified module name and a description, for example:=head1 NAME
Bio::Tools::MyTool - parse MyTool gene predictions
=head1 SYNOPSIS
# Synopsis code demonstrating the module goes here
=head1 DESCRIPTION
A description about this module.
=cut
=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
=cut
=head1 FEEDBACK
=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.
bioperl-l@bioperl.org - General discussion
=head2 Support
Please direct usage questions or support issues to the mailing list:
I<bioperl-l@bioperl.org>
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:
https://github.com/bioperl/bioperl-live/issues
=head1 AUTHOR
=cut
podchecker
to check your POD syntax