in reply to Re: Using AUTOLOAD to create class methods
in thread Using AUTOLOAD to create class methods

Hm, yes, I am aware of the potential problems with AUTOLOAD. The approach above does work -- but it has one problem that the use of AUTOLOAD solves: I want to always have all of a DBH's methods sent to my DBH. So, it looks like I'm faced with a tradeoff.

On the one hand, I could do as you suggest above, but I'd have to maintain a list of the methods on my {DBH} attribute. If I miss one, then I have a bug. This also raises the complexity of my test suite.

On the other hand, I could continue to use AUTOLOAD, and deal with the issue. My current version of the AUTOLOAD sub:

# sets up autoload subs that 'inherit' DBI's DBH methods sub AUTOLOAD { my $op = $AUTOLOAD; my $self = shift; $op =~ s/^.*:://; if ( DBI::db->can($op) ) { # create a wrapper for a DBH method eval "sub $op { return shift->{DBH}->$op(\@_); }"; $op->($self, @_); } elsif ( $op =~ /^_/ ) { # return the appropriate attribute $op =~ s/^_//; exists $self->{$op} && return $self->{$op}; return $self->error("Can't autoload for attribute _$op"); } else { return $self->error("Cannot autoload $op"); } }

I don't worry too much about the security of my eval in this case, since this is a module, and doesn't directly process user input. My scripts never use user input to pass to AUTOLOAD either. Finally, I don't eval anything until I've checked that it's a DBH method. That, all in all, seems pretty safe, though I'd love to be enlightened if I'm missing something there.

I like the idea of Class::Delegator (and, actually, it solved another issue I've been pondering recently, so thanks!), but I'm wondering if there's a way to get the important feature that AUTOLOAD is providing me (making all of the DBI dbh methods available) without the issues AUTOLOAD raises.

Any ideas?

<-radiant.matrix->
A collection of thoughts and links from the minds of geeks
The Code that can be seen is not the true Code
"In any sufficiently large group of people, most are idiots" - Kaa's Law

Replies are listed 'Best First'.
Re^3: Using AUTOLOAD to create class methods
by Ovid (Cardinal) on Nov 03, 2005 at 23:32 UTC

    There's no way you can do it perfectly reliably without AUTOLOAD because of Perl's poor introspection. And, as you note, if you miss a method you have a bug. You can either publish which methods you support (thus turning the bug into a "feature") or have your AUTOLOAD handle it. You might want to just check can (which returns a code ref). The following untested bit might help:

    if (my $sub = $self->{DBI}->can($op)) { no strict 'refs'; *$op = $sub; }

    You'd have to customize that for your needs, but it has the benefit of installing the subroutine directly into your namespace so you only take the AUTOLOAD hit on the first call.

    Cheers,
    Ovid

    New address of my CGI Course.

      Do you have any information that compares getting repeated hits to AUTOLOAD vs once and losing the method cache?

        I'm not sure what you mean by "once and losing the method cache". Perhaps there's something I didn't read in the thread.

        AUTOLOAD tends to be slow as Perl must walk through the inheritance tree (if any beyond UNIVERSAL) and search for an appropriate method. Then Perl goes back to the top and looks for AUTOLOAD methods. If it finds one (and you hope it's the right one if there's more than one), then Perl has to execute your AUTOLOAD code prior to getting to the correct method call. Whether or not this is a significant hit depends upon the how frequently AUTOLOAD is going to get called in your application.

        Cheers,
        Ovid

        New address of my CGI Course.