C'est une chose que je fais beaucoup ces derniers temps.
Exemple:
setCircle(circle, i, { current }) {
if (i == current) {
circle.src = 'images/25CE.svg'
circle.alt = 'Now picking'
} else if (i < current) {
circle.src = 'images/25C9.svg'
circle.alt = 'Pick failed'
} else if (i > current) {
circle.src = 'images/25CB.svg'
circle.alt = 'Pick chance'
}
}
Souvent, l'échelle if / else est beaucoup plus compliquée que cela ...
Voir la clause finale? C'est redondant. L'échelle est censée finalement capturer toutes les conditions possibles. Ainsi, il pourrait être réécrit comme ça:
setCircle(circle, i, { current }) {
if (i == current) {
circle.src = 'images/25CE.svg'
circle.alt = 'Now picking'
} else if (i < current) {
circle.src = 'images/25C9.svg'
circle.alt = 'Pick failed'
} else {
circle.src = 'images/25CB.svg'
circle.alt = 'Pick chance'
}
}
C'est ainsi que j'écrivais du code, mais je n'aime pas ce style. Ma plainte est que la condition dans laquelle la dernière partie du code sera exécutée n'est pas évidente d'après le code. J'ai donc commencé à écrire explicitement cette condition pour la rendre plus évidente.
Toutefois:
- L'écriture explicite de la condition exhaustive finale est ma propre idée, et j'ai de mauvaises expériences avec mes propres idées - généralement les gens me crient à quel point ce que je fais est horrible - et (parfois beaucoup) plus tard, je découvre que c'était effectivement le cas sous-optimal;
- Une indication pourquoi cela peut être une mauvaise idée: non applicable à Javascript, mais dans d'autres langues, les compilateurs ont tendance à émettre des avertissements ou même des erreurs lorsque le contrôle atteint la fin de la fonction. Faire allusion à quelque chose comme ça pourrait ne pas être trop populaire ou je me trompe.
- Les plaintes du compilateur m'ont parfois fait écrire la condition finale dans un commentaire, mais je suppose que cela est horrible car les commentaires, contrairement au code, n'ont aucun effet sur la sémantique réelle du programme:
} else { // i > current
circle.src = 'images/25CB.svg'
circle.alt = 'Pick chance'
}
Suis-je en train de manquer quelque chose? Ou est-ce OK de faire ce que j'ai décrit ou est-ce une mauvaise idée?
Réponses:
Les deux approches sont valides. Mais regardons de plus près les avantages et les inconvénients.
Pour une
if
chaîne avec des conditions triviales comme ici, cela n'a pas vraiment d'importance:else
, il est évident pour le lecteur de savoir dans quelle condition le reste est déclenché;else if
, il est aussi évident pour le lecteur qu'aucun supplémentelse
n'est nécessaire puisque vous avez tout couvert.Cependant, il existe de nombreuses
if
chaînes qui reposent sur des conditions plus complexes, combinant des états de plusieurs variables, peut-être avec une expression logique complexe. Dans ce cas, c'est moins évident. Et voici la conséquence de chaque style:else
: vous êtes sûr que l'une des branches est prise. S'il vous arrive d'oublier un cas, il passera par cette dernière branche, donc pendant le débogage, si la dernière branche a été choisie et que vous vous attendiez à autre chose, vous comprendrez rapidement.else if
: vous devez dériver la condition redondante à coder, ce qui crée une source d'erreur potentielle avec le risque de ne pas couvrir tous les cas. De plus, si vous avez manqué un cas, rien ne sera exécuté et il pourrait être plus difficile de découvrir que quelque chose manquait (par exemple, si certaines variables que vous vous attendiez à définir conservent des valeurs des itérations précédentes).La dernière condition redondante est donc une source de risque. C'est pourquoi je préfère proposer d'aller en finale
else
.Edit: codage haute fiabilité
Si vous développez avec une grande fiabilité en tête, vous pourriez être intéressé par une autre variante: compléter votre finale explicite redondante
else if
par une finaleelse
afin de détecter toute situation inattendue.Il s'agit d'un codage défensif. Il est recommandé par certaines spécifications de sécurité telles que SEI CERT ou MISRA . Certains outils d'analyse statique implémentent même cela comme une règle systématiquement vérifiée (cela pourrait expliquer les avertissements de votre compilateur).
la source
assert
en finaleelse if
. Cependant, votre guide de style peut varier selon qu'il s'agit d'une bonne idée. (La condition d'unassert
ne devrait jamais être fausse, à moins que le programmeur ne se trompe. Donc, cela utilise au moins la fonctionnalité pour son usage prévu. Mais tellement de gens en abusent que beaucoup de magasins l'ont interdit.)Quelque chose qui manque jusqu'à présent dans les réponses est une question de savoir quel type d'échec est moins nocif.
Si votre logique est bonne, peu importe ce que vous faites, le cas important est ce qui se passe si vous avez un bug.
Vous omettez le conditionnel final: l'option finale s'exécute même si ce n'est pas la bonne chose à faire.
Vous ajoutez simplement le conditionnel final: il n'exécute aucune option, selon la situation, cela peut simplement signifier que quelque chose ne s'affiche pas (faible préjudice), ou cela peut signifier une exception de référence nulle à un moment ultérieur (ce qui pourrait être un débogage douleur.)
Vous ajoutez le conditionnel final et une exception: il lève.
Vous devez décider laquelle de ces options est la meilleure. Dans le code de développement, je considère cela comme une évidence - prenez le troisième cas. Cependant, je définirais probablement circle.src sur une image d'erreur et circle.alt sur un message d'erreur avant de lancer - au cas où quelqu'un déciderait de désactiver les assertions plus tard, cela échouerait sans danger.
Une autre chose à considérer - quelles sont vos options de récupération? Parfois, vous n'avez pas de chemin de récupération. Ce que je pense en est l'ultime exemple, c'est le premier lancement de la fusée Ariane V. Une erreur non capturée / 0 (en fait un débordement de division) a entraîné la destruction du booster. En réalité, le code qui s'est écrasé ne servait à rien à ce moment-là, il était devenu sans objet à l'instant où les boosters de ceinture s'allumaient. Une fois qu'ils ont allumé l'orbite ou le boom, vous faites de votre mieux, les erreurs ne peuvent pas être autorisées. (Si la fusée s'égare à cause de cela, le gars de la sécurité de la gamme tourne sa clé.)
la source
Ce que je recommande, c'est d'utiliser une
assert
déclaration dans votre autre final, dans l'un de ces deux styles:Ou une assertion de code mort:
L'outil de couverture de code peut souvent être configuré pour ignorer le code tel que «affirmer faux» du rapport de couverture.
En plaçant la condition dans une assertion, vous documentez efficacement la condition d'une branche explicitement, mais contrairement à un commentaire, la condition d'assertion peut en fait être vérifiée et échouera si vous gardez les assertions activées pendant le développement ou en production (je recommande généralement de garder les assertions activées en production s'ils n'affectent pas trop les performances).
la source
J'ai défini une macro «affirmée» qui évalue une condition, et dans une version de débogage tombe dans le débogueur.
Donc, si je suis sûr à 100% qu'une des trois conditions doit être vraie, j'écris
Cela montre assez clairement qu'une condition sera vraie et qu'aucune branche supplémentaire pour une assertion n'est nécessaire.
la source
Je recommande d' éviter complètement le reste . Permet
if
de déclarer ce que le bloc de code est censé gérer et de terminer le bloc en quittant la fonction.Il en résulte un code très clair:
La finale
if
est bien sûr redondante ... aujourd'hui. Cela peut devenir très important si / quand un futur développeur réorganise les blocs. Il est donc utile de le laisser là-dedans.la source