|No such thing as a small change|
Re: is autoload bad style?by ihb (Deacon)
|on Jul 26, 2003 at 18:39 UTC||Need Help??|
Update: As adrianh and Aristotle pointed out there is a module, NEXT, to cope with this. But NEXT has some issues of its own and is slow. (See "Bugs and irritations" in the documentation.) Having to pull in another module just proves my point: unless you really need AUTOLOAD, try to stay away from it. It may very well create more problem than it tries to solve.
I've never really needed AUTOLOAD, although I've found some nifty (and "useful") uses for it. (That doesn't mean there aren't any cases where it is needed.)
I try to avoid AUTOLOAD in object oriented code. There are two subtile traps that I'll try to explain here. The problem applies to all AUTOLOADs that don't want to do anything useful for all invokations of it. As example I'll use the popular concept of autogenerating attribute methods, which is particulary nice as an example as there would be no problems if the methods was pre-generated instead. (See Re: Re: is autoload bad style? for an elaboration on this.)
This is your standard attribute AUTOLOAD routine customized to illustrate my point. It works as expected:
Now let's inherit Foo, and use the same technique in the child.
This too seems to work as expected:
But it doesn't quite work right when trying to use Foo's attributes:
So apparently we need to patch &Foo::Bar::AUTOLOAD.
Now it's suddenly not that pretty anymore, and not fully transparent. There is a caller backtrace issue. An error message about missing attribute will probably (and should, imho) point at the return line in &Foo::Bar::AUTOLOAD rather than where it really is invoked by the programmer. You could wrap the call in an eval BLOCK and propagate the error. But I wouldn't call that elegant.
We can't use goto(), because then $AUTOLOAD won't be set in the target &AUTOLOAD. You could perhaps manually find where SUPER::AUTOLOAD is, and manually set $AUTOLOAD. But then it gets even uglier.
As a parenthesis: return if $m eq 'DESTROY'; is bad in the general case if we should be strict. There's no guarentee that no super-autoload wants to deal with it.
For me, this is enough to avoid AUTOLOAD and think of it as the very last resort.
But wait, there's more.
This problem has to do with multiple inheritance. We start by defining two simple classes that use AUTOLOADed attribute methods, as above. As in issue 1 this issue applies to all AUTOLOAD routines that have some criteria for when it should do anything useful.
Just as before, they seem to work alright:
Now, let's inherit both A and B.
Now we expect both AB::->xism and AB::->yism to work.
But nope. The explanation is that there's no way for an AUTOLOAD to tell perl that "oh, no, sorry, ignore me". Perl never gets a chance to discover &B::AUTOLOAD.
I consider these two issues quite severe, and therefore I tend to frown upon AUTOLOAD.
If one takes these two issues into consideration the coolness of AUTOLOAD is reduced--at least for me. I'm not totally anti-AUTOLOAD but I think it should be used with caution.Hope I've helped,