README for Bioperl Exceptions

This directory contains some sample scripts and modules that
illustrate the use of Graham Barr's Error.pm module for creating,
throwing, and catching exceptions within Bioperl code. These demo
scripts should be executed within the examples/exceptions directory
of the Bioperl distribution.

Demo script         Description
------------------  ----------------------------------------
test1.pl            How to throw and catch Error.pm objects
test2.pl            How to throw Error.pm objects via Bio::Root::Root
test3.pl            Illustrates inheritance between Error.pm types
test4.pl            Shows what happens when Error.pm isn't installed

Error.pm is available through CPAN and I encourage Bioperl users and
developers to install it and start using it in your scripts and
Bioperl modules. For your convenience, I've included a tarball
containing the latest Error.pm distribution from CPAN
(Error-0.13.tar.gz).

This module is quite convenient and easy to use and adds a level of
control for managing errors within your Perl code using familiar
object-oriented, try-catch-finally semantics. You can define subclasses
of Error.pm representing particular types of exceptions, and you can
define catch blocks to handle these types of exceptions. 

This has distinct advantages over simply catching any and all errors
with an eval{} block, as is currently done in Bioperl. Strongly typed
exception objects make it easy to write appropriate handlers. It also
makes you code easier to understand because it's clear what type of
things can go wrong.

So why use Error.pm instead of some other utility? Well, Perl 6 will
most likely include some form of structured exception handling akin to
that provided by Error.pm (see these RFC's:
http://dev.perl.org/rfc/63.pod and http://dev.perl.org/rfc/88.pod).
So it will probably be easy to convert Error.pm-based exception handling
to whatever is adopted for Perl 6.

(Side note for CORBA folks: Error.pm is used in some other CPAN
modules, notably CORBA::MICO. Thus, using Error.pm within Bioperl
allows consistent exception handling methodology when working with
such modules and Bioperl together.)

Bio::Root::Exception.pm
-----------------------

The Bio::Root::Exception.pm module contains a number of Error.pm subclasses
representing common types of errors. If you want to throw an exception
within your Bioperl module that doesn't correspond to any of the ones
defined in Bio::Root::Exception, feel free to define a new one, but be sure
it inherits from Bio::Root::Exception or one of its subclasses. This will
allow anyone to write a handler for any type of Bioperl exception.

Defining a new type of exception can be done quite simply. All you
need to do is to specify the @ISA array for your new type, as in:

    @Bio::Root::Exception::MyBad::ISA = qw( Bio::Root::Exception );

If you want to override any of the available methods or add new ones,
you'll have to provide a package statement and the appropriate
method definitions.

Programming tip: Be careful not to use exceptions as your primary
means of flow control within your code. Throwing and handling
exceptions come with some execution overhead. Also, such excessive use
of exceptions can make your logic hard to follow.

Bio::Root::Interface.pm
-----------------------

Also in this directory is the module Bio::Root::Interface, that is
useful as a base class for any module that specifies an interface. 
Bio::Root::Interface simplifies the process of writing virtual methods.

It defines a method called "throw_not_implemented()" that will throw a
Bio::Root::NotImplemented exception. Any method within a Bio::Root::Interface 
subclass can call throw_not_implemented() to indicate that a method 
has not been implemented. Implementations of the interface must implement
the method or an exception will result when someone tries to use it.

Bio::Root::Interface can make use of Error.pm if available, but
Error.pm is not required. The module TestInterface.pm demonstrates how
to use of Interface.pm

Bio::Root::Root::throw() with Error.pm
---------------------------------------

Bio::Root::Root can determine if Error.pm is available and if so, can
make use of it when Bio::Root::Root::throw() is called. For a demo,
see test2.pl.


Real-Life Examples
------------------

For an example of how to make use of the Error.pm-related capabilities
of Bio::Root::Root.pm, I created new versions of Bio::SeqI.pm,
Bio::Seq.pm, Bio::PrimarySeqI.pm, and Bio::PrimarySeq.pm within the
Bio subdirectory. This conversion is pretty straightforward and could
be done on the other Bioperl modules without too much effort.

Using Error.pm's try{} and catch{} within Bioperl Modules
----------------------------------------------------------

For developers, using Error.pm's try{} and catch{} blocks within
Bioperl modules themselves could come in handy. But doing so would add
an external dependency for Error.pm, which is not part of the standard
Perl distribution. So at this stage, it's best to stick with just
using Error.pm's throw() method (via Bio::Root::Root) and leave the
try{} and catch{} blocks for use only within your scripts.

If you really want to use try{} and catch{} within your module and
still want to be capable of running when Error.pm isn't available, you
can check $Bio::Root::Root::ERRORLOADED variable, but this would be
kind of awkward.

If we really want to incorporate it within Bioperl, a reasonable
solution would be to distribute Error.pm with Bioperl. 

--
Steve Chervitz <sac@bioperl.org>
21 April 2001
Updated 19 December 2001

