The best way to check for invalid hash key entry

In my Perl script, I have a routine that is called hundreds of times with many different sets of parameters, since the only values โ€‹โ€‹that are sent are those that are different from the defaults. (It goes without saying that the number of permutations and combinations is very large). To make it more reliable, I would like to do some parameter checking. Here is an abridged version of my routine (the actual version has dozens of parameters with very specific, sometimes long names):

# 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); } 

As you can see, I am currently checking to see if the number of values โ€‹โ€‹matches, as if something was sent as "chan1Enable" instead of "channel1Enable", it will throw that number away.

But since there are so many subroutine calls from several other scripts written by several other engineers, I would like to find a way to find the WHICH value was incorrect (for example, not just saying that there was an unexpected parameter, say that "chan1Enable" is invalid). Also, if multiple values โ€‹โ€‹were incorrect, I would like to list them all.

What is the most efficient way to do this?

(I ask about efficiency, as the function is currently being called in more than 400 different ways and is likely to continue to grow as the application expands.)

+4
source share
2 answers

There are two types of errors: delivery of an unrecognized parameter or the inability to provide a recognized parameter. You will have to worry about the second problem when editing the parameter list and make sure that the new parameters are used consistently throughout the application.

The best and easiest solution is to use a different hash.

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

I recommend using a formal tool that will help check your options. Params :: Validate is checked and executed, and Type :: Params is a recent approach to problem space, allowing you to use the same set of restrictions as for Moo or Moose.

Here is the kind of diagnostics that Params :: Validate will give you an unrecognized parameter:

 use Params::Validate ':all'; sub foo { my %p = validate(@_, { first_required => 1, second_required => 1, first_optional => 0. }); } foo( boom => 'zoom' ); 

Results in:

 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 
+2
source

Source: https://habr.com/ru/post/1494524/


All Articles