La citation suivante est extraite du livre Code Complete :
"Mettez le cas normal après le
if
plutôt que après leelse
"
Ce qui signifie que des exceptions / déviations par rapport au chemin standard doivent être mises en place else
.
Mais le programmeur pragmatique nous apprend à "planter tôt" (p. 120).
Quelle règle devrais-je suivre?
if
branches revient, utilisez-la d'abord. Et évitez leelse
reste du code, vous êtes déjà retourné si les conditions préalables ont échoué. Le code est plus facile à lire, moins d'indentation ...Réponses:
"Crash early" n'indique pas quelle ligne de code est textuelle avant. Il vous indique de détecter les erreurs lors de la première étape du traitement , de manière à ne pas prendre par inadvertance de décisions et de calculs basés sur un état déjà défaillant.
Dans une construction
if
/else
, seul l'un des blocs est exécuté. Par conséquent, on ne peut pas dire qu'aucun d'entre eux constitue une étape "antérieure" ou "ultérieure". Comment les commander est donc une question de lisibilité, et "échouer tôt" n'entre pas dans la décision.la source
if/else
constructions, cela n'a probablement pas d'importance. Mais ceux qui sont appelés en boucle ou avec plusieurs instructions dans chaque bloc pourraient s'exécuter plus rapidement avec la condition la plus courante.Si votre
else
instruction ne contient que du code d'échec, alors, très probablement, elle ne devrait pas être là.Au lieu de faire ceci:
fais ça
Vous ne voulez pas imbriquer profondément votre code simplement pour inclure la vérification des erreurs.
Et, comme tout le monde l’a déjà dit, les deux conseils ne sont pas contradictoires. L'une concerne l' ordre d'exécution , l'autre l'ordre de code .
la source
if
et un flux exceptionnel dans le bloc aprèselse
ne s'applique pas si vous n'en avez paselse
! Les instructions Guard telles que celle-ci constituent la forme privilégiée de traitement des conditions d'erreur dans la plupart des styles de codage.Vous devriez suivre les deux.
Le conseil "Crash early" / fail early signifie que vous devez tester vos entrées pour rechercher d'éventuelles erreurs le plus rapidement possible.
Par exemple, si votre méthode accepte une taille ou un nombre censé être positif (> 0), le conseil d'échec précoce signifie que vous testez cette condition dès le début de votre méthode, au lieu d'attendre que l'algorithme produise un non-sens. résultats.
Le conseil de mettre le cas normal en premier signifie que si vous testez une condition, le chemin le plus probable doit venir en premier. Cela contribue aux performances (car la prédiction de branche du processeur sera exacte plus souvent) et à la lisibilité, car vous n'avez pas à ignorer des blocs de code lorsque vous essayez de comprendre ce que la fonction fait dans les cas normaux.
Ce conseil ne s'applique pas vraiment lorsque vous testez une condition préalable et que vous effectuez une sauvegarde immédiate (à l'aide d'assertions ou de
if (!precondition) throw
constructions), car il n'y a pas de gestion d'erreur à ignorer lors de la lecture du code.la source
if(cond){/*more likely code*/}else{/*less likely code*/}
est plus rapide que laif(!cond){/*less likely code*/}else{/*more likely code*/}
prédiction de branche. Je penserais que la prédiction de branche n’est pas biaisée parif
l’else
énoncé ou l’ énoncé et tient uniquement compte de l’histoire. Donc, si celaelse
est plus susceptible de se produire, il devrait être en mesure de prédire cela tout aussi bien. Cette hypothèse est-elle fausse?Je pense que @JackAidley en a déjà dit l'essentiel , mais laissez-moi le formuler comme suit :
sans exceptions (par exemple C)
Dans le flux de code normal, vous avez:
Dans le cas «erreur sur tôt», votre code lit tout à coup:
Si vous voyez ce modèle - un
return
dans unelse
(ou mêmeif
bloc), retravailler immédiatement si le code en question ne pas avoir unelse
bloc:Dans le monde réel…
Cela évite les imbrications trop profondes et remplit le cas de «rupture précoce» (aide à garder l'esprit et le flux de code propres) et ne viole pas la «mise de la chose la plus probable dans la
if
pièce», car il n'y a tout simplement aucuneelse
partie .C
et nettoyageInspiré par une réponse à une question similaire (qui s’est mal compris), voici comment vous effectuez le nettoyage avec C. Vous pouvez utiliser un ou deux points de sortie, voici un pour deux points de sortie:
Vous pouvez les réduire en un point de sortie s'il y a moins de nettoyage à faire:
Cette utilisation de
goto
est parfaitement bien, si vous pouvez vous en occuper; Le conseil de ne pas utilisergoto
est destiné aux personnes qui ne peuvent pas encore décider par elles-mêmes si une utilisation est bonne, acceptable, mauvaise, code spaghetti ou autre chose.Exceptions
Ce qui précède parle de langues sans exceptions, ce que je préfère vraiment (je peux utiliser la gestion explicite des erreurs beaucoup mieux et avec beaucoup moins de surprise). Pour citer igli:
Mais voici une suggestion pour savoir comment le faire dans une langue avec des exceptions et quand vous voulez bien l'utiliser:
erreur de retour face aux exceptions
Vous pouvez remplacer la plupart des premiers temps
return
par une exception. Cependant , votre flux de programme normal , c’est-à-dire tout flux de code dans lequel le programme n’a pas rencontré, eh bien, une exception… une condition d’erreur ou une telle erreur ne doit pas déclencher d’exception.Cela signifie que…
… Ça va, mais…
… n'est pas. Fondamentalement, une exception n'est pas un élément de flux de contrôle . Cela rend également les opérations étranges («ces programmeurs Java ™ nous disent toujours que ces exceptions sont normales») et peuvent entraver le débogage (par exemple, demander à l'EDI d'interrompre toute exception). Les exceptions nécessitent souvent que l'environnement d'exécution décompresse la pile pour produire une trace, etc. Il existe probablement d'autres raisons.
Cela revient à: dans un langage prenant en charge les exceptions, utilisez ce qui correspond à la logique et au style existants et vous semble naturel. Si vous écrivez quelque chose à partir de zéro, faites-le d’accord tôt. Si vous écrivez une bibliothèque à partir de zéro, pensez à vos consommateurs. (N'utilisez jamais non plus
abort()
dans une bibliothèque…). Mais quoi que vous fassiez, en règle générale, aucune exception n'est levée si l'opération se poursuit (plus ou moins) normalement après.conseils généraux Exceptions
Essayez d’obtenir l’utilisation en premier lieu des exceptions approuvées par toute l’équipe de développement. Fondamentalement, planifiez-les. Ne les utilisez pas en abondance. Parfois, même en C ++, Java ™, Python, un retour d'erreur est préférable. Parfois ce n'est pas; utilisez-les avec pensée.
la source
goto fail;
identité cachée.À mon avis, la "condition de garde" est l’un des moyens les plus simples et les plus faciles de rendre le code lisible. Je déteste vraiment quand je vois
if
au début de la méthode et ne vois pas leelse
code car il est hors de l'écran. Je dois faire défiler juste pour voirthrow new Exception
.Placez les vérifications au début de sorte que la personne qui lit le code ne soit pas obligée de sauter partout dans la méthode pour le lire, mais au contraire de toujours le scanner de haut en bas.
la source
(La réponse de @mirabilos est excellente, mais voici comment je réfléchis à la question pour parvenir à la même conclusion :)
Je pense à moi-même (ou à quelqu'un d'autre) en train de lire le code de ma fonction plus tard. Lorsque je lis la première ligne, je ne peux faire aucune hypothèse à propos de mon entrée (sauf celles que je ne vérifierai pas de toute façon). Donc, ma pensée est "Ok, je sais que je vais faire des choses avec mes arguments. Mais d'abord, nettoyons-les", c'est-à-dire supprimons les chemins de contrôle dans lesquels ils ne me plaisent pas. "Mais en même temps , Je ne vois pas le cas normal comme quelque chose qui est conditionné; je tiens à souligner que cela est normal.
la source
Ce type de classement dépend de la criticité de la section de code en question et de l’existence éventuelle de valeurs par défaut.
En d'autres termes:
A. section critique et pas de valeurs par défaut => Fail Early
B. section non critique et valeurs par défaut => Utiliser les valeurs par défaut dans la partie else
C. entre cas => décider au cas par cas
la source