To be honest, I am not yet sure what the best answer is. In general, I've stayed out of discussions regarding how best to use OO in perl (5) simply because I haven't seen a truely complete approach to putting OO together with perls dwimery such that you don't end up with dilemmas like this.
This sort of leads to the same set of thoughts that I had in my mind when I wrote this earlier today.
I've played with various OO techniques and modules from CPAN, but I invariably run up against some barrier, limitation, logical or syntactic inconsistancy that prevents me from getting the interfaces to work quite the way I would like them to.
- I like overloaded operators, where they make sense.
I find $complex1 += $complex2; infinitely preferable to
$complex1->set( $complex1->add( $complex2->get() );
- I like lvaluable (logical) attributes for objects.
I prefer
$file->position = 0 if $file->eof;
to $file->set_position( 0 ) if $file->eof();
- I like the idea of context sensitivity, on both input and output.
To my way of thinking the value of this is similar to one of the reasons we use OO in the first place. It is a form of namespace simplification. Polymorphism if you will.
One of the reasons for using OO, is that it allows us to re-use verbs as function (method) names without having to further qualify those names. I well remember writing C code where every library had its entrypoints prefixed with the name of the datastructure it operated on. thingy_init(), thingy_create(), thingy_destroy() and so on so as to prevent name conflicts. OO removes the need for this.
Avoiding the need for $thingy->set_date_from_string("...");
$thingy->set_date_from_array( localtime );
$thingy->set_date_from_array_ref( [localtime] );
by using using runtime determination of passed types to a single method seems a logical extension of this.
Likewise, return context.
So far, my attempts at trying to put together a clean and consistant implementation of classes that utilise all of these techniques in the same class have always ended up with an inconsistancy, or requiring undesirable copy&paste coding somewhere down the line.
Even simple things like inside-out objects leave me undecided. If your class has 3 physical attributes, do you code that as
package MyClass;
my %instances;
sub new{
my( $class, $attr1, $attr2, attr3 ) = @_;
my $self = bless {}, $class;
return $instances{ $self } = [$attr1, $attr2, $attr3];
}
or package MyClass;
my( %attr1, %attr2, %attr3 );
sub new{
my( $class, $attr1, $attr2, attr3 ) = @_;
my $self = bless {}, $class;
$attr1{ $self } = $attr1;
$attr2{ $self } = $attr2;
$attr3{ $self } = $attr3;
return $self;
}
The former is shorter and less profligate with space. The latter results in less complex syntax when referencing the attributes with the methods, but relies upon "parallel arrays", which I normally consider a bad idea. It also consumes more memory.
The complicated syntax of the former can be diffused by using (private) accessors/mutator functions, but that adds to the performance overhead.
If the objects are largish and few in number and not called in tight loops, neither is too much of a problem, but if the objects themselves are pretty small, but you need to use lots of them and/or call their methods in tight loops, then the overhead in memory and performance is a pain.
Maybe the answer is to wait until P6 for a clean solution and just muddle through for now?
|