[Biodevelopers] Object Oriented Perl issue

Joe Landman landman at scientificappliance.com
Wed Apr 24 08:58:56 EDT 2002


Folks:

  My day job (ok, one of the hats I wear) has me coding in Perl.  I am
using the OO methodologies with modules.  And of course, I had a
question on the "rightness" of a particular way of doing things.

  It works, and works nicely (except under SOAP::Lite, which I do not
understand).

  Here is the problem.  When you instantiate an object, usually you do
something like this:
	
    use Foo::Bar;
    $object = Foo::Bar->new();

  If you want to pass specific parameters to the new object, you
typically put an argument string in the parenthesis to new.  This can be
a scalar, an array, or a hash.  You just have to parse it correctly in
your Foo::Bar::new method. 

   This is fine, no issues here.  Now suppose you want to attach
attributes to the object (think of the object as having methods and
attributes, attributes being "localized" variables to the object).  So
you would use attribute accessor/mutator methods (aka get/set).  If you
read Damian Conway's book on the subject, he indicates that what you
should do is to build one accessor/mutator per attribute.  So if you
have many attributes, you have many accessor/mutator pairs. This means
that your code is sprinkled with:

    sub get_fragment
        {
          my $self = shift;
          return $self->{'fragment'};
        }
    sub set_fragment
        {
          my ($self,$value) = @_
          return $self->{'fragment'}=$value;
        }

This is fine, until you hit the second attribute, and you immediately
start thinking that this is a waste of time, typing, will slow down the
Perl system, etc.  To use this in your code, you do something like this:

    $object->set_fragment(10);
    .
    .
    printf "Fragment is %i\n",$object->get_fragment();

  So thinking about this, I realized that you could use a general
accessor/mutator pair and the auto-vivification capability of Perl, and
deal with any number of attributes with a single pair, like this:
    
    sub get_attribute
        {
          my ($self,$attribute) = @_;
          if (exists($self->{$attribute}))
             {
               return $self->{$attribute};
             }
            else
             {
    	   return undef;
             }
        }
    sub set_attribute
        {
          my ($self,$attribute,$value) = @_
          return $self->{$attribute}=$value;
        }

  To use this in your code, you would do something like:

    $object->set_attribute('fragment',10);
    .
    .
    printf "Fragment is %i\n",$object->get_attribute('fragment');
    

  So this works.  It works quite well.  Except for some reason, in a
remotely instantiated object under SOAP::Lite (then again, the other
method also doesnt work there).  Basically in your new method, you
include a line to copy the argument hash to the attributes like this:

    sub new
        {
    	my ($class,%args) = @_;
    	my $self={};
     	bless $self,ref $class || $class ;
    	while (my ($key,$value) = each %args)
    	   {
    		$self->set_attribute($key,$value);
    	   }
    	return $self;
        }

and your call to new now looks like this:

    $object=Foo::Bar->new(
    			'attribute-1'=>'value1',
    			'attribute-2'=>'value2',...
    		     );

You can use Data::Dumper and print Dumper(\$object) to see that this
really works.

My question is whether or not this is considered good OO style.  I am
effectively relying on the auto-vivification (the automatic creation of
a new variable) to build the attributes.  This means that in theory, I
can have an unlimited number of attributes.  I presume that the orginial
framers of OO would not be happy with this.

Another question revolves around what could go wrong with this.  I am
not trying to enforce hiding in OO here, just localization of an objects
variables with its methods.

Thoughts and comments welcome.  Is this an issue in Python (everything
is an object) or similar?

Joe




More information about the Biodevelopers mailing list