9
votes

Conditions dans les boucles, meilleures pratiques?

dise que j'ai une boucle comme ceci: xxx

contre ... xxx

existe-t-il une raison d'utiliser un sur le autre? Ou est-ce juste une préférence personnelle?
La langue principale que je demande à cela est Java, mais je suppose que cela s'applique également à la plupart des autres.


4 commentaires

Assurez-vous que le compilateur optimisera les deux et ils auront la même performance.


Vous trouverez que les réponses varient considérablement pour un peu de code non trivial. Cela dépend vraiment de la quantité d'autre code dans la boucle et exactement ce qu'il fait.


Si la clause si est courte et que la clause sinon est plus longue, j'utiliserais le premier formulaire.


Tout cela concerne la lisibilité et ainsi la préférence personnelle et dépendra beaucoup sur le code réel que vous l'utilisez. Dans ce qui précède, je préférerais else {} mais cela ne sera pas toujours le cas. Cela dépend exactement de ce qui est dans la seconde moitié, combien de temps je veux modifier le code existant, etc. Ne prenez donc pas de conseils génériques, alors commencez à l'appliquer universellement, vous devez vous asseoir et penser Lire dans cette situation .


8 Réponses :


16
votes

Techniquement, non, mais je trouve le deuxième plus joli pour ce cas particulier.


0 commentaires

2
votes

Je préférerais certainement la deuxième syntaxe.

Essayez d'éviter de continuer les déclarations dans la mesure du possible. Il rend le chemin de code plus difficile à suivre et il est difficile de déboguer


0 commentaires

7
votes

Je préfère la deuxième construction ... xxx

permet de dire que vous avez eu beaucoup de code avant le Continuer . Il est immédiatement apparent juste en regardant xxx

le ce qu'il n'est pas exécuté inconditionnellement .


1 commentaires

+1: Dans une réponse qui a déjà été supprimée, un membre avec 40k + points de réputation a manqué la déclaration . Je pense que c'est un indicateur assez fort que même avec une déclaration relativement courte si / autre, les programmeurs expérimentés peuvent toujours le manquer. Le bloc d'entier rend cela beaucoup plus clair.



5
votes

Pour moi, cela dépend de la scission entre le puis code> et la taille relative code> sinon code> de la branche: si l'un est massivement plus grand que l'autre, et le plus petit représente Une situation logiquement exceptionnelle, je mets le plus court dans alors code> et ajoutez un continuer code>; Quand ils sont à peu près égaux, la taille et dans le flux logique, je les garde dans leur propre alors code> et ele code> branches.

for (String op : operators) {
    if (isAdditive(op)) {
        // Do something for additive ops
    } else {
        // Do something for non-additive ops
    }
}


4 commentaires

Si ce bloc passe et encore, il est temps de le refroidir dans une fonction distincte (ou plusieurs fonctions).


@Jameskanze pas nécessairement: s'il s'avère que le traitement est unique à ce bloc, utilise des locaux définis en dehors de pour , et n'a aucune chance de réutiliser, il n'ya pas de point dans la création d'une fonction de feuille avec un seul site d'invocation. Bien qu'il y ait un avantage supplémentaire de donner un nom agréable à ce bloc de code, des commentaires font un bon travail de manière à déplacer le code dans une fonction distincte.


En fin de compte, il est question de savoir si vous souhaitez que votre code soit lisible et maintenu. Bien qu'il y ait des exceptions, je refuserais généralement une fonction de plus d'environ 10 lignes, ou avec plus d'un ou à la plupart des niveaux de nidification.


@Jameskanze Bien que la lisibilité et la main-d'œuvre soient une chose subjective, une limite de dix lignes est trop stricte: j'ai régulièrement des méthodes de code avec des contrôles d'argumentation qui prennent bien plus de dix lignes. Pour moi, garder le code associé ensemble est une partie extrêmement importante de la maintenabilité. C'est pourquoi, en règle générale, j'essaie de rester à partir de fonctions non réutilisables avec un seul site d'invocation: ils brisent mon flux de lecture du code sans me donner l'avantage de la réutilisabilité.



1
votes

Dans ce cas particulier, je suis d'accord avec tout le monde que le second est préférable. Mais il y a des cas où j'irais pour le premier. Si dosomething () n'était vraiment qu'un appel, et i == somécontion est un cas de bord et dosomeotherstuff () était en réalité 20 lignes du code au lieu de celui-ci, alors je préférerais utiliser le continuer . Dans ce scénario, je l'ai lu comme "d'abord, prenons soin de ce cas d'un bord rapidement. D'accord, faisons maintenant les vrais trucs."

Bien sûr, on pourrait faire l'argument pour le si-ele en reformulant mon interprétation à "Si nous sommes dans le cas de bord, fais cela, sinon fait les vrais trucs". Mais cela signifie que toutes ces 20 lignes sont maintenant une nidification plus profondément, et c'est plus lisible pour prendre soin des cas de bord, puis concentrez-vous sur le chemin commun.


