【问题标题】:Management of imported modules in module consisting of multiple files管理由多个文件组成的模块中的导入模块
【发布时间】:2018-01-03 11:22:09
【问题描述】:

我正在构建我的第一个 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 File::Path in MyModule.pm,但只在MyMethod.pm

此外,这是否也应该扩展到特定的use'ing 子例程?例如,假设我需要在 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 风格”是什么,或者这些示例是否有优点/缺点。

【问题讨论】:

  • (1) 仅包含每个模块中需要的内容 (2) 您可以在该子程序中 require Mod; Mod->import(qw(...)); 以便它在运行时运行,因此只有在子程序运行时才会运行。不好:您看不到文件顶部的Mod 被使用;某些模块在运行时导入可能会有所不同,并暗示不同的用途,请参阅this Q。你的电话,我会说。我确实在运行时加载模块,当它们很重并且确实不经常使用时。请注意,由于一些运行时开销(仅在发生时),这会减少编译时间(每次)。

标签: perl module


【解决方案1】:

我认为一个很好的一般原则是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 加载并编译模块当且仅当它之前加载(为此它检查特殊哈希%INC 的状态:您可以在documentation for require阅读更多详细信息。

import 将被调用 3 次(MyModule 中的一个,MyMethod 中的一个和 AnotherMethod 中的一个),但是没有办法绕过它,因为我们需要将这些符号放入其中每个包。

仅导入需要的内容也是一种记录模块的 /intentions/ 的形式,从角度来看,它还可以使重构更容易。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-28
    • 2022-12-10
    • 1970-01-01
    • 2017-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多