ELISHEVA has asked for the wisdom of the Perl Monks concerning the following question:
While playing around today with the combination of eval and require, I've discovered that require adds the modules it finds to %INC whether or not they can be fully compiled..
Since some modules don't tolerate repeated reloading and a broken module may compile partially (e.g. BEGIN blocks that make resource intensive DB connections), this makes perfect sense. We don't want to reload modules over and over, whether broken or not.
However, it has one not-so-nice side effect: I can't reliably use require to tell if a module is successfully loaded. My most common use of eval("require $module") is to dynamically include plugins. In general, I only want to enable functionality if the plug-in module compiles successfully.
All will be well and good if my call to eval("require $somePlugIn") just happens to be the first attempt to require this particular module and often it is. On the first attempt eval "require $somePlugIn" obligingly sets $@ to a list of compilation problems. However, successive calls only test to see if $somePlugIn is in %INC and, of course, return true.
The problem comes when a plug-in module is used in more than one place. Two scenarios come to mind: (a) two independently developed parts of an application rely on the same plugin or (b) the module is loaded via Test::More::require_ok and also in the modules being tested. The second scenario actually occurred earlier this afternoon and is the motivation for this question. A call to Test::More::require_ok gave me a false "ok" because it came after a use statement for a module that had also called require for the same plug-in.
When two different location in code, try to require the module, the first place to require it sees the error, but other places that try to require it dynamically via eval "require $somePlugIn ..." do not. They only see the true return value.
Now I could try to prevent problems by setting up my own special version of require. Before trying to load the module using CORE::require, it checks to see if the module is in the broken list and if so returns the original error rather than try to reload it. But this seems rather leaky to me: I can't guarantee that every module will use my special version of require: any module loaded before the module that contains the definition of the special require will use CORE::require, not my special function, and won't get added to my %BROKEN list.
I could also try social controls: A team decision that thou shalt use module Foo::Bar to load all plugins. But that only addresses code developed in house. It increases the likelihood that clients writing their own plug-ins will make a mistake that interferes with our ability to track broken modules. It limits our use of 3rd party modules since they don't necessarily play by our rules (e.g. Test::More). Even in-house social controls are not the perfect solution. Mistakes happen and tracking them down is time consuming. The "shape up or ship out" attitude isn't really the best approach either. Firing repeat offenders isn't really an option if they do a lot of other things "just right".
I am wondering if there is a non-hackish way to tell if a particular module in %INC compiled successfully. By non-hackish, I mean that:
I'm hoping someone will tell me that there is some sort of internal table I can get access to rather than maintaining my own %BROKEN table. Or that maybe someone who knows more than I can suggest a non-leaky way to wrap CORE::require so that I can keep my own table. Or even some totally different approach that makes this a non-problem.
Thanks in advance, beth
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Detecting broken modules
by moritz (Cardinal) on Jun 29, 2009 at 20:19 UTC | |
by ELISHEVA (Prior) on Jun 29, 2009 at 20:43 UTC | |
|
Re: Detecting broken modules
by ikegami (Patriarch) on Jun 29, 2009 at 21:01 UTC | |
by ELISHEVA (Prior) on Jun 30, 2009 at 04:24 UTC | |
|
Re: Detecting broken modules
by moritz (Cardinal) on Jun 30, 2009 at 16:45 UTC | |
|
Re: Detecting broken modules
by Anonymous Monk on Jun 29, 2009 at 22:20 UTC | |
by ELISHEVA (Prior) on Jun 29, 2009 at 22:30 UTC | |
by Porculus (Hermit) on Jun 30, 2009 at 22:32 UTC | |
by Anonymous Monk on Jun 30, 2009 at 12:44 UTC | |
by ELISHEVA (Prior) on Jun 30, 2009 at 13:15 UTC | |
by Anonymous Monk on Jun 29, 2009 at 22:22 UTC |