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

Whether this is purely arbitrary, or following a specific format for, e.g., plugins, how do you load a module whose name is in a string? I'm also mostly thinking of OO-style modules where importing is not simply unnecessary, but undesirable. Arbitrarily loading strict is somewhat of a waste.

Off the top of my head, I see three basic code approaches. I'm not including checks for loading success since they're basically the same everywhere. I'm also not including how $module is determined since that, too, doesn't change here, e.g., you could be getting it from a template a la Template Toolkit, and then putting "Template::Plugin::" in front, or it could be a command-line parameter, or both (such as ack), or any number of other options.

eval "use $module"; my $obj = $module->new($options);
Simply use the perl interpreter to interpret and run the exact code that you would type in if it were a static module name. Straight-forward, and, from what I can tell, it's also the most common approach. Calls $module->import under the covers which is likely unnecessary, perhaps polluting your namespace if the module does export stuff, which seems to me as it may introduce a surprise under some circumstances. And, in general, has all the downsides of eval STRING: code injection. Admittedly, there are ways around that, but I rarely see anyone try.
eval "require $module"; my $obj = $module->new($options);
Same as before, but avoids importing anything. I rarely see this.
(my $filename = $module) =~ s[::][/]g; $filename .= '.pm'; eval { require $filename }; my $obj = $module->new($options);
Avoids eval STRING horrors. Probably is faster than re-invoking the perl interpreter for figuring out what to use, but that also probably gets swallowed up by re-invoking the perl interpreter to parse/compile the module itself, so speed probably is not a significant factor. Avoiding code injection would be. Also, since this is a require, like the previous option, it's more obvious that importing is not happening. Disadvantage is that it's extra code that the perl interpreter would do for you if you were using an eval STRING.
So, my questions are:
  1. What format do you use today, if any?
  2. If this node is making you think about it more than you have, which format are you now thinking of using?
  3. What would you recommend to others?
  4. Why? i.e., Why were you using the format you were using, if any; why are you thinking of changing, if you are; why would you make that recommendation, especially if it's different from what you'll use in the future?

Just looking to broaden my thought processes. :-)

Thanks!

Replies are listed 'Best First'.
Re: Loading arbitrary modules
by ikegami (Patriarch) on Mar 16, 2010 at 16:00 UTC

    Two minor comments.

    • Using "/" in the last snippet is portable. It works in all three supported systems (unix, Windows and VMS).

    • You mentioned code injection for the first two, but not the last even though it's also vulnerable. While it is safer, it does allow execution of arbitrary locally accessible .pm files with a known absolute path or a known relative path (wrt the current work dir).

Re: Loading arbitrary modules
by Anonymous Monk on Mar 16, 2010 at 17:13 UTC
Re: Loading arbitrary modules
by shmem (Chancellor) on Mar 16, 2010 at 20:05 UTC
    And, in general, has all the downsides of eval STRING: code injection.
    ...
    Avoids eval STRING horrors.

    What is it that's so horrific about string eval? At the bottom of any file inclusion there's eval STRING! Perl has taint mode.

    Your third example

    (my $filename = $module) =~ s[::][/]g; $filename .= '.pm'; eval { require $filename }; my $obj = $module->new($options);

    isn't any bit less frightening, since nothing is done to remove '.' from @INC ...

    That said, I a) use the first two forms mostly, the third form only if I have to construct non-standard paths; b) I'm feeling happy with that; c) I'd recommend "that what fits best"[tm] and d) uhm, well, there's TIMTOWDTI, laziness, and such... ;-)

Re: Loading arbitrary modules
by dsheroh (Monsignor) on Mar 17, 2010 at 11:00 UTC
    Personally, I don't think I've ever needed to use/require a single, specific module whose name is not known when I write the code, so I've never had cause to do quite what your examples illustrate.

    When I am loading modules which can't be pulled in with just a plain, eval-free use, I'm grabbing everything in the Foo::Bar::* namespace (they're usually plugins or something similar), so I use Module::Pluggable to handle it:

    use Module::Pluggable instantiate => 'register', search_path => ['Foo::Bar']; { my @plugins = plugins(undef, $hooks); }