检查错误哈希键输入的最佳方法

时间:2013-07-31 14:39:41

标签: perl perl-data-structures

在我的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种不同的方式调用,随着应用程序的扩展,这种方式可能会继续增长。)

2 个答案:

答案 0 :(得分: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);
}

答案 1 :(得分: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