2017-10-19 78 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