获取并特别设置Perl模块的全局变量是否合适?

时间:2010-05-27 16:24:10

标签: perl coding-style encapsulation perl-module

我想知道Perl的最佳实践是关于获取 - 或者更重要的是,通过直接访问$Module::varName来设置 - 某个模块的全局变量,以防模块没有提供getter / setter方法它

它对我来说闻起来不好的原因是它有点绕过封装。仅仅因为我可以在Perl中执行它,我不完全确定我应该(假设实际上有一个替代方法,例如向模块添加getter / setter)。

4 个答案:

答案 0 :(得分:8)

如果变量是公共API的一部分,则不会违反封装。 (如果这不是另一回事。)

我认为直接访问更可取,因为它允许您利用动态范围:

local $Module::varName = 42;

这与使用Module的其他代码冲突的可能性较小。

答案 1 :(得分:2)

全球模块变量在过去很流行,但在“现代Perl”中被视为“坏形式”的接口。重要的是要认识到Perl现在已经有22到23岁了,风格和做法也发生了变化。 :)请注意,有时它仍然适用,因为有一些非常好的功能与包变量一起出现。通常需要经验和实践才能看到一个好的解决方案。

要了解包变量的最佳用法,您真的需要了解local的工作原理。查看local's perldoc help。 Local允许您在包$My::Variable中使用包变量(例如)My,并创建它的dynamically scoped版本。通常,如果您更改$My::Variable,它将影响您的整个程序,并将持续存在。对于小型程序,这可能不是什么大问题。对于大型,这可能会产生灾难性的副作用。 local允许您临时更改该变量,该变量仅限于您当前的范围。

以下是它的工作原理:

use 5.012;
use warnings;

package My;

our $Variable = 5;

package main;

say $My::Variable; # prints 5
$My::Variable = 7;
say $My::Variable; # prints 7
{  # create a new lexical scope
    local $My::Variable = 10; # create a new dynamic scope for $My::Variable
                              # that will persist to the end of the lexical scope
    say $My::Variable;  # prints 10
}
say $My::Variable;  # end of the lexical scope for the localized
                    # $My::Variable, so prints 7 again

实际上,它允许您以安全的方式使用包变量。不幸的是,不是每个人都知道本地,所以他们经常破坏全局变量。记录良好用途(例如,local)总是有帮助的。

具有适当对象封装的getter / setter可以防止很多这种情况,但并非总是如此。为了使它像局部变量一样工作,你必须做很多额外的工作。能够本地化一个包变量的最好的事情是你可以非常容易地进行临时更改,例如,调试变量。通常,您必须执行以下模式:

{
    my $current_variable  My::get_variable();
    $My::set_variable($new_value);

    # Do code work

    $My::set_variable($current_variable);
}

对于本地,这变为:

{
    local $My::Variable = $new_value;

    # do code work
}

(顺便说一句,我希望你也可以对词汇变量这样做,出于同样的原因......但你不能。)所以,对于某些事情,包变量可以有意义。这取决于你想如何使用它。像

这样的事情
  • 调试变量
  • 不经常/不应经常更改的全局配置

但是,如果确实需要定期更改,

  • 经常使用的变量(参见File::Find的可怕界面)
  • 临时配置
  • “对象”变量

基本上,任何需要多次修改或在极少数情况下修改的内容,或者应该封装到生成的对象中的内容,我都会避免使用包变量。

答案 2 :(得分:1)

如果模块没有提供访问者,请创建一个,使用它,然后发送补丁。

答案 3 :(得分:-2)

输入 - 卫生/错误处理不是封装的全部内容吗?

如果没有必要,那么可以反对实施getter和setter,这样看起来就像sub set_variable { $variable = shift; }一样愚蠢。

请注意,使用set_variable(42)比使用Michael建议的内容更容易!