2017-10-19 21 views
3

J'ai une question sur les meilleures pratiques pour la validation des entrées dans les fonctions Matlab à entrées multiples. C'est un peu philosophique. J'ai regardé autour dans le forum et je n'ai pas vu une discussion complète de ceci. Je me soucie du cas où les conditions de validation impliquent deux ou plusieurs des variables d'entrée. Voici un exemple. Supposons que j'écris une fonction avec deux entrées, a et b. Je sais que les entrées doivent satisfaire aux conditionsMeilleure pratique pour la validation de deux entrées connexes dans Matlab

a > 0 et b > 0.

Si je veux valider ces entrées, je normalement écrire une fonction comme celui-ci (juste à titre d'exemple, ce que la fonction n'est pas important):

% 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 

Mais supposons maintenant que a et b sont tableaux, et que j'ai également besoin de vérifier si elles sont de la même taille:

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

Existe-t-il un moyen de gérer une telle situation avec l'analyseur d'entrée? Si non, quelle est la meilleure façon de faire face à cela?

Je peux penser à quatre solutions, mais je ne peux pas déterminer laquelle est la meilleure.

1) Dois-je regrouper a et b dans une variable de tableau de cellules d'entrée unique sumInput de la forme {a,b} et écrire une fonction de validation personnalisée pour le tableau de cellules? C'est bien, mais je ne sais pas si c'est toujours une bonne pratique de regrouper des intrants comme ça. Ici, il semble très naturel d'être en mesure d'écrire myLogSum(a,b) au lieu de myLogSum(sumInput).

2) Ou dans ce cas, dois-je écrire cette partie de la validation d'entrée dans la fonction, par exemple, modifier le code ci-dessus comme ceci:

% 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 

C'est bien aussi, mais il fait la validation: Peu inhomogène et inesthétique car maintenant les entrées a et b sont validées deux fois de manière différente et pour des raisons différentes.

3) Dois-je donner juste sur l'analyseur d'entrée et il suffit d'écrire mes propres fonctions de validation, comme le suggère ici:

Best practice when validating input in MATLAB

Mais je tout à fait comme l'analyseur d'entrée car il est une belle façon gérer les options.

4) Je pourrais juste laisser Matlab gérer l'erreur par lui-même quand le programme atteint la dernière ligne result = log(a) + log(b) et les tailles de tableau ne correspondent pas. Mais d'une manière ou d'une autre, j'ai l'impression que cela demande des problèmes à long terme.

Si vous avez de l'expérience avec Matlab, faites-moi savoir ce que vous pensez être la stratégie de validation la plus robuste et complète lorsque les deux entrées sont liées.

Ben

+0

l'anecdote: j'ai fini par la mise en caisse ma propre fonction « parse_input » pour mon code, qui donne également des valeurs par défaut, etc. Si vous le faites correctement (pas comme je l'ai fait), vous pouvez faire une bonne fonction relativement générale, mais c'est vrai que vous avez modifié en fin de compte les parties du code pour chaque fonction ... Ce n'est pas une mauvaise option, mais si vous le faites, écrivez des tests unitaires pour l'analyseur d'entrée! –

+1

@AnderBiguri C'est aussi ce que je fais, mais pour une raison différente que je ne connaissais pas l'analyseur d'entrée du tout. J'ai pu écrire un parser universel en tant que classe dans mon grand projet, qui a plus de cours et presque tous l'utilisent. Pas difficile à transporter des valeurs par défaut et gérer la liste désordonnée. – Yvon

Répondre

3

Il n'y a rien pour vous empêcher d'appeler parse une fois, puis de nouvelles entrées et l'ajout d'appeler parse à nouveau - à quel point vous pouvez utiliser la valeur analysée précédemment (s) dans votre fonction de validation.La fonction validateattributes est utile ici pour créer des fonctions de validation avec plusieurs conditions. Par exemple:

% 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 génère également des messages d'erreur raisonnablement explicatifs pour vous:

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

Je n'avais pas compris que c'était possible. C'est évident en rétrospective. Je pense que c'est ma solution préférée. C'est auto-cohérent, relativement élégant, et peut être appliqué uniformément à toutes les fonctions. Merci beaucoup. – Ben

+0

Sur une note similaire, est-il possible d'ajouter une condition de validation après que l'entrée a déjà été ajoutée à l'analyseur? Certaines conditions de validation peuvent dépendre du succès de la validation précédente. – Ben