我什么时候应该使用`use`?

时间:2010-10-22 13:37:58

标签: perl perl-module moose

只要我记得,每当我使用模块时,我都会在代码的开头添加use行。

最近我写了两个相互使用的Moose对象模块。看看这个过于简单的例子:

一个模块:

package M1 0.001;

use Moose;
use 5.010;
use namespace::autoclean;
# use M2; ### SEE QUESTION BELOW

has 'name' => (
 is       => 'ro',
 isa      => 'Str',
 required => 1,
);

has 'very_cool_name' => (
 is      => 'ro',
 lazy    => 1,
 builder => '_build_very_cool_name',
);

sub _build_very_cool_name {
 my ($self) = @_;
 my $m2 = M2->new( m1 => $self );
 return 'very ' . $m2->cool_name();
}

__PACKAGE__->meta->make_immutable;

1;

另一个模块:     包M2 0.001;

use Moose;
use 5.010;
use Data::Dumper;    # TODO DEBUG REMOVE
use namespace::autoclean;
use M1;

has 'm1' => (
 is       => 'ro',
 isa      => 'M1',
 required => 1,
);

sub cool_name {
 my ($self) = @_;
 return 'cool ' . $self->m1->name();
}

__PACKAGE__->meta->make_immutable;

1;

一个使用它们的简短例子:

use strict;
use warnings;
use 5.010;
use M1;
use M2;

my $m1 = M1->new(name => 'dave');
say $m1->very_cool_name();

现在,请注意这两个模块互相使用。 M1创建M2的实例并使用它生成very_cool_name,而M2的实例为M1作为属性。

现在,如果我在use M2;取消注释M1,我的日食会发疯。我想这是因为这是一个循环使用的循环。

我评论了这个use,一切似乎都很好(我想......),但让我非常焦虑(我正在使用一个没有use的对象 - 它的类!是的'法律'?..)。这也让我想知道:

  • 我何时才需要使用use?我认为我被教导要经常使用它,当然我使用的是对象。

  • 当两个模块互相使用时(从某种意义上说,每个模块都使用另一个模块的对象),是否有任何根本错误;我知道在某些情况下这在逻辑上是不可能的,但有时 - 在这种情况下 - 我认为这确实有意义。)

2 个答案:

答案 0 :(得分:3)

从Perl的角度来看,没关系。 use足够聪明,可以识别模块已经加载而不再加载。也就是说,微弱的代码气味应该会让你思考相互依赖是否可以接受,或者你是否应该重构你的代码来消除它。

显然,Eclipse并不那么明亮。注释掉其中一个use语句来安抚编辑器可能可以工作,但可能会产生微妙的错误,具体取决于模块加载的顺序(由应用程序)以及何时使用彼此功能。例如如果首先加载M1,则不use M2,并且有BEGIN块需要M2的功能......繁荣!如果在运行之前没有任何事情发生(可能),你应该没问题。

虽然这不是问题,但如果您从其他包中导入use符号,也会遇到问题。在这种情况下,无法删除use而不更改您的代码以完全限定所有引用。 (例如,请致电MyModule::function()而不是function()

答案 1 :(得分:2)

M2没有理由use M1。你实际上没有递归依赖。

所有M2都会验证某个对象的类名 - 它不需要加载M1 - 并在其上调用一个方法 - 这意味着构造该对象的任何人都加载了M1。

关于为了在该类的对象上调用方法而需要use类的规则是错误的。当你要直接调用方法时,use一个类 - 例如new。 (这假定纯OO模块,显然不是导出函数/符号的东西。)

考虑多态性。这是一个特征,我可以创建我自己的M1子类(称为M1A)并将其传递给M2,而不需要知道有关M1A存在的任何信息。