2017-10-19 91 views
3

我有一个关于在具有多个输入的Matlab函数中进行输入验证的最佳实践的问题。这有点哲学。我在论坛中四处看了一下,我还没有看到这方面的全面讨论。我关心验证条件涉及两个或更多输入变量的情况。这是一个例子。在Matlab中验证两个相关输入的最佳实践

假设我用两个输入a和b编写函数。我知道输入必须满足条件

a > 0b > 0

如果我想验证这些投入,我通常会写这样的功能(只用于说明目的,函数功能并不重要):

% My function 
function [result] = myLogSum(a,b) 

% Create an input parser 
p = inputParser; 
% Add required inputs with validation 
isPositive = @(x) all(x>0); 
addRequired(p, 'a', isPositive); 
addRequired(p, 'b', isPositive); 
% Parse the inputs 
parse(p,a,b); 

% Calculate the log sum 
result = log(a) + log(b); 

end 

但现在假设A和B是阵列,并且我还需要检查它们是否具有相同的尺寸:

all(size(a) == size(b)) == true

有没有办法处理输入解析器的这种情况?如果不是,处理这个问题的最好方法是什么?

我可以想出四个解决方案,但我无法弄清楚哪一个最好。

1)我是否应该在表单{a,b}的单个输入单元格数组变量sumInput中填写a和b,然后为单元格数组写入自定义验证函数?这很好,但我不知道是否总是把输入结合在一起的好习惯。这里能够写myLogSum(a,b)而不是myLogSum(sumInput)似乎很自然。

2),或在这种情况下,我应该写在函数中输入验证的这一部分,即修改上面的代码是这样的:

% My function 
function [result] = myLogSum(a,b) 

% Create an input parser 
p = inputParser; 
% Add required inputs with validation 
isPositive = @(x) all(x>0); 
addRequired(p, 'a', isPositive); 
addRequired(p, 'b', isPositive); 
% Parse the inputs 
parse(p,a,b); 

% Check that the input arrays have the same size 
if ~all(size(a)==size(b)) 
    message = 'The arrays a and b must have the same size.'; 
    error(message); 
end 

% Calculate the log sum 
result = log(a) + log(b); 

end 

这是一件好事,但它使验证一个有点不均匀和不美观,因为现在我的输入A和b都以不同的方式和不同的原因验证两次。

3)我是不是应该放弃对输入解析器和只写我自己的验证功能,在这里建议:

Best practice when validating input in MATLAB

但是我很喜欢输入解析器,因为它是一种巧妙的方法管理选项。

4)我可以只让Matlab的自行处理错误在程序到达最后一行result = log(a) + log(b)和数组大小不匹配。但不知何故,我觉得像这样的要价,从长远来看麻烦。

如果你有在Matlab中的经验,只是让我知道你在想什么是最强大和最全面的验证策略,当两个输入相关。

+0

作为一个趣闻:我最终装箱我自己的“parse_input”功能为我的代码,这也给了默认值等。如果你做得不错(不像我这样做),你可以做一个相对普通的函数,但它的确是你最终修改了每个函数的代码块......这不是一个坏的选择,但是如果你这样做,为输入分析器编写单元测试! –

+1

@AnderBiguri这也是我所做的,但由于不同的原因,我根本不知道输入分析器。我能够在我的大项目中编写一个通用解析器作为一个类,它有更多的类,几乎所有的类都使用它。不难携带默认值并处理无序列表。 – Yvon

回答

3

有什么可调用parse一次,然后添加新的输入,并再次调用parse阻止你 - 此时,您可以使用您的验证功能之前解析值(S)。validateattributes函数在这里用于构建具有多个条件的验证函数。例如:

% My function 
function [result] = myLogSum(a,b) 

% Create an input parser 
p = inputParser; 
% Add required inputs with validation 
addRequired(p, 'a', @(x) validateattributes(x, {'numeric'}, {'>', 0})); 
% Check the first input was valid 
p.parse(a); 
addRequired(p, 'b', @(x) validateattributes(x, {'numeric'}, {'>', 0, 'size', size(a)})); 
% Parse the inputs 
p.parse(a,b); 

% Calculate the log sum 
result = log(a) + log(b); 

end 

validateattributes也产生合理的解释错误信息给你:

>> myLogSum(30, 40) 

ans = 

    7.0901 

>> myLogSum([30 20], 40) 
Error using myLogSum (line 12) 
The value of 'b' is invalid. Expected input to be of size 1x2 when it is 
actually size 1x1. 

>> myLogSum([30 20], [40 1]) 

ans = 

    7.0901 2.9957 

>> myLogSum([30 20], [40 -1]) 
Error using myLogSum (line 12) 
The value of 'b' is invalid. Expected input to be an array with all of the 
values > 0. 
+0

我没想到这是可能的。回顾展会很明显。 我认为这是我的首选解决方案。它是自洽的,相对优雅的,可以统一应用于所有功能。非常感谢。 – Ben

+0

在类似的说明中,是否可以在输入已经添加到解析器之后添加验证条件?一些验证条件可能取决于以前验证的成功。 – Ben