我正在构建我的第一个Perl模块,我想知道在您自己的模块中加载模块的最佳做法是什么。我确实阅读了this answer,但它似乎谈到了单个文件项目。
我开始只是在主文件中加载项目中我需要的所有模块(让我们称之为MyModule.pm
),如下所示:
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;
但后来我意识到并非所有模块(或子程序/方法)都是必需的。例如,File::Path
可能仅在模块的单个方法中需要,该方法具有自己的文件(例如MyMethod.pm
)。我会use
中的不 MyModule.pm
File :: Path,但仅限于MyMethod.pm
此外,是否应该将其扩展到子例程的特定use
个?例如,假设我需要在MyModule.pm和MyMethod.pm中使用catdir
,但在AnotherMethod.pm中使用catfile,我也会将其拆分吗?我假设Perl只会忽略一个子程序,如果它已经被导入但是我在询问常见的做法。我会这样做吗?
# MyModule.pm
use File::Spec qw(catdir);
...
# MyMethod.pm
use File::Spec qw(catdir);
...
# AnotherMethod.pm
use File::Spec qw(catfile);
...
或者更确切地说
# MyModule.pm
use File::Spec qw(catdir catfile);
...
# MyMethod.pm
use File::Spec qw(catdir catfile);
...
# AnotherMethod.pm
use File::Spec qw(catdir catfile);
...
甚至只是
# MyModule.pm
use File::Spec qw(catdir catfile);
...
对我来说,将它们分开似乎很好,就像在第一个例子中那样。这样,您可以立即看到每个文件的依赖关系。但是我想知道这个典型的'Perl风格'是什么,或者是否有任何这些例子的上升/下降。
答案 0 :(得分:0)
我认为一个好的一般原则是be specific(我将Peter Norvig和Kent Pitman的幻灯片与他们关于Lisp编程良好风格的教程相关联:有一些特定于Lisp的部分,但也有很好的一般性建议)。
这意味着在一个多文件项目中,每个模块都应该在最狭窄的范围内使用(我的意思是范围文件)。在顶级软件包中加载模块会违反这种特殊性原则,因为它们并非特定需要。
话虽如此,我认为我们可以扩展此标准以将符号导入名称空间。我的意思是你的例子中的这种风格:
# MyModule.pm use File::Spec qw(catdir); ... # MyMethod.pm use File::Spec qw(catdir); ... # AnotherMethod.pm use File::Spec qw(catfile);
此双use
中没有暗示效率低下。为了解释原因,我们需要检查它的工作原理。
use Module qw/ foo bar baz /;
大致相当于:
require Module;
Module->import( qw/ foo bar baz / );
require
加载并编译模块当且仅当之前未加载时(为此,它会检查特殊哈希的状态{ {1}}:您可以在documentation for require
。
%INC
将被调用三次(import
中的一个,MyModule
中的一个和MyMethod
中的一个),但由于单向或某种方式,它无法绕过它其他我们需要在每个包中都有这些符号。
仅导入所需内容也是记录模块/意图/的一种形式,它也可以使视角更容易进行重构。