1

I am building my first ever Perl module, and I am wondering what the best practice is of loading modules in your own module. I did read this answer, but it seems to talk about single file projects.

I started out by simply loading all modules I'd ever need in the project in the main file (let's call it MyModule.pm), like so:

use Config::IniFiles;
use File::Spec qw(catdir catfile curdir);
use File::Path qw(remove_tree);
use File::Basename qw(fileparse dirname);
use Cwd qw(abs_path);
use XML::Twig;
use Getopt::Long;

But then I realised that not all modules (or subroutines/methods) are always necessary. For instance, it is possible that File::Path is only required in a single method of the module, which has its own file (e.g. MyMethod.pm). Would I then not use File::Path in MyModule.pm, but only in MyMethod.pm

Furthermore, should this be extended to specific use'ing of subroutines as well? For instance, let's say I need to use catdir in MyModule.pm and MyMethod.pm, but catfile in AnotherMethod.pm, would I split that up as well? I assume that Perl will just ignore a subroutine if it's already been imported but I am asking about the common practice. Would I do this?

# MyModule.pm
use File::Spec qw(catdir);
...
# MyMethod.pm
use File::Spec qw(catdir);
...
# AnotherMethod.pm
use File::Spec qw(catfile);
...

Or rather

# MyModule.pm
use File::Spec qw(catdir catfile);
...
# MyMethod.pm
use File::Spec qw(catdir catfile);
...
# AnotherMethod.pm
use File::Spec qw(catdir catfile);
...

Or even simply

# MyModule.pm
use File::Spec qw(catdir catfile);
...

To me it seems nice to split them up, as in the first example. That way, you immediately see what the dependencies for each file are. But I am wondering what the typical 'Perl style' for this is, or if there are up/downsides of any of these examples.

Bram Vanroy
  • 27,032
  • 24
  • 137
  • 239
  • (1) Include only what is needed in each module (2) You can `require Mod; Mod->import(qw(...));` inside that sub so it goes at runtime thus only if the sub runs. Bad: you don't see that `Mod` is used by glancing at the top of the file; importing at runtime may differ for some modules, and imply different use, see [this Q](https://stackoverflow.com/q/41094774/4653379). Your call, I'd say. I do load modules at runtime, when they are heavy and indeed used infrequently. Note, this relieves compilation time (every time) on the account of some runtime overhead (only when it happens). – zdim Jul 27 '17 at 19:13

1 Answers1

0

I think a good general principle is be specific (I linked Peter Norvig's and Kent Pitman's slides for their tutorial on Lisp programming good style: there are parts specific to Lisp but also good general advices).

This means that in a multi-file project each module should be use'd in the most narrowest scope (I mean scope file-wise) where they're needed. Loading modules in the top package would violate this specificity principle, because they are not specifically needed there.

That being said, I think we can extend this criteria to importing symbols into namespaces. I mean this style from your example:

# MyModule.pm
use File::Spec qw(catdir);
...
# MyMethod.pm
use File::Spec qw(catdir);
...
# AnotherMethod.pm
use File::Spec qw(catfile);

There are no inefficiencies implied in this double use. To explain why, we need to examine some details of how it works.

use Module qw/ foo bar baz /;

is roughly equivalent to:

require Module;
Module->import( qw/ foo bar baz / );

require loads and compiles the module if and only if it has been not loaded before (to do so it examines the status of the special hash %INC: you can read more details in the documentation for require.

import will be called three times (one in MyModule, one in MyMethod and one in AnotherMethod), but there's no way around it because one way or the other we need to have those symbols in each package.

Importing only what is needed is also a form of documenting the /intentions/ of your module, and it could also make refactoring easier, in perspective.

larsen
  • 1,431
  • 2
  • 14
  • 26