talexb has asked for the wisdom of the Perl Monks concerning the following question:

This isn't really a question, more like a comment and an "Anyone else noticed this?" I'm hoping that someone will be able to confirm and/or comment.

After a fair bit of grinding through log files recently, I discovered that one of my scripts was quietly dying because I'd used the right method on the wrong object. So after thinking about Schwern's rant about AUTOLOAD from YAPC 19100's Lightning Talks, I tried the following code:

sub AUTOLOAD { our $AUTOLOAD; return if ( $AUTOLOAD =~ /DESTROY$/ ); # No problem with that. $logger->warn("Tried to call $AUTOLOAD."); }

The objective was that if anything called the right method on the wrong object, AUTOLOAD would catch it. Note that I don't do anything rash if the method ends in DESTROY, but the current development push is over, I'm going to change 'warn' to 'die' and really stress test the system to see if I can find out what causes these quiet deaths.

I'd be interested in hearing if anyone else has noticed this or tried it.

Alex / talexb / Toronto

Life is short: get busy!

Replies are listed 'Best First'.
Re: How many ways are there to use AUTOLOAD?
by shemp (Deacon) on Jul 20, 2004 at 20:23 UTC
    One thing to watch out for with this, and with autoload in general is when you have parent / child classes, if your AUTOLOADs actually handle any method calls. You need to be careful that a child AUTOLOAD doesnt die before a parent AUTOLOAD gets a chance to handle the method properly. For example:
    package parent; ... sub AUTOLOAD { our $AUTOLOAD; return if ( $AUTOLOAD =~ /DESTROY$/ ); if ( $AUTOLOAD eq 'handled_func' ) { # do something return; } $logger->warn("Tried to call $AUTOLOAD."); } ... package child { ... sub AUTOLOAD { our $AUTOLOAD; return if ( $AUTOLOAD =~ /DESTROY$/ ); $logger->warn("Tried to call $AUTOLOAD."); }
    Now if you call handled_func() on a child object, child::AUTOLOAD will *handle* it by logging the warning, when you probably wanted parent::AUTOLOAD to actually deal with the method call

      Interesting point -- as it happens, I'm not using inheritance, so I don't anticipate encountering this problem.

      Alex / talexb / Toronto

      Life is short: get busy!

Re: How many ways are there to use AUTOLOAD?
by mortis (Pilgrim) on Jul 20, 2004 at 21:26 UTC
    I've used this kind of technique over and over in my Perl projects. I go one step further and in addition to logging the mistake, I make it a hard error by throwing an exception (or using confess) so I get a full stack trace so I can see how things got that way. I sometimes use the idiom $obj->$method, so it's not always clear how the incorrect (typod) method name happened by looking only a single stack frame up.

    It would be nice if perl had a 'use strict qw(methods);' mode for detecting as many of these issues as possible at compile time (of course you'd also have to be disciplined about declaring variable types) instead of having to deferr them to run-time.

    I usualy put that kind of AUTOLOAD into the base class for all my objects.

    As far as using AUTOLOAD to do anything else I usualy avoid it as it can make for harder to maintain and understand code in my opinion. There are some places where it can be very useful but I don't find myself using it too frequently (more often I will use code generation for refactorable syntax).

    Kyle

Re: How many ways are there to use AUTOLOAD?
by adamk (Chaplain) on Jul 21, 2004 at 04:21 UTC
    Personally, I use AUTOLOAD for two things.

    Firstly, in Class::Autouse, to enable run-time class loading, normally on a per module basis, but with a fast-and-loose option of hooking it into UNIVERSAL::AUTOUSE and handling any random call

    Secondly, I also use it in some Template Toolkit stuff to catch calls, and then find the property within the context of the call. Basically making TT do what you'd expect it to.

    I'm not sure I understand why you are doing this though? Doesn't perl general errors anyway when you call a method that doesn't exist? Wouldn't just catching and logging the $@ in an eval be exactly what you wanted anyway?

      I use AUTOLOAD when templating too.

      I find that when building an application with CGI::Application, CGI::Session, and HTML::Template I have two types of subroutines:

      • Those that exist to do something, view or update a database.
      • Those that just exist to populate a couple of pieces of information on a static page, like a FAQ.

      The second set of subroutines I handle by having an AUTOLOAD test to see if the application was called with a run mode for which there exists a template. If so it just populates it with "standard" things and returns it.

      Steve
      ---
      steve.org.uk
Re: How many ways are there to use AUTOLOAD? (huh?)
by tye (Sage) on Sep 03, 2004 at 15:46 UTC
    I discovered that one of my scripts was quietly dying because I'd used the right method on the wrong object.

    What are you doing to make this possible? It sounds simply broken to me, but noone else in the thread appears to think so so I must just be out of context.

    My first thought was that this was likely a problem with some misuse of inheritance, but you say "I'm not using inheritance", so I'm at a loss to imagine how you could end up with such a broken situation.

    - tye        

      This morning's problem was that I was calling $document->gDbh when I should have been calling $document->_gDbh. As a result I was getting the error that method "do" was being called on an undefined object, that is, the undefined value coming back from my bad method call.

      For situations where I just called a method but didn't use the return value, I wanted to be sure to catch the typo.

      Alex / talexb / Toronto

      "Groklaw is the open-source mentality applied to legal research" ~ Linus Torvalds

        So how does $document->gDbh not produce the fatal error:

        Can't locate object method "gDbh" via package "...

        ? That is what I don't understand and what seems simply broken to me. That is the error I get when I call the wrong method and I don't have to play strange games with AUTOLOAD.

        - tye