我想知道 Perl 中的最佳实践是关于获取 - 或者更重要的是,设置 - 通过直接访问某个模块的全局变量,$Module::varName
以防模块没有为其提供 getter/setter 方法。
它对我来说很难闻的原因是它有点绕过封装。仅仅因为我可以在 Perl 中做到这一点,我并不完全确定我应该这样做(假设实际上有一种替代方法,例如向模块添加 getter/setter)。
我想知道 Perl 中的最佳实践是关于获取 - 或者更重要的是,设置 - 通过直接访问某个模块的全局变量,$Module::varName
以防模块没有为其提供 getter/setter 方法。
它对我来说很难闻的原因是它有点绕过封装。仅仅因为我可以在 Perl 中做到这一点,我并不完全确定我应该这样做(假设实际上有一种替代方法,例如向模块添加 getter/setter)。
如果变量是公共 API 的一部分,则不违反封装。(如果不是那是另一回事。)
我认为直接访问更可取,因为它允许您利用动态范围:
local $Module::varName = 42;
这使得与其他代码使用冲突的Module
可能性降低。
全局模块变量在过去很流行,但在现代 Perl 中被认为是“糟糕的形式”作为接口。重要的是要认识到 Perl 现在已经 22-23 岁了,风格和实践已经发生了变化。:) 请注意,有时它仍然是合适的,因为包变量附带了一些非常好的特性。像往常一样,看看什么是好的解决方案可能是经验和实践的问题。
要了解包变量的最佳用途,您确实需要了解其local
工作原理。查看local
perldoc 帮助。$My::Variable
Local 允许您使用 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
)基本上,任何需要修改不止一次或在极少数情况下,或者应该以其他方式封装到生成的对象中的东西,那么我会避免使用包变量。
如果模块没有提供访问器,创建一个,使用它,然后发送补丁。