Perl is a wonderful language for it allows one to
accomplish certain task in many ways imaginable.
One other distinct feature of Perl is it's 'implementation'
of the OOP paradigm. In my short career I have seen
code where it was heavily abused, and as well rare
few snippets where it made the most perfect sense.
Just recently, I was working on an older piece of code
that I wrote some months ago. The reason I had to go back
and look at the code was due to a just sprang bug that I had
to fix. Although I could have taken significantly less time
to repair the script, it took me much longer this time
due to poor OO design of some of my objects which impaired my
ability to fully discern program logic and consiquently
fix the bug in the most efficient way (minimal required code
change/impact). Here, I'll attempt to describe the nature of
this OO design flaw on an imaginary script...
imagine class
Gadget.
package Gadget;
#
# 'build' new gadget...
# return undef on fail.
#
sub new {
my ($proto, $name, %args) = @_;
my $self = bless {}, $proto;
$self->{name} = $name;
. . . work with %args . . .
return $self;
}
#
# check if a gadget has already been built.
#
sub is_built {
my ($self, $name) = @_;
return exists %_built_gadgets{$name};
}
1;
package main;
my $g1 = new Gadget('knob');
. . . create a bunch of other gadgets . . .
if ($g1->is_built($athing_name)) {
print "Gadget '$athing_name' has already been built!!\n";
} else {
. . . do something useful here . . .
}
Here the use and purpose of
is_built() method is
obscured by two factors. On the one hand, it seems that
is_built() has something to do with the instance of a Gadget
class (the $g1 object). Am I checking here whether object
$g1 was built with name
$athing_name? Or, do I simply
check that an instance of class Gadget named
$athing_name
exists and that
also it is somehow related to the
$g1 object? On the other hand, there's this 'Gadget
... has already been built!' comment that gets printed
on the success of the is_built() which sort of points me in the direction
of thinking that the latter assertion is true (gadget named so-and-so
exists).
Clearly, I had to change the way I used is_built() method in my code.
My immediate suggestion for improvement was to
treat is_built() as a class method instead of
as an per-object method. The problem is Perl
is in no way as strict as C/C++ when it comes to
these matters. Despite of this, I at times find
myself frustrated over a piece of code that doesn't
quite conform to common standards (logic).
In this particular script, the
if ($g1->is_built($athing_name)) {
should be instead written as
if (Gadget->is_built($athing_name)) {
And also the is_built() sub has to be modified
to this:
sub is_built {
my ($class, $name) = @_;
# return if dealing with a reference...
# note: not tested ;)
return if (ref $class eq '__PACKAGE__');
. . .
# do stuff if this sub is called ast a class
# method.
...
}
since as far as the purpose and design of the
imagined class goes, this method has no buisiness
inside an object. When is used as a per-object
method, it implies a weak (or confusing) logical
statement. Frankly, I find it hard to frame
original line in a clear statement of logic.
UPDATE: thanks
Fletch for your comment, i fixed is_built() now (I forgot to update the post since I added a similar change to my script.. as i did in fact broke my script with the first implementation of is_built() :).
|
"There is no system but GNU, and Linux is one of its kernels." -- Confession of Faith
|