直接获取尤其是设置 Perl 模块的全局变量是否正确?

发布于 2024-09-03 01:48:44 字数 251 浏览 6 评论 0原文

我想知道 Perl 中的最佳实践是什么,通过直接访问 $Module::varName 来获取(或者更重要的是,设置)某个模块的全局变量,以防模块不提供 getter /setter 方法。

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

I was wondering what the best practice in Perl is regarding getting - or, more importantly, setting - a global variable of some module by directly accessing $Module::varName in case the module didn't provide getter/setter method for it.

The reason it smells bad to me is the fact that it sort of circumvents encapsulation. Just because I can do it in Perl, I'm not entirely certain I should (assuming there actually is an alternative such as adding a getter/setter to the module).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

陌路终见情 2024-09-10 01:48:44

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

我认为直接访问更好,因为它允许您利用动态作用域:

local $Module::varName = 42;

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

It isn't violating encapsulation if the variable is part of the public API. (If it isn't that's another matter.)

I think direct access is preferable as it allows you to take advantage of dynamic scoping:

local $Module::varName = 42;

This makes conflicts with other code using Module less likely.

留蓝 2024-09-10 01:48:44

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

要了解包变量的最佳用途,您确实需要了解 local 的工作原理。查看 local 的 perldoc 帮助。 Local 允许您在包 My 中获取一个包变量,例如(作为示例)$My::Variable,并创建一个 动态范围 版本。通常,如果您就地更改 $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

实际上,它可以让您以安全的方式使用包变量。不幸的是,并不是每个人都了解局部变量,因此他们经常破坏全局变量。记录良好的使用(例如,本地)总是有帮助的。

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

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

    # Do code work

    $My::set_variable($current_variable);
}

对于 local,这将变为:(

{
    local $My::Variable = $new_value;

    # do code work
}

顺便说一句,我希望您也可以对词法变量执行此操作,出于同样的原因......但您不能。)因此,对于某些事情,包变量可以有意义。这取决于您想如何使用它。诸如

  • 调试变量
  • 之类的全局配置不会/不应该经常更改

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

  • 定期使用的变量(请参阅可怕的界面File::Find)
  • 临时配置
  • “对象”变量

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

Global module variables were in vogue in the past, but considered "bad form" as an interface in Modern Perl. It's important to recognize that Perl is 22-23 years old now, and styles and practices have changed. :) Do note though that there are times when it's still appropriate, because there's some very nice features that come along with package variables. It's as usual a matter of experience and practice to see what a good solution might be.

To understand the best use for package variables, you really need to understand how local works. Check out local's perldoc help. Local lets you take a package variable like (as an example) $My::Variable in the package My, and create a dynamically scoped version of it. Normally if you change $My::Variable in place, it will affect your entire program, and will persist. For small programs, that might not be a big deal. For large ones, this can have disastrous side effects. local lets you make a temporary change to that variable, that's limited to your current scope.

Here's how it works:

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

Effectively, it lets you use package variables in a safe way. Unfortunately, not everyone knows about local, so they often clobber the global variable. Documenting good use (eg, local) always helps.

A getter/setter with proper object encapsulation prevents a lot of this, but not always. To make it work the way a local variable does, you'd have to do a lot of extra work. The nicest thing about being able to localize a package variable is that you can do temporary changes very easily, say, for a debug variable. Normally, you have to do a pattern like:

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

    # Do code work

    $My::set_variable($current_variable);
}

With local, this becomes:

{
    local $My::Variable = $new_value;

    # do code work
}

(Incidentally, I wish you could do this to lexical variables too, for the same reason...but you can't.) So, for some things, package variables can make sense. It depends on how you want to use it. Things like

  • Debugging Variables
  • Global configuration that doesn't/shouldn't be changed often

However, if it's something that does need to be changed on a regular basis, like

  • Regularly used variables (see the horrible interface for File::Find)
  • Temporary configuration
  • "Object" variables

Basically, anything that needs to be modified more than once or in rare situations, or should otherwise be encapsulated into a generated object, then I'd avoid the package variable.

清醇 2024-09-10 01:48:44

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

If the module doesn't provide an accessor, create one, use it, and send in the patch.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文