(BTW, this is re: the reimplementation of major chunks of BioPerl using Moose, Biome: http://github.com/cjfields/biome/tree/)

Locations should use a Role (specifically, Biome::Role::Range), so start/end/strand should be attributes, not methods. With attributes the best way to do this is probably with a builder, and lazily (start requires end, and vice versa). Factor out the common code as Tomas indicates. BTW, the $self->throw() is akin to BioPerl's $self- >throw() exception handling; it simply catches any exceptions and passes them to the metaclass exception handling.

I've been thinking about making the Range role abstract for this very reason (or defining very basic attributes); something like:

----------------------------

package Bio::Role::Range;

requires qw(_build_start _build_end _build_strand);

# also require other methods which need to be defined in implementation

has 'start' => (
     isa      => 'Int',
     is       => 'rw',
     builder  => '_build_start',
     lazy     => 1
);

# same for end, strand (except strand has a different isa via MooseX::Types)
....

package Bio::Location::Foo;

with 'Bio::Role::Range';

sub _build_start {
   # for location-specific start
}

sub _build_end {
   # for location-specific end
}

sub _build_strand {
   # for location-specific strand
}

sub _common_build_method {
   # factor out common code here, call from other builders
}

----------------------------

Also, I think the Coordinate-related stuff should be simplified down to a trait or an attribute; they bring in way too much overhead in bioperl w/o much added value.

And now back to your regular Moose-related broadcast...

chris

On Aug 11, 2009, at 9:27 PM, Siddhartha Basu wrote:

Hi,
In one my classes i have this boilerplate code block that is repeated all
over ....

sub start {
   my ( $self,  $value ) = @_;
   $self->{'_start'} = $value if defined $value;

## -- from here
   $self->throw( "Only adjacent residues when location type "
         . "is IN-BETWEEN. Not ["
         . $self->{'_start'}
         . "] and ["
         . $self->{'_end'}
         . "]" )
     if defined $self->{'_start'}
     && defined $self->{'_end'}
     && $self->location_type eq 'IN-BETWEEN'
     && ( $self->{'_end'} - 1 != $self->{'_start'} );
   return $self->{'_start'};
## -- here

}

then again ....

sub end {
   my ( $self,  $value ) = @_;

   $self->{'_end'} = $value if defined $value;

   #assume end is the same as start if not defined
   if ( !defined $self->{'_end'} ) {
       if ( !defined $self->{'_start'} ) {
$self->warn('Calling end without a defined start position');
           return;
       }
       $self->warn('Setting start equal to end');
       $self->{'_end'} = $self->{'_start'};
   }

## ----

   $self->throw( "Only adjacent residues when location type "
         . "is IN-BETWEEN. Not ["
         . $self->{'_start'}
         . "] and ["
         . $self->{'_end'}
         . "]" )
     if defined $self->{'_start'}
     && defined $self->{'_end'}
     && $self->location_type eq 'IN-BETWEEN'
     && ( $self->{'_end'} - 1 != $self->{'_start'} );

   return $self->{'_end'};
#---------
}


Is there any way moose can be used here for more code resuage. I thought about converted it to a type but still couldn't figure out how that can
be done.


thanks,
-siddhartha

Reply via email to