perl - 有没有系统的方法来检查 `strict refs` ?

标签 perl reference use-strict

过去几年,我们在遗留的 Perl 代码库中采用了 use strict。我的任务是将它添加到其余模块中,同时确保它不会破坏任何东西。

现在对于 use strict 'vars'use strict 'subs' 这很容易,因为这些是编译时错误,一个简单的 perl -c 捕获。但是是否有系统的方法来检查由 use strict 'refs' 触发的运行时错误?

当然,我可以通过在所有可能的情况下调用所有函数(即完全覆盖)来引发运行时错误,但这尤其麻烦。因为这段代码缺少单元测试。如果您有更好的主意,我将不胜感激。

最佳答案

因为 Perl 是无类型的(一个变量可能包含引用或非引用),这只能在运行时检查。考虑:

use strict;

# Usage: foo(HASHREF)
sub foo {
   print $_[0]{name}, "\n" if int(rand(2));
}

my $var = int(rand(2))
   ? { name => "Hello" }
   : "World";  # oopsie!

foo($var);

这将在大约 25% 的时间内失败。无类型语言的静态分析无法捕捉到那种东西——它只能被你的测试套件捕捉到,所以你的首要任务应该是改进它。

也就是说,有一些改进代码的方法可以帮助您解决问题。例如,如果我们对传入参数进行类型检查,我们可以证明 foo sub 本身是正确编写的:

sub foo {
   my $href = $_[0];
   ref($href) eq 'HASH' or die("Expected hashref!");
   print $href->{name}, "\n" if int(rand(2));
}

这将确保 foo 行为正确性的负担从 foo 推到了 foo 的调用者身上。在 foo 中,您现在有一小段代码,您可以在其中确定每个变量的数据类型。像这样逐步添加断言可以让您不断扩大“信任区域”。

请注意,上面的小变化意味着我们的代码现在将有 50% 的时间失败,而不是 25% 的时间。因为 foo 现在更加一致地失败,这将帮助我们捕获错误的真正源:

my $var = int(rand(2))
   ? { name => "Hello" }
   : "World";  # oopsie!

foo($var);

部分是因为我写的,部分是因为它是 damn fast ,我建议你看看Type::Params用于检查子参数。以下是如何使用它的示例:

use feature qw(state);
use Types::Standard qw( HashRef );
use Type::Params qw( compile );

sub foo {
   state $signature = compile( HashRef );
   my ($href) = $signature->(@_);
   print $href->{name}, "\n" if int(rand(2));
}

将其扩展到一个接受多个参数的子...

use feature qw(state);
use Types::Standard qw( -types );
use Type::Params qw( compile );

sub query_get_rows {
   state $signature = compile( InstanceOf['DBI::db'], Str, Optional[Int] );
   my ($dbh, $query, $limit) = $signature->(@_);

   # do stuff here
}

关于perl - 有没有系统的方法来检查 `strict refs` ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23126760/

相关文章:

perl - libapreq2 : libtool: link: CURRENT `' must be a nonnegative integer

perl - Perl 有类似 docopt 的模块吗?

perl - 如何通过上一个/下一个强制退出 perl 子例程/闭包以使程序自动失败?

javascript - getElementById 和简单地使用元素的 ID 作为变量有什么区别?

javascript - "use strict"导致未定义的错误

perl - 为什么不证明接受 -MCarp=verbose?

java - 修改传递给类的 Java 参数

scala - 前向引用扩展了值(value)形状的定义

javascript - 为什么 "use strict"仍然是字符串文字?

node.js - 启用“use-strict”但在 Node 中不起作用