Dans le livre Javascript: The Good Parts de Douglas Crockford, voici tout ce que l'auteur a à dire sur la déclaration continue:
L'instruction
continue
saute en haut de la boucle. Je n'ai jamais vu un morceau de code qui n'a pas été amélioré en le refactorisant pour supprimer l'instructioncontinue
.
Cela m'embrouille vraiment. Je sais que Crockford a des opinions très avisées sur JavaScript, mais cela me semble tout à fait faux.
Tout d'abord, continue
fait plus que simplement sauter en haut d'une boucle. Par défaut, il progresse également vers l'itération suivante. La déclaration de Crockford n'est-elle donc pas simplement une fausse information?
Plus important encore, je ne comprends pas entièrement pourquoi continue
serait même considéré comme mauvais. Ce post fournit ce qui semble être l'hypothèse générale: Pourquoi continuer à l'intérieur d'une boucle est-il une mauvaise idée?
Bien que je comprenne comment continue
peut rendre le code difficile à lire dans certains cas, je pense qu'il est tout aussi probable qu'il puisse rendre le code plus lisible. Par exemple:
var someArray=['blah',5,'stuff',7];
for(var i=0;i<someArray.length;i++){
if(typeof someArray[i]==='number'){
for(var j=0;j<someArray[i];j++){
console.log(j);
}
}
}
Cela pourrait être refactorisé en:
var someArray=['blah',5,'stuff',7];
for(var i=0;i<someArray.length;i++){
if(typeof someArray[i]!=='number'){
continue;
}
for(var j=0;j<someArray[i];j++){
console.log(j);
}
}
continue
n'est pas particulièrement bénéfique dans cet exemple spécifique, mais il démontre le fait qu'il réduit la profondeur d'imbrication. Dans un code plus complexe, cela pourrait potentiellement augmenter la lisibilité.
Crockford ne fournit aucune explication quant à la raison pour laquelle continue
ne devrait pas être utilisé, donc y a-t-il une signification plus profonde derrière cette opinion qui me manque?
La déclaration est ridicule. continue
peut être utilisé abusivement, mais souvent aide lisibilité.
Utilisation typique:
for (somecondition)
{
if (!firsttest) continue;
some_provisional_work_that_is_almost_always_needed();
if (!further_tests()) continue;
do_expensive_operation();
}
Le but est d'éviter le code "lasagne", où vous avez des conditions profondément imbriquées.
Modifié pour ajouter:
Oui, c'est finalement subjectif. Voici ma métrique pour décider.
Modifié une dernière fois:
Cet exemple est bien sûr trop simple et vous pouvez toujours remplacer les conditions imbriquées par des appels de fonction. Mais vous devrez peut-être ensuite transmettre des données aux fonctions imbriquées par référence, ce qui peut créer des problèmes de refactorisation au moins aussi graves que ceux que vous essayez d'éviter.
Je suis personnellement de l'autre côté que la majorité ici. Le problème n'est généralement pas avec les modèles continue
affichés, mais avec ceux plus profondément imbriqués, où les chemins de code possibles peuvent devenir difficiles à voir.
Mais même votre exemple avec un continue
ne montre pas d'amélioration à mon avis qui est justifiable. D'après mon expérience, quelques instructions continue
sont un cauchemar pour refactoriser plus tard (même pour les langages statiques mieux adaptés pour une refactorisation automatisée comme Java, en particulier lorsque quelqu'un y met plus tard break
aussi).
J'ajouterais donc un commentaire à la citation que vous avez donnée:
Refactoring pour supprimer l'instruction
continue
augmente votre capacité de refactoriser.
Et les boucles intérieures sont vraiment bien candidates, par exemple fonction d'extraction . Un tel refactoring est effectué lorsque la boucle interne devient complexe, puis continue
peut la rendre douloureuse.
Ce sont mes opinions honnêtes après avoir travaillé professionnellement sur des projets JavaScript en équipe, il y a des règles dont Douglas Crockford parle montrent vraiment leurs mérites.
Douglas Crockford peut ressentir cela, car il ne croit pas à l'affectation dans un conditionnel. En fait, son programme JSlint ne vous permet même pas de le faire, même si Javascript le fait. Il n'écrirait jamais:
exemple 1
while (rec = getrec())
{
if (condition1(rec))
continue;
doSomething(rec);
}
mais je suppose qu'il écrirait quelque chose comme:
exemple 2
rec = getrec();
while (rec)
{
if (!condition(rec))
doSomething(rec);
rec = getrec();
}
Les deux fonctionnent, mais si vous mélangez accidentellement ces styles, vous obtenez une boucle infinie:
exemple
rec = getrec();
while (rec)
{
if (condition1(rec))
continue;
rec = getrec();
}
Cela pourrait expliquer pourquoi il n'aime pas continuer.
Continue est un outil extrêmement utile pour enregistrer les cycles de calcul dans les algorithmes. Bien sûr, il peut être mal utilisé, mais il en va de même pour tous les autres mots clés ou approches. Lors de la recherche de performances, il peut être utile d'adopter une approche inverse de la divergence de chemin avec une instruction conditionnelle. Une poursuite peut faciliter l'inverse en permettant de sauter des chemins moins efficaces lorsque cela est possible.
En fait, d'après toutes les analyses, il semble:
À la défense de Douglas Crokford, je pense que ses recommandations ont tendance à tendre vers programmation défensive , ce qui, en toute honnêteté, semble être une bonne approche pour `` protéger les idiots '' du code dans l'entreprise.
Personnellement, je n'ai jamais rien entendu de mal à propos de l'utilisation de la déclaration continue. Il est vrai que cela pourrait (la plupart du temps) être facilement évité, mais il n'y a aucune raison de pas l'utiliser. Je trouve que les boucles peuvent être beaucoup plus propres et plus lisibles avec des instructions continues en place.