On Tue, 8 Aug 2000 14:22:20 -0500 , Garrett Goebel wrote:
>What's the conventional wisdom on creating a module that supports both an OO
>and non-OO interface? Are there any CORE or CPAN modules to serve as a
>textbook, or is the anwser "Don't do that"?
>
>I've got some code that checks the first parameter passed to see if it is a
>reference, assumes any reference is an object reference... and then proceeds
>accordingly. -It feels pretty sloppy, but it works.
Gee, I wonder what this is doing on the Perl6 mailing lists. But, maybe
there are some lessons to be learned, so...
My idea is: "Don't do it". Let me point to just one example: CGI.pm.
Probably one of the most used modules, I might add. Open the source, and
scroll down till you find the definition for self_or_default, around
line 317 ($VERSION = 2.56). Oh hell, here it is:
sub self_or_default {
return @_ if defined($_[0]) && (!ref($_[0])) &&
($_[0] eq 'CGI');
unless (defined($_[0]) &&
(ref($_[0]) eq 'CGI' || UNIVERSAL::isa($_[0],'CGI'))
# slightly optimized for common case
) {
$Q = $CGI::DefaultClass->new unless defined($Q);
unshift(@_,$Q);
}
return @_;
}
Excuse me for the rewrapping. This sub is called at the start of every
single method, I think. It serves to distinguish between a plain sub
call, and a class or method call. If it's a method call, the name of the
"default class" is prepended to the arguments list.
This is a bug waiting to happen. Suppose you call it as a function, but
with a literal string:
$x = param('x'); # Will work
$cgi = param('CGI'); # Oops! Major goof here!
It will barf on the latter, because the sub "self_or_default" will think
it is called as a class method, but it isn't.
Lesson to be learned: this is a bug caused by poor design. Perhaps, a
special global variable -- local'ized, of course -- e.g. $SELF, ought to
have been set before the sub is called, to either the object (object
method) or class name (class method); or undef(), if called as a regular
function. The object/class should not have been unshifted unto @_.
Let's do better with Perl6.
p.s. Gee, if Perl6 is going to be so radically different than Perl5,
perhaps we need a new pragma:
use perl6;
or, in contrast:
use perl5;
which could turn on/off the backward compatibility mode.
--
Bart.