Well, I disagree strongly that you should avoid OO just because the code
is small. Just yesterday I wrote an OO module that was under 20 lines.
At this point, since you've not shown the need for inheritance
implementation reuse or even interface reuse, I'd stay away from the
complexity of objects. My personal rule is not to pull in OO technology
in Perl until the line count of the program exceeds about 1000 lines, and
using all the OO features of abstraction, inheritance, and data hiding
all becomes useful.
Well, I find that implementation reuse and inheritance are way over
emphasized in OO and almost never happen (outside of standard
libraries that get shipped with the language). Although I see a small
percentage of objects that do interface reuse (via inheritance), the
majority don't do any of those things.
In Perl the most common big advantages I see from OO are reduction of
namespace collisions and simplified compartmentalization of configuration
settings (my other favorite is cleaning up via destructors, but not all objects involve such). Here we want cascading defaults (ie. compartmentalization
of configuration settings), which is done very nicely and naturely in
Perl OO (I've never noticed it being done nicely in Perl in the absense
of OO). I find that using Perl OO almost gives you cascading defaults
without even trying.
Have a package global that contains the default configuration parameters.
Have a constructor that copies the configuration parameters from the
package or object that was used to call it. Provide methods for changing
configuration parameters (but only on constructed objects, not on the
package global of sane defaults). (Heck, if writing methods seems like
too much work, you can let the module user directly set the parameters
using $obj->{param_name} -- though I think you'd be wrong
both in thinking that writing methods is too much work and in encouraging
such unverified manipulation of your object's members.)
If you want script-level defaults, then you can also make this easy by
making it easy to export/import a default error object for the script
(see below).
Also, a package that starts out at 20 lines could eventually grow to over
1000. Retrofitting OO at that point would be a huge pain. I wouldn't
necessarilly start all projects as OO modules. But once you get to the
point that you see a need to use the code from multiple scripts and that
therefore it makes sense to turn it into a module, then I think it also
usually (in Perl) makes sense to put in OO.
package Err;
use base qw( Exporter );
use Carp qw( croak );
my( %defaults, @options );
BEGIN {
%defaults= (
Title => 'An error has occurred',
Message => 'If error persists, seek assistance',
);
@options= keys(%defaults);
}
sub new {
my $this= shift; # Either a package name or an object.
croak 'Usage: $handle= ',__PACKAGE__,"->new();\n",
' or: $handle= $ErrHandle->new()',"\n"
if @ARGV;
my $class= ref($this) || $this;
# Copy defaults from calling object or use standard defaults:
my $obj= ref($this) ? {%$this} : {%defaults};
return bless $obj, $class;
}
sub import {
# Export a unique $ErrHandle to each caller:
my $uniq= $_[0]->new();
*ErrHandle= \$uniq;
goto &Exporter::import;
}
sub Configure {
my( $self, $opts )= @_;
croak 'Usage: $ErrHandle->Configure( ',
'{ Title=>"new title", Message=>"new msg" } )', "\n"
unless 2 == @ARGV && ref($opts)
&& UNIVERSAL::isa($opts,"HASH");
my @err= grep { ! exists $defaults{$_} } keys %$opts;
croak __PACKAGE__,"::Configure: Unknown option(s) ",
"(@err) not (@options)\n"
if @err;
@{$self}{keys %$opts}= values %$opts;
return $self;
}
Now add a method that actually reports the error (you just had "do something"
in your example). And you use it like this:
use Err qw( $ErrHandle );
# Set script-specific defaults:
$ErrHandle->Configure( {Message=>"Contact technical support"} );
# Use script defaults:
$ErrHandle->Report(...);
# Set and use other configurations:
my $accountingErrHandle= $ErrHandle->new()->Configure(
{Message=>"Please notify Bob"} );
$accountingErrHandle->Report(...);
Note that you can now add a new configuration parameter by just adding
one line specifying the name and default value for it. At 40 lines, it
is more complex than what we started out with. But a lot of that has
to do with the request for script-level defaults and some nice things
I added like croak()ing when a method is called incorrectly.
In summary, I think you can write very small but reasonable OO modules
when you have something that starts out very simple but that you want to
use several places. I think that in the long run you'll be glad you
did start out with OO.
Update: Fixed unmatched quotes in my
still-thoroughly-untested sample code. Actually, I was
forced to test the exporting of a unique scalar stuff
before posting since I'd never actually done that before
(actually).
-
tye
(but my friends call me "Tye")
|