2013-07-31 56 views
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」的形式發送,則會丟棄該數字。

但有這麼多的電話從多個其他工程師編寫的其他多個腳本中的子程序,我想找到一種方法來找到這個值是不正確的(例如,不要只是說有一個意外的參數,說「chan1Enable」無效)。此外,如果多個值不正確,我想列出所有這些值。

什麼是最有效的方法來做到這一點?

(我問效率,因爲該功能在超過400種不同的方式目前被稱爲,這將有可能繼續增長,因爲該應用程序擴展)

回答

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); 
} 
+0

我認爲複製的哈希值是一個好主意。我確定這是我的錯誤,但由於在子程序中設置了默認值,所以確實沒有「必需的參數」。如果需要其餘的默認值,通常只設置5-10個參數(這節省了大量空間和寫入)。然而,主要想法可以堅持:有一個「好」參數列表,並將其與發送的內容進行比較。謝謝! – MattDavBen

+1

您檢查「期望」參數列表(是比「必需」更好的單詞),因爲當您添加或重命名參數時,可能會忘記爲其設置默認值。 – mob

2

我建議使用正規的工具來幫助驗證您的參數,你帶過。Params::Validate是嘗試和真實,而Type::Params是最近的作爲在問題空間,讓您在使用相同的一組約束,你會也用於Moo或Moose。

這裏的一種診斷認爲PARAMS ::驗證會給你 無法識別的參數:

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 
+0

以前從未見過這個模塊!謝謝! – MattDavBen