[bop-devel] (eval/AUTOLOAD and the problem as I see it)
Phil Lobbes
phil at perkpartners.com
Wed Aug 30 12:38:13 PDT 2006
Follow up comments from my original email and Ivan's response...
[ ... other text related to patch deleted ... ]
Phil> * get rid of possible use an undefined value as a HASH reference
Phil> * stop redefining subs if they already exist
Phil> - NOTE: it might be nice to do away with this completely and use a
Phil> notion of $self->param('name' => 'value') and
Phil> $self->delete('name') instead of creating subs on the fly. This
Phil> would be a little cleaner design for v3 I would think. It would
Phil> get rid of some (in theory) unnecesary subs and remove some uses
Phil> of eval which might be a little better for performance (probably
Phil> minor but haven't benchmarked to know for sure) and perhaps a
Phil> bit more friendly to people that use mod_perl too.
Ivan> I don't agree we should do away with this completely - I think we
Ivan> should think *really* long and hard about API changes that affect
Ivan> B:OP users / app writers in a backwards-incompatible way.
I agree, but I also don't want to simply concede that we should keep
something because "that's the way it has [always] been".
Ivan> If you felt it was important, perhaps we could get rid of the
Ivan> string eval's without breaking the API or processor modules by
Ivan> using an AUTOLOAD sub?
While I don't love the eval, nor even using AUTOLOAD for this usage.
The bigger issue I see is that we're modifying the class itself and for
people like me when I switch between drivers in mod_perl I don't want
pseudo accessors from another driver getting created for my object and I
doubt any other drivers want mine for that matter. NOTE: At the bottom
of this message you will find some test code to help clarify.
Because of this type of issue I think we're better off changing our way
of dealing with this in a different way and the param()/delete()
paradigm used with CGI, CGI::Application and other modules seems like a
pretty good fit.
Ivan> Why is this unfriendly to mod_perl users? I use B:OP with
Ivan> mod_perl all the time, and this was never a problem for me.
My usage may be a little unique, but hopefully you can relate to why I
dislike this a little more now.
Ivan> My most most annoying peeve with mod_perl usage is when
Ivan> Crypt::SSLeay or Net::SSLeay loads up a different OpenSSL library
Ivan> verison that the one compiled into the web server and the whole
Ivan> thing segfaults without a trace of what happened. :)
That really is annoying, certainly a segfault is worse than a little
namespace pollution :-(.
Phil
Details on the test cases that show namespace pollution...
$ make test TEST_VERBOSE=1
bop_class.t
PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e"
"test_harness(1, 'blib/lib', 'blib/arch')" t/*.t
t/bop_class....1..9
ok 1 - use Business::OnlinePayment;
ok 2 - MOCK1 CLASS can proc1
ok 3 - MOCK1 OBJECT can proc1
ok 4 - MOCK1 CLASS can NOT proc2
ok 5 - MOCK1 OBJECT can NOT proc2
ok 6 - MOCK2 CLASS can proc1 (BAD!)
ok 7 - MOCK2 OBJECT can proc1 (BAD!)
ok 8 - MOCK2 CLASS can proc2
ok 9 - MOCK2 OBJECT can proc2
ok
Code for bop_class.t:
-----------------------------------------------------------------
#!/usr/bin/perl
use strict;
use warnings;
use Test::More tests => 9;
BEGIN { use_ok("Business::OnlinePayment") or exit; }
{ # fake test driver #1
package Business::OnlinePayment::MOCK1;
use strict;
use warnings;
use base qw(Business::OnlinePayment);
}
{ # fake test driver #2
package Business::OnlinePayment::MOCK2;
use strict;
use warnings;
use base qw(Business::OnlinePayment);
}
# trick to make use() happy (called in Business::OnlinePayment->new)
$INC{"Business/OnlinePayment/MOCK1.pm"} = "testing";
$INC{"Business/OnlinePayment/MOCK2.pm"} = "testing";
{ # MOCK1: new (via build_subs) automatically creates accessors for args
my $obj = Business::OnlinePayment->new( "MOCK1", "proc1" => "value1" );
is( ref Business::OnlinePayment::MOCK1->can("proc1"),
"CODE", "MOCK1 CLASS can proc1" );
is( ref $obj->can("proc1"),
"CODE", "MOCK1 OBJECT can proc1" );
is( Business::OnlinePayment::MOCK1->can("proc2"),
undef, "MOCK1 CLASS can NOT proc2" );
is( $obj->can("proc2"),
undef, "MOCK1 OBJECT can NOT proc2" );
}
{ # MOCK2: new (via build_subs) automatically creates accessors for args
my $obj = Business::OnlinePayment->new( "MOCK2", "proc2" => "value2" );
# prove MOCK2 namespace is polluted...
is( ref Business::OnlinePayment::MOCK2->can("proc1"),
"CODE", "MOCK2 CLASS can proc1 (BAD!)" );
is( ref $obj->can("proc1"),
"CODE", "MOCK2 OBJECT can proc1 (BAD!)" );
is( ref Business::OnlinePayment::MOCK2->can("proc2"),
"CODE", "MOCK2 CLASS can proc2" );
is( ref $obj->can("proc2"),
"CODE", "MOCK2 OBJECT can proc2" );
}
More information about the bop-devel
mailing list