Je tombe parfois sur du code similaire à l'exemple suivant (ce que fait exactement cette fonction sort du cadre de cette question):
function doSomething(value) {
if (check1(value)) {
return -1;
}
else if (check2(value)) {
return value;
}
else {
return false;
}
}
Comme vous pouvez le voir, if
, else if
et les else
déclarations sont utilisées conjointement avec la return
déclaration. Cela semble assez intuitif à un observateur occasionnel, mais je pense qu'il serait plus élégant (du point de vue d'un développeur de logiciels) de supprimer le else
-s et de simplifier le code comme ceci:
function doSomething(value) {
if (check1(value)) {
return -1;
}
if (check2(value)) {
return value;
}
return false;
}
Cela a du sens, car tout ce qui suit une return
instruction (dans la même portée) ne sera jamais exécuté, ce qui rend le code ci-dessus sémantiquement égal au premier exemple.
Laquelle des réponses ci-dessus correspond le mieux aux bonnes pratiques de codage? Y a-t-il des inconvénients à l'une ou l'autre méthode en ce qui concerne la lisibilité du code?
Modifier: Une suggestion en double a été faite avec cette question fournie comme référence. Je crois que ma question touche à un sujet différent, car je ne demande pas à éviter les déclarations en double comme présenté dans l'autre question. Les deux questions visent à réduire les répétitions, quoique de manières légèrement différentes.
la source
else
un problème moindre, le plus gros problème est que vous renvoyez évidemment deux types de données à partir d'une seule fonction, ce qui rend l'imprévisibilité de l'API de la fonction.-1
est un nombre,false
est un booléen etvalue
n'est pas spécifié ici, il peut donc s'agir de n'importe quel type d'objet.value
c'est en fait un entier. Si cela peut être quelque chose, c'est encore pire.Réponses:
J'aime celui sans
else
et voici pourquoi:Parce que faire ça n'a rien cassé ce qu'il n'était pas censé faire.
Détestez l'interdépendance sous toutes ses formes (y compris en nommant une fonction
check2()
). Isolez tout ce qui peut être isolé. Parfois, vous en avez besoin,else
mais je ne vois pas cela ici.la source
if
bloc de} //else
pour indiquer clairement, lors de la lecture du code, que la seule exécution prévue après leif
bloc de code est si la condition dans l'if
instruction est fausse. Sans quelque chose comme ça, en particulier si le code dans leif
bloc devient plus complexe, il peut ne pas être clair pour quiconque gère le code que l'intention était de ne jamais s'exécuter après leif
bloc lorsque laif
condition est vraie.if
pour indiquer clairement que cette section de code est terminée et que la structure est terminée. Pour ce faire, je fais ce que je n'ai pas fait ici (parce que je ne voulais pas me distraire du point principal du PO en faisant d'autres changements). Je fais la chose la plus simple possible qui permet d'atteindre tout cela sans être distrayante. J'ajoute une ligne vierge.Je pense que cela dépend de la sémantique du code. Si vos trois cas dépendent les uns des autres, indiquez-le explicitement. Cela augmente la lisibilité du code et le rend plus facile à comprendre pour n'importe qui d'autre. Exemple:
Ici, vous dépendez clairement de la valeur de
x
dans les trois cas. Si vous omettiez le dernierelse
, ce serait moins clair.Si vos cas ne dépendent pas directement les uns des autres, omettez-les:
Il est difficile de montrer cela dans un exemple simple sans contexte, mais j'espère que vous comprendrez mon point.
la source
Je préfère la deuxième option (séparée
ifs
avec nonelse if
et précocereturn
) MAIS qui est aussi longue que les blocs de code sont courts .Si les blocs de code sont longs, il vaut mieux les utiliser
else if
, car sinon, vous n'auriez pas une compréhension claire des différents points de sortie du code.Par exemple:
Dans ce cas, il vaut mieux l'utiliser
else if
, stocker le code retour dans une variable et avoir une seule phrase retour à la fin.Mais comme il faut s'efforcer que les fonctions soient courtes, je dirais de rester court et de quitter tôt comme dans votre premier extrait de code.
la source
return
est dans les 3 lignes deif
donc ce n'est pas si différent queelse if
même après 200 lignes de code. Le style de retour unique que vous introduisez ici est une tradition de c et d'autres langages qui ne signalent pas les erreurs avec des exceptions. Le but était de créer un endroit unique pour nettoyer les ressources. Les langues d'exception utilisent unfinally
bloc pour cela. Je suppose que cela crée également un endroit pour mettre un point d'arrêt si votre débogueur ne vous laisse pas en mettre un sur les fonctions fermant l'accolade.retVal
. Si vous pouvez quitter une fonction en toute sécurité, faites-le immédiatement, sans affecter la valeur sûre à renvoyer à une variable d'une seule sortie de la fonction. Lorsque vous utilisez le point de retour unique dans une fonction très longue, je ne fais généralement pas confiance aux autres programmeurs et je finis par chercher dans le reste de la fonction d'autres modifications de la valeur de retour. Échouer rapidement et revenir tôt sont, entre autres, deux règles que je respecte.J'utilise les deux dans des circonstances différentes. Lors d'un contrôle de validation, j'omet le reste. Dans un flux de contrôle, j'utilise le reste.
contre
Le premier cas se lit plus comme si vous vérifiez d'abord toutes les conditions préalables, en les éliminant, puis en progressant vers le code que vous souhaitez exécuter. En tant que tel, le code juteux que vous voulez vraiment exécuter appartient directement à la portée de la fonction; c'est vraiment la fonction.
Le deuxième cas se lit plus comme si les deux chemins sont un code valide à exécuter qui est tout aussi pertinent pour la fonction que l'autre en fonction d'une condition. En tant que tels, ils appartiennent à des niveaux de portée similaires les uns aux autres.
la source
La seule situation que j'ai jamais vue vraiment importante est un code comme celui-ci:
Il y a clairement quelque chose qui cloche ici. Le problème est qu'il n'est pas clair s'il
return
faut l'ajouter ou leArrays.asList
supprimer. Vous ne pouvez pas résoudre ce problème sans une inspection plus approfondie des méthodes connexes. Vous pouvez éviter cette ambiguïté en utilisant toujours des blocs if-else exhaustifs. Cette:ne compilera pas (dans les langues vérifiées statiquement) sauf si vous ajoutez d'abord un retour explicite
if
.Certaines langues ne permettent même pas le premier style. J'essaie de ne l'utiliser que dans un contexte strictement impératif ou pour des conditions préalables dans les méthodes longues:
la source
Avoir trois sorties de la fonction comme celle-ci est vraiment déroutant si vous essayez de suivre le code et de mauvaises pratiques.
Si vous avez un seul point de sortie pour la fonction, les autres sont requis.
En fait, allons encore plus loin.
Assez juste, vous pourriez plaider pour un retour anticipé unique sur la validation des entrées. Évitez simplement d'envelopper la masse entière si votre logique dans un if.
la source
Je préfère omettre la déclaration else redondante. Chaque fois que je le vois (en révision ou refactorisation de code), je me demande si l'auteur a compris le flux de contrôle et qu'il pourrait y avoir un bug dans le code.
Si l'auteur pensait que la déclaration else était nécessaire et ne comprenait donc pas les implications du flux de contrôle de la déclaration de retour, un tel manque de compréhension est certainement une source majeure de bogues, dans cette fonction, et en général.
la source