4

在我的 Perl 脚本中,我的子例程被调用了数百次,并带有许多不同的参数集,因为发送的唯一值是与默认值不同的值。(不用说,排列组合的数量非常大)为了使其更健壮,我想对参数进行一些检查。这是我的子程序的缩小版本(实际版本有几十个参数非常具体,有时名称很长):

# Obtain any parameters that differ from the defaults and send for processing
sub importantSub
{
   my %params = 
   (
      commandType       => 5,
      commandId         => 38,
      channel1Enable    => 0,
      channel2Enable    => 0,
      channel3Enable    => 0,
      channel4Enable    => 0,
      channel5Enable    => 0,
      channel6Enable    => 0,
      channel7Enable    => 0,
      channel8Enable    => 0,
      channel9Enable    => 0,
      channel10Enable   => 0,
      # This goes on for a VERY long time
      @_
   );

    # Make sure we have exactly as many keys as we expect - verify that
    # no additional parameters were added (Real version has 92)
   if( keys(%params) !=  92 ) 
   {
      croak("Unexpected parameter in hash!");
   }

   return &$privateProcessingFunction('Data Path Configuration', \%params);
}

如您所见,我目前正在检查值的数量是否相同,就好像某些东西是以“chan1Enable”而不是“channel1Enable”的形式发送的,它会丢弃该数字。

但是由于多个其他工程师编写的多个其他脚本对子例程的调用如此之多,我想找到一种方法来查找 WHICH 值不正确(例如,不要只说有一个意外的参数,而是说“chan1Enable”无效)。此外,如果多个值不正确,我想列出所有值。

最有效的方法是什么?

(我询问效率,因为该函数目前以 400 多种不同的方式被调用,并且随着应用程序的扩展可能会继续增长。)

4

2 回答 2

4

有两种错误:提供无法识别的参数,或未能提供可识别的参数。当您编辑参数列表并确保在整个应用程序中一致地使用新参数时,您将不得不担心第二个问题。

最好和最简单的解决方案是使用另一个哈希。

my @params = qw(commandType commandId channel1Enabled ...);
my %copy = %params;
my @validation_errors = ();

# are all the required parameters present?
foreach my $param (@params) {
    if (not exists $copy{$param}) {
        push @validation_errors, "Required param '$param' is missing.";
    }
    delete $copy{$param};
}

# since we have  delete'd  all the recognized parameters,
# anything left is unrecognized
foreach my $param (keys %copy) {
    push @validation_errors, "Unrecognized param '$param' = '$copy{$param}' in input.";
}

if (@validation_errors) {
    die "errors in input:\n", join("\n", @validation_errors);
}
于 2013-07-31T14:49:42.510 回答
2

我建议使用正式工具来帮助验证您传入的参数。Params::Validate是经过验证的,而Type::Params是最近对问题空间的看法,允许您使用相同的约束集与 Moo 或 Moose 一起使用。

这是 Params::Validate 为您提供的无法识别参数的诊断类型:

use Params::Validate ':all';

sub foo {
    my %p = validate(@_, {
        first_required => 1,
        second_required => 1,
        first_optional => 0.
    });
}

foo( boom => 'zoom' );

结果是:

The following parameter was passed in the call to main::foo but was not listed in the validation options: boom
 at /tmp/t.pl line 7
        main::foo('boom', 'zoom') called at /tmp/t.pl line 14
于 2013-07-31T15:08:04.683 回答