2 commentaires

Si Dosomeotherstuff () est de 20 lignes de code, il devrait être dans une fonction distincte.


@Jameskanze peut-être, peut-être pas. Si la boucle pour est la seule chose qui se passe dans la fonction, par exemple, il peut ne pas y avoir de raison d'avoir mycoscincifunction () {pour (...) {myactualfunction (); }} . Et peut-être que ces 20 lignes ne sont pas 20 déclarations, mais incluent beaucoup de "bruit vertical" (comme une méthode avec des arguments longistiques que vous avez séparés sur plusieurs lignes). Ou des commentaires. Point est, c'est un appel de jugement.



2
votes

Comme tout le monde dit, la deuxième forme est recommandée. De nombreuses normes de codage vous recommandent d'éviter les déclarations "Continuer" et "Casser", car cela ajoute de la complexité à votre code.

Juste pour vous donner une référence:

JSF ++ (règle 190) et MISRA C (règle 57) Dites:

La déclaration de poursuite ne doit pas être utilisée.

Ce sont des normes pour les applications critiques de sécurité, mais elles peuvent également être appliquées à d'autres applications.

MISA est payé, mais JSF ++ peut être téléchargé gratuitement ici:

http://www.jsf.mil/downloads/documents/jsf_av_c ++ _ coding_standards_rev_c.doc

C'est pour C ++, mais de nombreuses règles peuvent être appliquées à d'autres langues. Cela vaut la lecture!


5 commentaires

Ne pas utiliser Continuer entraînera inévitablement un blague de code inutile, car vous êtes obligé de mettre en œuvre manuellement la logique (probablement via des variables booléennes).


@ EDA-QAMORT-ORA-Y Vous devez lire la norme pour que vous puissiez l'utiliser. Au début, il fait la différence entre l'utilisation des mots "volonté", "doit" et "doit". Les règles «doit» sont des recommandations que vous devriez utiliser lorsque cela est possible. Mais à moins que vous ne travaillez avec de vieux codes, vous ne pourrez rarement pas éviter de «continuer».


@ EDA-QAMORT-ORA-Y à près de 30 ans d'expérience, je n'ai jamais vu un tel cas. Sauf lorsque la fonction était trop compliquée pour commencer par - dans ce cas, la solution consiste à le refroidir en fonctions plus petites, à ne pas ajouter à la complexité d'une fonction déjà complexe.


@Renan: Les règles "doivent effectivement" sont totalement obligatoires selon JSF. Citer: "Les règles sont des exigences obligatoires. Ils doivent être suivis et nécessitent une vérification (automatique ou manuelle)." L'écart par rapport à la règle de la volonté ou une règle doit être approuvé à la fois le responsable du produit et et le responsable de l'ingénierie. Pour les règles, la violation doit être documentée dans le même dossier, aucun déviation autorisé.


@Jameskanze, l'expérience peut varier, mais j'ai travaillé sur beaucoup de code où supprimer le continuer rendrait le code moins clair. Je n'aime vraiment pas les boucles où tout le corps est une déclaration de si.



0
votes

Je pense vraiment qu'il existe une raison pertinente de préférer le premier sur la seconde, , bien que dans la plupart des cas, la seconde est définitivement plus lisible forte>.

dire par exemple, vous avez beaucoup, et je veux dire beaucoup strong> de conditions dans votre boucle, où en ayant beaucoup de si code> affecte réellement la lisibilité par l'indentation: P>

for ( int i = 0 ; i < n ; i++ )
{
   if ( !obj[i] )
   {
       continue;
   }
   doSomething();
   if ( !someOtherCondition() 
   {
       continue;
   }
   //...........  
}


0 commentaires

0
votes

Je pense que cela dépend davantage de ce que vous faites.

C'est un exemple simple, mais en règle générale s'il y a une condition que je "extraire" d'une autre logique de boucle, je vais le sortir comme rapidement aussi possible avec une poursuite plutôt que d'ajouter à la complexité de l'avenir si des déclarations (votre premier exemple s'il s'agit d'une condition pouvant être extraite de simplifier la logique future), par exemple: xxx > Maintenant, il est clair que l'extraction de la première condition dans xxx

pourrait sauvegarder une certaine confusion car cette boucle est améliorée. J'utilise beaucoup cette tactique pour tester les paramètres de la méthode et renvoyer tôt ou jetant une exception.

aussi (c'est totalement un côté, ne faisant pas partie de la réponse du tout!), Je dirais que si Vous avez déjà vu une condition équilibrée «vraiment» que vous pourriez donner une idée sérieuse à votre design OO. Si vous étiez que des dossions et une autre confondes étaient similaires, elles devraient probablement être des implémentations différentes d'une méthode définie dans une classe de base ou une interface, conduisant à ce code: xxx


0 commentaires