J'ai souvent écrit ce type de fonction dans les deux formats, et je me demandais si un format était préféré à un autre et pourquoi.
public void SomeFunction(bool someCondition)
{
if (someCondition)
{
// Do Something
}
}
ou
public void SomeFunction(bool someCondition)
{
if (!someCondition)
return;
// Do Something
}
Je code habituellement avec le premier puisque c'est ainsi que mon cerveau fonctionne lors du codage, même si je pense que je préfère le second, car il gère immédiatement toute erreur et me permet de lire plus facilement.
Réponses:
Je préfère le deuxième style. Commencez par supprimer les cas non valides, soit en supprimant les exceptions, soit en levant des exceptions, insérez une ligne vide, puis ajoutez le corps "réel" de la méthode. Je trouve cela plus facile à lire.
la source
Certainement le dernier. Le premier ne semble pas mauvais en ce moment, mais quand vous obtenez un code plus complexe, je ne peux pas imaginer que quiconque puisse penser ceci:
est plus lisible que
Je reconnais pleinement que je n’ai jamais compris l’avantage des points de sortie uniques.
la source
return value;
aide!?! Ensuite, il faut en chasser une demi-douzainevalue = ...
, avec le désavantage de ne jamais être sûr que la valeur ne sera pas modifiée entre cette cession et la déclaration finale. Au moins un retour immédiat est clair que rien ne changera plus le résultat.Cela dépend - En général, je ne vais pas faire tout ce qui est en mon pouvoir pour essayer de déplacer un tas de code afin de sortir de la fonction plus tôt que prévu - le compilateur s'en chargera généralement pour moi. Cela dit, s’il existe certains paramètres de base dont j’ai besoin et que je ne peux pas continuer sinon, j’interviendrai tôt. De même, si une condition génère un
if
bloc géant en fonction, je l'aurai aussi tôt.Cela dit, cependant, si une fonction nécessite des données lors de son appel, je vais généralement lancer une exception (voir exemple) au lieu de simplement y retourner.
la source
Je préfère le retour rapide.
Si vous avez un point d'entrée et un point de sortie, vous devez toujours suivre l'intégralité du code dans votre tête jusqu'au point de sortie (vous ne savez jamais si un autre morceau de code ci-dessous fait quelque chose d'autre, avoir à suivre jusqu’à exister). Vous ne le faites pas quelle branche détermine le résultat final. C'est difficile à suivre.
Avec une entrée et plusieurs existantes, vous revenez lorsque vous avez votre résultat et vous ne perdez pas la peine à la suivre pour vous assurer que personne ne fait rien d'autre (car il n'y aura rien d'autre depuis votre retour). C'est comme si le corps de la méthode était scindé en plusieurs étapes, chacune d'elles avec la possibilité de renvoyer le résultat ou de laisser la prochaine étape tenter sa chance.
la source
En programmation C, où vous devez nettoyer manuellement, il y a beaucoup à dire pour un retour en un point. Même s'il n'est pas nécessaire pour le moment de nettoyer quelque chose, quelqu'un peut éditer votre fonction, allouer quelque chose et avoir besoin de le nettoyer avant de revenir. Si cela se produit, ce sera un travail de cauchemar en parcourant toutes les déclarations.
En programmation C ++, vous avez des destructeurs et même maintenant des gardes de sortie. Tous ces éléments doivent être présents pour que le code soit protégé contre les exceptions en premier lieu. Le code est donc bien protégé contre une sortie anticipée. Par conséquent, cette opération ne présente aucun inconvénient logique et constitue uniquement un problème de style.
Je ne connais pas suffisamment Java pour savoir si le code de bloc sera finalement appelé et si les finaliseurs peuvent gérer le problème de la nécessité de s’assurer que quelque chose se passe.
C # Je ne peux certainement pas répondre à.
Le langage D vous donne les protections de sortie intégrées appropriées et est donc bien préparé pour une sortie anticipée et ne doit donc pas poser de problème autre que le style.
Les fonctions ne devraient évidemment pas être aussi longues en premier lieu, et si vous avez une énorme instruction switch, votre code est probablement aussi mal pris en compte.
la source
goto
et, éventuellement, un retour en deux points. Exemple (formatage de code non possible dans les commentaires):foo() { init(); if (bad) goto err; bar(); if (bad) goto err; baz(); return 0; err: cleanup(); return 1; }
Retour rapide pour le gagnant. Ils peuvent sembler laids, mais beaucoup moins laids que les gros
if
emballages, surtout s’il ya plusieurs conditions à vérifier.la source
J'utilise les deux.
Si
DoSomething
est 3-5 lignes de code alors le code est beau en utilisant la première méthode de formatage.Mais s'il a beaucoup plus de lignes que cela, alors je préfère le deuxième format. Je n'aime pas quand les crochets d'ouverture et de fermeture ne sont pas sur le même écran.
la source
Une raison classique pour une seule entrée, une seule sortie est que sinon, la sémantique formelle devient indiciblement laide (sinon, GOTO a été considéré comme nuisible).
En d'autres termes, il est plus facile de déterminer quand votre logiciel quittera la routine si vous n'avez qu'un seul retour. Ce qui est aussi un argument contre les exceptions.
En règle générale, je minimise l'approche de retour rapide.
la source
Personnellement, je préfère effectuer des contrôles de réussite / d’échec au début. Cela me permet de regrouper la plupart des défaillances les plus courantes au sommet de la fonction avec le reste de la logique à suivre.
la source
Ça dépend.
Retour anticipé s'il existe une impasse évidente à vérifier immédiatement qui rendrait inutile l'exécution du reste de la fonction. *
Définissez Retval + single return si la fonction est plus complexe et pourrait avoir plusieurs points de sortie sinon (problème de lisibilité).
* Cela peut souvent indiquer un problème de conception. Si vous constatez que bon nombre de vos méthodes doivent vérifier un état externe / paramater ou autre avant d'exécuter le reste du code, c'est probablement quelque chose qui devrait être traité par l'appelant.
la source
Fred
la fenêtre l’est déjàFred
, et définir le nom du contrôle à son état actuel forcerait le redessin (ce qui, même s’il est potentiellement utile dans certains cas, ennuyeux dans l’actuel), il serait parfaitement raisonnable d’avoir la méthode set-name early-exit si les anciens et les nouveaux noms correspondent.Utilisez un si
Dans le livre de Don Knuth sur GOTO, je lis qu'il donne une raison pour que la condition la plus probable soit toujours la première dans une déclaration if. En supposant que cela reste une idée raisonnable (et non une idée par pure considération pour la rapidité de l'époque). Je dirais que les retours anticipés ne sont pas de bonnes pratiques de programmation, surtout si l'on considère qu'ils sont le plus souvent utilisés pour la gestion des erreurs, à moins que votre code ne risque pas d'échouer que de ne pas échouer :-)
Si vous suivez les conseils ci-dessus, vous aurez besoin de mettre ce retour au bas de la fonction, et vous pourriez tout aussi bien ne pas l'appeler retour, il suffit de définir le code d'erreur et de le renvoyer deux lignes. Réalisant ainsi l'idéal 1 entrée 1 sortie.
Delphi Spécifique ...
Je suis d’avis que c’est une bonne pratique de programmation pour les programmeurs Delphi, bien que je n’en ai aucune preuve. Pré-D2009, nous ne disposons pas d' une manière atomique pour renvoyer une valeur, nous avons
exit;
etresult := foo;
ou nous pourrions simplement jeter des exceptions.Si vous deviez remplacer
pour
vous pourriez juste en avoir marre de voir cela au sommet de chacune de vos fonctions et préférer
et juste éviter
exit
complètement.la source
if true then Exit(foo);
J'utilise souvent la technique pour initialiserresult
ànil
ouFALSE
respectivement, puis pour vérifier toutes les conditions d'erreur et justeExit;
si l'une d'entre elles est remplie. Le cas de réussiteresult
est alors (généralement) défini quelque part à la fin de la méthode.Je suis d'accord avec l'énoncé suivant:
Tiré de cette question dans stackoverflow .
la source
J'utilise les retours anticipés presque exclusivement de nos jours, à l'extrême. J'écris ceci
comme
mais ce n'est pas grave. Si vous avez plus d'un ou deux niveaux d'imbrication dans vos fonctions, ils doivent être supprimés.
la source
Je préférerais écrire:
la source
DoSomeFunctionIfSomeCondition
?Comme vous, j’écris habituellement le premier mais préfère le dernier. Si j'ai beaucoup de contrôles imbriqués, je refactorise généralement à la deuxième méthode.
Je n'aime pas la façon dont le traitement des erreurs est éloigné du chèque.
Je préfère ça:
la source
Les conditions sur le dessus sont appelées "conditions préalables". En mettant
if(!precond) return;
, vous listez visuellement toutes les conditions préalables.L'utilisation du grand bloc "if-else" peut augmenter le temps d'indentation (j'ai oublié la citation concernant les indentations à 3 niveaux).
la source
Je préfère garder si les déclarations sont petites.
Alors, choisissez entre:
et
Je choisirais ce que vous avez décrit comme un "retour anticipé".
Remarquez, je me fous des retours anticipés ou autres, j'aime vraiment simplifier le code, raccourcir le corps des déclarations if, etc.
Niché si et pour et tandis que sont horribles , évitez-les à tout prix.
la source
Comme d’autres disent, ça dépend. Pour les petites fonctions qui renvoient des valeurs, je peux coder les premiers retours. Mais pour les fonctions importantes, j'aime toujours avoir une place dans le code où je sais que je peux mettre quelque chose qui sera exécuté avant son retour.
la source
Je pratique l'échec rapide au niveau de la fonction. Il garde le code cohérent et propre (pour moi et ceux avec qui j'ai travaillé). Pour cette raison, je reviens toujours tôt.
Pour certaines conditions souvent vérifiées, vous pouvez implémenter des aspects pour ces vérifications si vous utilisez AOP.
la source