web-dev-qa-db-fra.com

Meilleure façon de formater une déclaration avec plusieurs conditions

Si vous voulez que du code soit exécuté en fonction de deux conditions ou plus, quel est le meilleur moyen de formater cette instruction if?

premier exemple: -

if(ConditionOne && ConditionTwo && ConditionThree)
{
   Code to execute
}

Deuxième exemple: -

if(ConditionOne)
{
   if(ConditionTwo )
   {
     if(ConditionThree)
     {
       Code to execute
     }
   }
}

ce qui est plus facile à comprendre et à lire en gardant à l’esprit que chaque condition peut être un nom de fonction long ou quelque chose.

81
Matt690

Je préfère l'option A

bool a, b, c;

if( a && b && c )
{
   //This is neat & readable
}

Si vous avez des variables/conditions de méthode particulièrement longues, vous pouvez simplement les séparer.

if( VeryLongConditionMethod(a) &&
    VeryLongConditionMethod(b) &&
    VeryLongConditionMethod(c))
{
   //This is still readable
}

Si elles sont encore plus compliquées, alors je considérerais de faire les méthodes de conditions séparément en dehors de l'instruction if

bool aa = FirstVeryLongConditionMethod(a) && SecondVeryLongConditionMethod(a);
bool bb = FirstVeryLongConditionMethod(b) && SecondVeryLongConditionMethod(b);
bool cc = FirstVeryLongConditionMethod(c) && SecondVeryLongConditionMethod(c);

if( aa && bb && cc)
{
   //This is again neat & readable
   //although you probably need to sanity check your method names ;)
}

IMHO La seule raison pour l'option 'B' serait si vous avez des fonctions distinctes else à exécuter pour chaque condition.

par exemple.

if( a )
{
    if( b )
    {
    }
    else
    {
        //Do Something Else B
    }
}
else
{
   //Do Something Else A
}
123
Eoin Campbell

D'autres réponses expliquent pourquoi la première option est normalement la meilleure. Toutefois, si vous avez plusieurs conditions, envisagez de créer une fonction (ou une propriété) distincte effectuant les vérifications de conditions dans l'option 1. Cela rend le code beaucoup plus facile à lire, du moins lorsque vous utilisez de bons noms de méthodes.

if(MyChecksAreOk()) { Code to execute }

...

private bool MyChecksAreOk()
{ 
    return ConditionOne && ConditionTwo && ConditionThree;
}

Si les conditions dépendent uniquement de variables de portée locales, vous pouvez rendre la nouvelle fonction statique et transmettre tout ce dont vous avez besoin. S'il y a un mélange, passez dans le local.

28
Torbjørn

Le premier exemple est plus "facile à lire".

En fait, à mon avis, vous ne devriez utiliser que le second à chaque fois que vous devez ajouter une "autre logique", mais pour un simple Conditionnel, utilisez le premier. Si vous êtes préoccupé par la longueur de la condition, vous pouvez toujours utiliser la syntaxe suivante:

if(ConditionOneThatIsTooLongAndProbablyWillUseAlmostOneLine
                 && ConditionTwoThatIsLongAsWell
                 && ConditionThreeThatAlsoIsLong) { 
     //Code to execute 
}

Bonne chance!

10
David Santamaria

La question a été posée et, jusqu'à présent, on y a répondu comme si la décision devait être prise uniquement pour des raisons "syntaxiques".

Je dirais que la bonne réponse de la façon dont vous posez un certain nombre de conditions dans un if, devrait dépend également de la "sémantique". Les conditions doivent donc être divisées et regroupées en fonction de ce qui va ensemble "de manière conceptuelle".

Si deux tests sont vraiment les deux faces d'une même pièce, par exemple. si (x> 0) && (x <= 100), placez-les ensemble sur la même ligne. Si une autre condition est conceptuellement beaucoup plus éloignée, par exemple. user.hasPermission (Admin ()) puis le mettre sur sa propre ligne

Par exemple.

if user.hasPermission(Admin()) {
   if (x >= 0) && (x < 100) {
      // do something
   }
}
9
interstar
    if (   ( single conditional expression A )
        && ( single conditional expression B )
        && ( single conditional expression C )
       )
    {
       opAllABC();
    }
    else
    {
       opNoneABC();
    }

Formatting a multiple conditional expressions in an if-else statement this way:
1) allows for enhanced readability:
    a) all binary logical operations {&&, ||} in the expression shown
       first
    b) both conditional operands of each binary operation are obvious
       because they align vertically
    c) nested logical expressions operations are made obvious using
       indentation, just like nesting statements inside clause
2) requires explicit parenthesis (not rely on operator precedence rules)
    a) this avoids a common static analysis errors
3) allows for easier debugging
    a) disable individual single conditional tests with just a //
    b) set a break point just before or after any individual test
    c) e.g. ...

    // disable any single conditional test with just a pre-pended '//'
    // set a break point before any individual test
    // syntax '(1 &&' and '(0 ||' usually never creates any real code
    if (   1
        && ( single conditional expression A )
        && ( single conditional expression B )
        && (   0
            || ( single conditional expression C )
            || ( single conditional expression D )
           )
       )
    {
       ... ;
    }

    else
    {
       ... ;
    }
7
Sean

Le second est un exemple classique du Arrow Anti-pattern Donc je l'éviterais ...

Si vos conditions sont trop longues, extrayez-les en méthodes/propriétés.

4
Omar Kooheji

La première est plus facile, car si vous la lisez de gauche à droite, vous obtenez: "Si quelque chose ET quelque chose d’autre ET quelque chose d’autre ALORS", ce qui est une phrase facile à comprendre. Le deuxième exemple se lit "Si quelque chose ALORS si quelque chose d'autre ALORS si quelque chose d'autre ALORS", ce qui est maladroit.

En outre, demandez-vous si vous souhaitez utiliser des RUP dans votre clause - comment le feriez-vous dans le second style?

3
RB.

Je crois switch...case est le meilleur moyen d’écrire du code ordonné dans ces circonstances, si le langage de programmation le prend en charge.

switch (//variable or Boolean) {
  case //Condition A:
  case //Condition B:
  case //Condition C:
    //Code to execute;
}
2
Kent

En Perl, vous pouvez faire ceci:

{
  ( VeryLongCondition_1 ) or last;
  ( VeryLongCondition_2 ) or last;
  ( VeryLongCondition_3 ) or last;
  ( VeryLongCondition_4 ) or last;
  ( VeryLongCondition_5 ) or last;
  ( VeryLongCondition_6 ) or last;

  # Guarded code goes here
}

Si l'une des conditions échoue, elle continuera simplement après le blocage. Si vous définissez des variables que vous souhaitez conserver après le bloc, vous devrez les définir avant le bloc.

0
Brad Gilbert