8

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

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

4

3 回答 3

9

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

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

local $Module::varName = 42;

这使得与其他代码使用冲突的Module可能性降低。

于 2010-05-27T16:28:05.280 回答
2

全局模块变量在过去很流行,但在现代 Perl 中被认为是“糟糕的形式”作为接口。重要的是要认识到 Perl 现在已经 22-23 岁了,风格和实践已经发生了变化。:) 请注意,有时它仍然是合适的,因为包变量附带了一些非常好的特性。像往常一样,看看什么是好的解决方案可能是经验和实践的问题。

要了解包变量的最佳用途,您确实需要了解其local工作原理。查看localperldoc 帮助$My::VariableLocal 允许您使用 package中的包变量(例如)My,并创建它的动态范围版本。通常,如果您更改$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
  • 临时配置
  • “对象”变量

基本上,任何需要修改不止一次或在极少数情况下,或者应该以其他方式封装到生成的对象中的东西,那么我会避免使用包变量。

于 2010-05-27T16:38:05.747 回答
1

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

于 2010-05-27T17:43:10.530 回答