Search code examples
perl

Using a module or a feature in another package than where it is supposed to be used


According to Perl::Critic::Policy::Modules::RequireExplicitPackage :

In general, the first statement of any Perl module or library should be a package statement. Otherwise, all the code that comes before the package statement is getting executed in the caller's package, and you have no idea who that is.

Now Object::Pad suggests to break this rule, see: https://metacpan.org/pod/Object::Pad#File-Layout :

Begin the file with a use Object::Pad line; ideally including a minimum-required version. This should be followed by the toplevel package and class declarations for the file.

I believe the same is suggested for the new class feature, see https://github.com/Perl/perl5/blob/blead/pod/perlclass.pod, see e.g. the synopsis example there.

Is there any drawbacks to this approach? I guess any problems could be worked around by using the following file layout:

package MyClass; # ensure that Object::Pad is loaded within the `MyClass` package
use Object::Pad;
class MyClass;
...

instead of using this file layout

use Object::Pad;
class MyClass;
...

I am not sure why the documentation for Object::Pad suggests the latter file layout, or if it is even a problem. It would be great if someone could clarify this issue.


Solution

  • When you load a module, you want to find the correct import. You want to find the correct subs loaded by the module. etc. The lack of package directive matching the use statement is a strong sign that there's a problem.

    Obviously, this check isn't flawless. Like you said, the policy doesn't accommodate Object::Pad or the new class feature.

    But, there are two things that uses the package directive directly. There's the policy in question, obviously. And there's CPAN. The indexer searches the source for package PackageName;. So including the package directive will help there.

    And no, I don't see why Object::Pad would care from what package it was invoked, unless it has a check that prevents it from populating an existing package, a check you would already have discovered. Keep in mind that if you don't include the package, the code is executed in the namespace of the caller, which could be anything. So Object::Pad is obviously not picky about that.