Les déclarations if / else devraient-elles être organisées en fonction de la rareté des cas ou de la difficulté de les traiter?

18

Dans un code que j'écris en ce moment, j'ai quelque chose comme ceci:

if (uncommon_condition) {
    do_something_simple();
} else {
    do();
    something();
    long();
    and();
    complicated();
}

Une partie de moi pense que "c'est bien la façon dont c'est écrit. Les cas simples devraient aller en premier et les cas plus compliqués devraient aller ensuite." Mais une autre partie dit: "Non! Le elsecode devrait aller sous le if, parce qu'il ifest pour traiter des cas inhabituels et elsepour tous les autres cas." Qu'est-ce qui est correct ou préférable?

EMBLÈME
la source
4
Commandez par simplicité / compréhensibilité des conditions! Le reste peut être pris en charge par les optimiseurs, les prédicteurs de branche et le refactoring.
Marjan Venema du
C'est pourquoi nous sommes payés beaucoup d'argent: pour prendre ces décisions difficiles.

Réponses:

24

Ordre par leur probabilité d'être exécuté. La ou les conditions les plus courantes, les plus probables, etc. doivent apparaître en premier.

La "difficulté de les traiter" devrait être traitée par la structure du code, l'abstraction, etc. dans l'exemple, le bloc else pourrait être refactorisé en appel de méthode unique. Vous voulez que vos ifclauses soient au même niveau abstrait.

if ( ! LotteryWinner ) {
    GoToWorkMonday();
} else {
    PlanYearLongVacation();
}
radarbob
la source
6
Pour la performance, je pourrais être d' accord. Mais là encore, la plupart des optimiseurs et des prédicteurs de branche sont parfaitement capables de s'en occuper. Pour plus de lisibilité, je pourrais être d' accord si le cas le plus probable a beaucoup plus de lignes que le cas le moins probable. Mais pour moi, cela indiquerait plus tôt la nécessité d'extraire une méthode que d'utiliser a not. Personnellement, je me concentrerais sur l'évitement des notconditions. Il a été prouvé qu'ils induisent plus de charge cognitive à comprendre que les conditions "positives" et sont préjudiciables à la lisibilité / compréhensibilité du code. J'ai tendance à les utiliser uniquement dans les déclarations de garde.
Marjan Venema
2
@MarjanVenema, je peux voir votre point sur "ne pas" ing. Mais le double négatif est le vrai "pas" WTF. L'autre jour, j'ai rencontré cela dans notre code doesNotAllowxxFiles = false. Assez mauvais mais faites çaif(! doesNotAllowxxFiles)
radarbob
Oui, doubles négatifs, négatifs combinés avec et et / ou ou (sic!) Et négatifs combinés avec une méthode / var avec Pas dans le nom, donnez à mon cerveau une touche à chaque fois :-)
Marjan Venema
si vous avez du mal à comprendre ce qui se passe, je pense qu'il est souvent utile de faire des choses comme: simpleBool = (! (complexBool || randomfFlag)) &&! randomFlag
TruthOf42
2
Je serais d'accord avec vous, sauf pour l'existence de clauses de garde (qui ont toujours la condition exceptionnelle dans la partie ALORS de la déclaration IF, pas la condition commune).
Robert Harvey
5

Essayez d'améliorer la lisibilité. Une façon consiste à placer le bloc de code plus long dans la partie else.

if (s == null)
     // short code
else 
     // long 
     // code
     // block

est plus lisible que

if (s != null)
    // long
    // code
    // block
else
    // short code
CWallach
la source
2
pourquoi est-il plus lisible? Je ne vois aucune différence entre les deux en termes de lisibilité
John Demetriou
2
@JohnDemetriou Le Else est plus visible si le Then est court. Les gens recherchent d'abord la structure, puis lui attribuent un sens. Le code sans Else est différent du code avec un, donc rendre plus visible Else est plus compréhensible. (Toutes choses étant égales par ailleurs, les mardis quand il ne pleut pas, etc.)
4

Pas de règle fixe en tant que telle j'ai entendu parler de l'usage mais je suis comme ça

if(usual)
{
(more often)
}
else (unusual)
{
(rarely occurring)
}

Mais si les deux ont la même fonction avec des propriétés différentes, il vaut mieux opter d'abord pour inhabituel puis habituel afin de pouvoir enregistrer une instruction.


if(x == 0)  // 1
  {x = 1;}  // 2
else
  {x = 2;}  // 3

Pour le code d'assemblage ci-dessus, le code ressemblera à ceci:

1. 000d 837DFC00        cmpl    $0, -4(%ebp)
   0011 7509            jne .L2

2. 0013 C745FC01        movl    $1, -4(%ebp)
   001a EB07            jmp .L3

    .L2:
3.001c C745FC02         movl    $2, -4(%ebp)

        .L3:

Si la condition à l'intérieur de if est vraie, le débit est 1-> 2 (4 intructions)
SI la condition à l'intérieur de if est fausse, alors le flux est 1-> 3 (3 intructions)

Il est donc préférable de mettre des événements inhabituels ou rarement survenant dans une partie et un état normal ailleurs afin que nous puissions enregistrer une instruction à chaque fois ;-)

Santosh Mudhol
la source
2

J'ai trouvé que le modèle opposé exact conduit à un code plus facile à lire et réduit ou élimine les instructions if imbriquées. J'appelle cela un modèle de «gantelet». (Dans le récit, un gant serait une série de défis qui doivent être relevés avec succès avant que la tâche finale ne soit terminée.) En traitant d'abord vos cas marginaux , vous permettez au corps principal de votre code d'être propre et concis:

if(gauntlet_1){ handle the first gauntlet condition }; 
if(gauntlet_2){ handle the second gauntlet condition };
...
// All preconditions (gauntlets) have been successfully handled

// Perform your main task here
Byron Jones
la source
Ainsi, la partie «gérer le gant» devrait soit être un transfert de contrôle, comme une instruction throw ou return, soit corriger réellement le défaut. Certaines personnes désapprouvent une série d'instructions if ... return, mais je ne pense pas et cela rend en fait le code plus facile à lire, comme vous l'avez dit.
1
Si la condition de gant est quelque chose qui empêcherait la fonction de réussir, elle renvoie immédiatement une erreur. Si la condition de gant peut être gérée, je le fais avant d'entrer le corps principal de code chaque fois que possible. J'essaie principalement d'éviter les instructions IF imbriquées, qui d'après mon expérience sont l'une des principales causes d'erreurs de codage obscures et difficiles à déboguer.
Byron Jones
0

Pour moi, il s'agit plus des conditions que de la complexité du code qu'elles exécutent. Vous devez ordonner les conditions afin de piéger les conditions inhabituelles en premier, puis les plus courantes après. De plus, si le code else est vraiment long et compliqué, je ferais probablement un sub pour cela, pour garder la partie conditionnelle évidente pour le lecteur.

Steve Thomas
la source
-1

Je n'ai pas de règle fixe, mais en général, je suis la suivante - tout d'abord, réfléchissez à l'endroit où il y a un modèle de conception manquant qui prendra cela en compte. Sinon, je l'écris pour que la condition dans le if soit la plus clairement comprise. Autrement dit, en évitant les doubles négatifs et similaires.

Don Branson
la source