2010-03-02 5 views
3

J'ai une méthode pour la validation qui a beaucoup d'instructions conditionnelles. Fondamentalement, cela vaMéthode de refactoring avec plusieurs instructions de retour conditionnelles

If Check1 = false 
    return false 
If Check2 = false 
    return false 
etc 

FxCop se plaint que la complexité cyclomatique est trop élevée. Je sais que ce n'est pas la meilleure pratique d'avoir des instructions de retour au milieu des fonctions, mais en même temps la seule alternative que je vois est une liste moche d'instructions If-else. Quelle est la meilleure façon d'aborder cela?

Merci d'avance.

Répondre

11

Je ne suis pas d'accord avec votre affirmation selon laquelle il n'est pas recommandé d'avoir des instructions de retour au milieu des méthodes. La longueur de certaines personnes pour avoir une seule déclaration de retour est fou - aller avec tout ce qui produit le code le plus lisible. Parfois, ce sera un seul point de retour, mais souvent je trouve qu'il y a un "early out" - et il vaut mieux avoir ce retour que d'introduire plus de nidification dans le code avec un if pour le chemin alternatif. J'aime les méthodes qui ne finissent pas en retrait trop loin, en règle générale :)

Après avoir dit cela, est-ce vraiment la méthode rien mais vérifie? Les contrôles sont-ils indépendants? Quelles variables ont-ils besoin? Pouvez-vous les regrouper en méthodes plus petites représentant les «zones» des contrôles que vous effectuez?

+0

Vous pouvez l'imaginer en validant la saisie de l'utilisateur dans de nombreux champs. Certaines vérifications sont indépendantes, d'autres non.Vous avez raison de dire qu'il peut introduire de nombreuses instructions if imbriquées et du code en retrait si vous utilisez une seule instruction return. –

+1

Je pense que la meilleure pratique pour avoir seulement une déclaration de retour vient du code C simple, où les ressources sont libérées manuellement. Dans ce cas, un seul point de retour simplifie le traitement des ressources. Dans les langues modernes avec la collecte des ordures, ce n'est plus pertinent, donc je suis totalement d'accord avec ce qui précède. –

+0

@Anders: Garbage Collection et essayer/enfin ou en utilisant des déclarations permettent certainement un nettoyage plus élégant - Je pense que vous avez raison sur la source du mantra. Juste un autre cas de savoir * pourquoi * certaines choses sont considérées comme bonnes, et de les réévaluer par rapport à d'autres situations. Tellement important. –

1

En utilisant votre exemple:

return (Check1 == false) || (Check2 == false) [ || etc ] 
1

Pour votre cas particulier, il semble que vous pourriez probablement utiliser une boucle ... en supposant que cela est sorti d'un gestionnaire d'événements dans un formulaire ou quelque chose:

For Each ctrl As Control In Me.Controls 

    Dim check As CheckBox = TryCast(ctrl, CheckBox) 

    If check IsNot Nothing AndAlso check.Checked = False Then 
     Return False 
    End If 

Next 

Return True 

Edit: Après un examen plus approfondi, je me rends compte que cela était basé sur psuedocode et que vous n'utilisiez pas de cases à cocher. Cependant, je pense que la même méthodologie s'applique. Vous pouvez très facilement refactoriser vos règles dans une classe séparée qui implémente une interface personnalisée (IRule ou similaire), ou avoir une liste de délégués qui renvoient true/false que vous parcourez dans le cadre de votre modèle de vérification.

+0

C'est la bonne façon d'y aller une fois que vos conditions deviennent de plus en plus complexes. L'exemple de case à cocher présenté dans cette réponse est très intelligent - pourquoi ne devriez-vous pas avoir le contrôle à l'exécution sur quel ensemble de validateurs votre code traverse. Un autre cas courant est lorsque vous voulez retourner une raison pour laquelle la validation a échoué, beaucoup mieux de cacher ce genre de chose de la logique conditionnelle réelle. – CurtainDog

0

Si vous avez plusieurs contrôles de suite et ne pas besoin de conserver un court-circuit, vous pouvez essayer quelque chose comme ceci:

 bool isValid = true; 
     isValid &= Condition1; 
     isValid &= Condition2; 
     isValid &= Condition3; 
     if (!isValid) 
      return false; 

Si vous avez besoin de conserver un court-circuit, vous pouvez consolider les conditions dans une grande déclaration if. S'il y a beaucoup de conditions, cependant, je préférerais le code original, avec des retours multiples, comme un grand 'si' pourrait devenir un peu moche. Notez que, dans ce dernier cas, vous ne faites que contourner la métrique, car la branche logique est en fait la même. Si les vérifications de condition n'ont pas d'effets secondaires (et j'espère vraiment qu'elles ne le sont pas), je pense que la complexité cyclomatique élevée est une fausse alarme, car les retours multiples sont vraiment une manière plus lisible d'exprimer une logique de validation booléenne complexe.

Ceci n'est vrai que si les conditions sont toutes en série. Si elles sont réparties dans le code, avec un traitement significatif entre les vérifications, alors la métrique indique une réelle complexité (plus de branches qui doivent être testées). Dans ce cas, vous pouvez déterminer si la méthode peut être divisée logiquement en éléments plus petits et individuellement testables.

Questions connexes