Une fonction ne devrait-elle avoir qu'un seul retour?

y a-t-il de bonnes raisons pour lesquelles c'est une meilleure pratique de n'avoir qu'une seule déclaration dans une fonction?

ou est-il acceptable de revenir d'une fonction dès qu'il est logiquement correct de le faire, ce qui signifie qu'il peut y avoir plusieurs déclarations de retour dans la fonction?

781
demandé sur Tim Post 2008-08-31 13:26:55
la source

30 ответов

j'ai souvent plusieurs déclarations au début d'une méthode de retour "facile" des situations. Par exemple, ceci:

public void DoStuff(Foo foo)
{
    if (foo != null)
    {
        ...
    }
}

... peut être rendu plus lisible (IMHO) comme ceci:

public void DoStuff(Foo foo)
{
    if (foo == null) return;

    ...
}

donc oui, je pense que c'est bien d'avoir plusieurs" points de sortie " d'une fonction/méthode.

743
répondu Matt Hamilton 2015-03-11 23:40:44
la source

personne n'a mentionné ou cité Code complet donc je vais le faire.

17.1 retour

réduire au minimum le nombre de retours dans chaque routine . C'est plus difficile de comprendre une routine si, en la lisant en bas, vous n'êtes pas conscient de la possibilité qu'elle soit revenue quelque part au-dessus.

utilisez un retour quand il améliore la lisibilité . Dans certaines routines, une fois que vous connaissez la réponse, vous voulez la retourner à la routine d'appel immédiatement. Si la routine est définie de telle manière qu'elle ne nécessite aucun nettoyage, ne pas revenir immédiatement signifie que vous devez écrire plus de code.

355
répondu Chris S 2014-03-17 14:01:35
la source

je dirais qu'il serait incroyablement imprudent de décider arbitrairement contre plusieurs points de sortie car j'ai trouvé la technique utile dans la pratique encore et encore , en fait j'ai souvent refactorisé le code existant à plusieurs points de sortie pour plus de clarté. Nous pouvons comparer les deux approches ainsi:-

string fooBar(string s, int? i) {
  string ret = "";
  if(!string.IsNullOrEmpty(s) && i != null) {
    var res = someFunction(s, i);

    bool passed = true;
    foreach(var r in res) {
      if(!r.Passed) {
        passed = false;
        break;
      }
    }

    if(passed) {
      // Rest of code...
    }
  }

  return ret;
}

comparez ceci au code où plusieurs points de sortie sont autorisés:-

string fooBar(string s, int? i) {
  var ret = "";
  if(string.IsNullOrEmpty(s) || i == null) return null;

  var res = someFunction(s, i);

  foreach(var r in res) {
      if(!r.Passed) return null;
  }

  // Rest of code...

  return ret;
}

je pense que ce dernier est beaucoup plus clair. Pour autant que je puisse dire, la critique des points de sortie multiples est un point de vue assez archaïque de nos jours.

229
répondu ljs 2014-06-06 18:30:57
la source

je travaille actuellement sur une base de code où deux des personnes qui travaillent dessus souscrivent aveuglément à la théorie du" point unique de sortie " et je peux vous dire que de l'expérience, c'est une pratique horrible et horrible. Cela rend le code extrêmement difficile à maintenir et je vais vous montrer pourquoi.

avec la théorie du "point de Sortie unique", on se retrouve inévitablement avec un code qui ressemble à ceci:

function()
{
    HRESULT error = S_OK;

    if(SUCCEEDED(Operation1()))
    {
        if(SUCCEEDED(Operation2()))
        {
            if(SUCCEEDED(Operation3()))
            {
                if(SUCCEEDED(Operation4()))
                {
                }
                else
                {
                    error = OPERATION4FAILED;
                }
            }
            else
            {
                error = OPERATION3FAILED;
            }
        }
        else
        {
            error = OPERATION2FAILED;
        }
    }
    else
    {
        error = OPERATION1FAILED;
    }

    return error;
}

non seulement cela rend le code très dur à suivre, mais maintenant dire plus tard vous avez besoin de revenir en arrière et ajouter une opération entre 1 et 2. Vous devez indenter à peu près toute la fonction flippante, et bonne chance en s'assurant que toutes vos conditions if/else et bretelles sont assortis correctement.

cette méthode rend la maintenance du code extrêmement difficile et sujette aux erreurs.

191
répondu 17 of 26 2008-08-31 16:50:37
la source

Structured programming dit que vous ne devriez jamais avoir qu'un seul État de retour par fonction. C'est à la limite de la complexité. Beaucoup de gens comme Martin Fowler soutiennent qu'il est plus simple d'écrire des fonctions avec plusieurs instructions return. Il présente cet argument dans le classique refactoring Livre qu'il a écrit. Cela fonctionne bien si vous suivez ses autres conseils et écrire de petites fonctions. Je suis d'accord avec ce point de vue et seulement strict les puristes de programmation structurée adhèrent à des déclarations de retour uniques par fonction.

72
répondu cdv 2009-09-05 14:56:54
la source

comme Kent Beck le fait remarquer lorsqu'il parle des clauses de garde dans Implementation Patterns making a routine have a single entry and exit point ...

" était d'éviter la confusion possible en sautant dans et hors de beaucoup de endroits dans la même routine. Il fait bon sens lorsqu'on l'applique à FORTRAN ou programmes de langues de l'Assemblée écrits avec beaucoup de données mondiale où même comprendre quels sont les énoncés d'exécution a été labeur. .. avec de petites méthodes et surtout des données locales, c'est inutilement conservateur."

je trouve une fonction écrite avec des clauses de garde beaucoup plus facile à suivre qu'un long tas emboîté de déclarations if then else .

62
répondu blank 2008-08-31 13:48:40
la source

dans une fonction qui n'a pas d'effets secondaires, il n'y a aucune bonne raison d'avoir plus d'un retour simple et vous devriez les écrire dans un style fonctionnel. Dans une méthode avec des effets secondaires, les choses sont plus séquentielles (indexées dans le temps), donc vous écrivez dans un style impératif, en utilisant la déclaration de retour comme une commande pour arrêter l'exécution.

en d'autres termes, si possible, favoriser ce style

return a > 0 ?
  positively(a):
  negatively(a);

sur ce

if (a > 0)
  return positively(a);
else
  return negatively(a);

Si vous vous trouvez en train d'écrire plusieurs couches de conditions imbriquées, il y a probablement un moyen de reformuler cela, en utilisant la liste de prédicat par exemple. Si vous constatez que vos SI et vos else sont très éloignés syntaxiquement, vous pourriez vouloir les décomposer en plus petites fonctions. Un bloc conditionnel qui s'étend sur plus d'un écran de texte est difficile à lire.

il n'y a pas de règle dure et rapide qui s'applique à toutes les langues. Quelque chose comme avoir une seule déclaration de retour ne fera pas votre code est bon. Mais bon code aura tendance à vous permettre d'écrire vos fonctions de cette façon.

61
répondu Apocalisp 2008-09-07 22:06:17
la source

j'ai vu dans les standards de codage pour C++ que c'était un hang-over de C, comme si vous n'aviez pas de RAII ou d'autre gestion de mémoire automatique alors vous devez nettoyer pour chaque retour, ce qui signifie soit couper-coller du nettoyage ou un goto (logiquement le même que 'enfin' dans les langages gérés), les deux sont considérés comme une mauvaise forme. Si vos pratiques sont d'utiliser des pointeurs et des collections intelligents en C++ ou un autre système de mémoire automatique, alors il n'y a pas une raison forte pour cela, et il devenez tout au sujet de la lisibilité, et plus d'un appel de jugement.

43
répondu Pete Kirkham 2010-10-28 12:36:51
la source

Je m'appuie sur l'idée que les déclarations de retour dans le milieu de la fonction sont mauvais. Vous pouvez utiliser des retours pour construire quelques clauses de garde au sommet de la fonction, et bien sûr dire au compilateur quoi retourner à la fin de la fonction sans problème, mais les retours dans le milieu de la fonction peut être facile à manquer et peut rendre la fonction plus difficile à interpréter.

40
répondu Joel Coehoorn 2010-07-14 23:15:45
la source

y a-t-il de bonnes raisons pour lesquelles c'est une meilleure pratique de n'avoir qu'une seule déclaration dans une fonction?

Oui , il y a:

  • le point de Sortie unique donne un excellent endroit pour affirmer vos post-conditions.
  • Être capable de mettre un débogueur point d'arrêt sur l'un retour à la fin de la fonction est souvent utile.
  • moins retourne signifie moins de complexité. Le code linéaire est généralement plus simple à comprendre.
  • Si essayer de simplifier une fonction à un seul retour provoque complexité, alors c'est une incitation à se réorienter vers des fonctions plus petites, plus Générales, plus faciles à comprendre.
  • si vous êtes dans une langue sans destructeurs ou si vous n'utilisez pas Rai, alors un seul retour réduit le nombre d'endroits que vous devez nettoyer.
  • certaines langues nécessitent une point de sortie (par exemple Pascal et Eiffel).

la question est souvent posée comme une fausse dichotomie entre des déclarations multiples ou profondément imbriquées. Il y a presque toujours une troisième solution qui est très linéaire (pas de nidification profonde) avec un seul point de sortie.

mise à Jour : Apparemment MISRA lignes directrices de promouvoir la sortie unique , trop.

pour être clair, Je ne dis pas que c'est toujours mal d'avoir plusieurs retours. Mais étant donné les solutions par ailleurs équivalentes, il ya beaucoup de bonnes raisons de préférer celui avec un seul retour.

38
répondu Adrian McCarthy 2017-05-23 15:10:48
la source

avoir un point de Sortie unique offre un avantage au débogage, car il vous permet de définir un point de rupture unique à la fin d'une fonction pour voir quelle valeur va réellement être retournée.

33
répondu Mark 2014-11-04 00:58:47
la source

En général, j'essaie d'avoir un seul point de sortie à partir d'une fonction. Il y a des fois, cependant, que le faire finit en fait par créer un corps de fonction plus complexe qu'il n'est nécessaire, auquel cas il est préférable d'avoir plusieurs points de sortie. Il faut vraiment qu'il s'agisse d'un" appel de jugement " basé sur la complexité résultante, mais l'objectif devrait être le moins de points de sortie possible sans sacrifier la complexité et la compréhensibilité.

19
répondu Scott Dorman 2016-01-08 22:37:01
la source

non, parce que nous ne vivons plus dans les années 1970 . Si votre fonction est assez longue pour que les retours multiples soient un problème, c'est trop long.

(indépendamment du fait que toute fonction multiligne dans une langue avec des exceptions aura de toute façon plusieurs points de sortie.)

14
répondu Ben Lings 2010-07-14 23:31:14
la source

Ma préférence serait pour une seule sortie à moins que cela complique vraiment les choses. J'ai constaté que, dans certains cas, plusieurs points existants peuvent masquer d'autres problèmes de conception plus importants:

public void DoStuff(Foo foo)
{
    if (foo == null) return;
}

en voyant ce code, je demanderais immédiatement:

  • est-ce que " foo " est toujours nul?
  • si oui, combien de clients de 'DoStuff' appellent la fonction avec un 'foo'nul?

selon sur les réponses à ces questions, il pourrait être que

  1. la vérification est inutile, car il n'est jamais vrai (c'est à dire. il devrait être une affirmation)
  2. la vérification est très rarement vraie et il peut donc être préférable de changer ces fonctions spécifiques de l'appelant car ils devraient probablement prendre une autre mesure de toute façon.

Dans les deux cas ci-dessus, le code peut probablement être retravaillé avec une affirmation à ce que " foo " n'est jamais nulle et les appelants changé.

il y a deux autres raisons (spécifiques je pense au code C++) où multiple existe peut effectivement avoir un négatif affecter. Ce sont des optimisations de taille de code et de compilateur.

un objet C++ non-POD dans scope à la sortie d'une fonction aura son destructeur appelé. Lorsqu'il y a plusieurs déclarations de retour, il se peut qu'il y ait différents objets dans la portée et donc la liste des les destructeurs seront différents. Le compilateur doit donc générer du code pour chaque instruction de retour:

void foo (int i, int j) {
  A a;
  if (i > 0) {
     B b;
     return ;   // Call dtor for 'b' followed by 'a'
  }
  if (i == j) {
     C c;
     B b;
     return ;   // Call dtor for 'b', 'c' and then 'a'
  }
  return 'a'    // Call dtor for 'a'
}

si la taille du code est un problème-alors cela peut être quelque chose qui vaut la peine d'éviter.

l'autre problème concerne l '" optimisation de la valeur de retour "(aka Copy Elision, ISO C++ ' 03 12.8/15). C++ permet à une implémentation de sauter l'appel au constructeur de copie si elle le peut:

A foo () {
  A a1;
  // do something
  return a1;
}

void bar () {
  A a2 ( foo() );
}

prend juste le code comme is, l'objet 'a1' est construit en 'foo' et sa copie sera appelée pour construire 'a2'. Cependant, copy elision permet au compilateur de construire 'a1' au même endroit sur la pile que 'a2'. Il n'est donc pas nécessaire de "copier" l'objet lorsque la fonction retourne.

plusieurs points de sortie complique le travail du compilateur en essayant de le détecter, et au moins pour une version relativement récente de VC++ l'optimisation n'a pas eu lieu où le le corps fonctionnel a eu des retours multiples. Voir nommé optimisation de la valeur de retour dans Visual C++ 2005 pour plus de détails.

14
répondu Richard Corden 2015-03-11 23:42:08
la source

ayant un point de Sortie unique réduit complexité cyclomatique et donc, en théorie , réduit la probabilité que vous introduirez des bugs dans votre code quand vous le Modifiez. La pratique, cependant, tend à suggérer qu'une approche plus pragmatique est nécessaire. J'ai donc tendance à viser un point de Sortie unique, mais à permettre à mon code d'en avoir plusieurs si celui-ci est plus lisible.

11
répondu John Channing 2008-09-03 01:17:52
la source

je me force à n'utiliser qu'une seule déclaration return , car elle générera en un sens une odeur de code. Laissez-moi vous expliquer:

function isCorrect($param1, $param2, $param3) {
    $toret = false;
    if ($param1 != $param2) {
        if ($param1 == ($param3 * 2)) {
            if ($param2 == ($param3 / 3)) {
                $toret = true;
            } else {
                $error = 'Error 3';
            }
        } else {
            $error = 'Error 2';
        }
    } else {
        $error = 'Error 1';
    }
    return $toret;
}

(les conditions sont arbritary...)

plus les conditions, plus la fonction est grande, plus elle est difficile à lire. Donc si vous êtes à l'écoute de l'odeur du code, vous le réaliserez, et vous voudrez reformuler le code. Deux solutions possibles sont:

  • déclarations multiples
  • Refactoring dans la séparation des fonctions de

Déclarations Multiples

function isCorrect($param1, $param2, $param3) {
    if ($param1 == $param2)       { $error = 'Error 1'; return false; }
    if ($param1 != ($param3 * 2)) { $error = 'Error 2'; return false; }
    if ($param2 != ($param3 / 3)) { $error = 'Error 3'; return false; }
    return true;
}

Fonctions Séparées

function isEqual($param1, $param2) {
    return $param1 == $param2;
}

function isDouble($param1, $param2) {
    return $param1 == ($param2 * 2);
}

function isThird($param1, $param2) {
    return $param1 == ($param2 / 3);
}

function isCorrect($param1, $param2, $param3) {
    return !isEqual($param1, $param2)
        && isDouble($param1, $param3)
        && isThird($param2, $param3);
}

certes, c'est plus long et un peu désordonné, mais dans le processus de remaniement de la fonction de cette façon, nous avons

  • a créé un certain nombre de fonctions réutilisables,
  • a rendu la fonction plus lisible, et
  • l'attention des fonctions est pourquoi les valeurs sont correctes.
11
répondu Jrgns 2015-11-30 12:57:18
la source

je dirais que vous devriez en avoir autant que nécessaire, ou tout autre qui rend le code plus propre (comme clauses de garde ).

personnellement, je n'ai jamais entendu/vu de" meilleures pratiques " dire que vous ne devriez avoir qu'une seule déclaration de retour.

pour la plupart, j'ai tendance à quitter une fonction le plus tôt possible sur la base d'un chemin logique (les clauses de garde en sont un excellent exemple).

10
répondu Rob Cooper 2008-08-31 13:30:18
la source

je crois que les retours multiples sont généralement bons (dans le code que j'écris en C#). Le style de retour simple est un hold-over de C. Mais vous n'êtes probablement pas le codage en C.

il n'y a pas de loi exigeant un seul point de sortie pour une méthode dans tous les langages de programmation . Certaines personnes insistent sur la supériorité de ce style, et parfois ils l'élèvent à une "règle" ou "loi", mais cette croyance n'est soutenue par aucune preuve ou recherche.

plus d'un style de retour peut être une mauvaise habitude dans le code C, où les ressources doivent être explicitement dé-affectées, mais les langues telles que Java, C#, Python ou JavaScript qui ont des constructions telles que la collecte automatique des ordures et try..finally blocs (et using blocs dans C#), et cet argument ne s'applique pas - dans ces langues, il est très rare d'avoir besoin d'une déallocation manuelle centralisée des ressources.

il y a des cas où un seul retour est plus lisible, et les cas où il ne l'est pas. Voir si cela réduit le nombre de lignes de code, rend la logique plus claire ou réduit le nombre d'accolades et d'indents ou de variables temporaires.

par conséquent, utilisez autant de retours que vous le souhaitez, car il s'agit d'un problème de mise en page et de lisibilité, et non d'un problème technique.

j'ai parlé de plus longuement sur mon blog .

10
répondu Anthony 2012-12-04 14:16:38
la source

il y a de bonnes choses à dire sur le fait d'avoir un seul point de sortie, tout comme il y a de mauvaises choses à dire sur l'inévitable " Flèche programmation qui en résulte.

si j'utilise plusieurs points de sortie lors de la validation des entrées ou de l'affectation des ressources, j'essaie de placer toutes les 'sorties d'erreur' très visiblement en haut de la fonction.

à la fois le programmation Spartan article du "SSDSLPedia" et le point de sortie de fonction unique article du" Wiki du dépôt de Pattern de Portland " ont quelques arguments perspicaces à ce sujet. Aussi, bien sûr, il y a ce poste à considérer.

si vous voulez vraiment un seul exit-point (dans n'importe quelle langue non-exception) par exemple pour libérer des ressources en un seul endroit, je trouve que l'application soigneuse de goto est bonne; Voir par exemple cet exemple plutôt artificiel (compressé pour sauver l'écran immobilier):

int f(int y) {
    int value = -1;
    void *data = NULL;

    if (y < 0)
        goto clean;

    if ((data = malloc(123)) == NULL)
        goto clean;

    /* More code */

    value = 1;
clean:
   free(data);
   return value;
}

personnellement, en général, je n'aime pas la programmation de flèches plus que je n'aime pas les points de sortie multiples, bien que les deux soient utiles lorsqu'ils sont appliqués correctement. Le meilleur, bien sûr, est de structurer votre programme à exiger ni. Décomposer votre fonction en plusieurs morceaux habituellement aider:)

bien qu'en faisant cela, je me retrouve avec plusieurs points de sortie de toute façon comme dans cet exemple, où une fonction plus grande a été brisée en bas dans plusieurs petites fonctions:

int g(int y) {
  value = 0;

  if ((value = g0(y, value)) == -1)
    return -1;

  if ((value = g1(y, value)) == -1)
    return -1;

  return g2(y, value);
}

selon le projet ou les lignes directrices de codage, la plupart des codes de la chaudière pourraient être remplacés par des macros. Comme note d'accompagnement, le décomposer de cette façon rend les fonctions g0, g1 ,g2 très facile à tester individuellement.

évidemment, dans un langage OO et d'exception, Je n'utiliserais pas si-des déclarations comme ça (ou du tout, si je pouvais m'en tirer avec peu d'effort), et le code serait beaucoup plus clair. Et non arrowy. Et la plupart des déclarations non finales seraient probablement des exceptions.

en bref;

  • Quelques retours sont mieux que beaucoup de retours
  • plus d'un retour vaut mieux que des flèches énormes, et clauses de garde sont généralement ok.
  • les Exceptions pourraient / devraient probablement remplacer la plupart des "clauses de sauvegarde" lorsque cela est possible.
10
répondu Henrik Gustafsson 2015-03-11 23:44:19
la source

Vous connaissez l'adage: la beauté est dans les yeux du spectateur .

certains jurent par NetBeans et certains par IntelliJ IDEA , certains par Python et certains par PHP .

dans certains magasins, vous pourriez perdre votre emploi si vous insistez pour le faire:

public void hello()
{
   if (....)
   {
      ....
   }
}

la question est tout au sujet de la visibilité et maintenabilité.

je suis accro à l'utilisation de l'algèbre booléenne pour réduire et simplifier la logique et l'utilisation de machines d'état. Cependant, il y avait des collègues passés qui ont estimé que mon emploi de "techniques mathématiques" dans le codage n'est pas approprié, parce qu'il ne serait pas visible et maintenable. Et que serait une mauvaise pratique. Désolé les gens, les techniques que j'emploie est très visible et maintenable pour moi - parce que quand je reviens au code six mois plus tard, je comprendrais le code clairement plutôt voir un gâchis de spaghetti proverbial.

Hey buddy (comme disait un ancien client) fais ce que tu veux tant que tu sais comment le réparer quand j'ai besoin de toi pour le réparer.

je me souviens qu'il y a 20 ans, un de mes collègues a été congédié pour avoir utilisé ce qu'on appellerait aujourd'hui développement agile stratégie. Il avait un plan méticuleux. Mais son manager lui hurlait :" tu ne peux pas libérer progressivement les fonctionnalités pour les utilisateurs! Vous devez coller avec le chute d'eau ."Sa réponse au directeur était que le développement progressif serait plus précis aux besoins du client. Il croyait au développement en fonction des besoins des clients, mais le gestionnaire croyait au codage en fonction des "exigences du client".

nous sommes souvent coupables d'avoir brisé la normalisation des données, MVP et MVC limites. Nous inline au lieu de construire un fonction. Nous prenons des raccourcis.

Personnellement, je crois que PHP est une mauvaise pratique, mais que sais-je. Tous les arguments théoriques se résume à essayer de remplir un ensemble de règles

qualité = précision, maintenabilité et de la rentabilité.

toutes les autres règles s'effacent à l'arrière-plan. Et bien sûr, cette règle ne disparaît jamais:

la Paresse est la vertu d'une bon programmeur.

9
répondu Blessed Geek 2015-03-11 23:44:58
la source

je penche vers l'utilisation de clauses de garde pour revenir tôt et autrement sortir à la fin d'une méthode. La règle de l'entrée et de la sortie uniques a une signification historique et a été particulièrement utile pour traiter le code d'héritage qui a couru à 10 pages A4 pour une seule méthode C++ avec des retours multiples (et de nombreux défauts). Plus récemment, la bonne pratique acceptée est de garder les méthodes petites, ce qui rend les sorties multiples moins impédantes à comprendre. Dans L'exemple suivant de Kronoz copié d'en haut, la question Est de savoir ce qui se passe dans //reste du code... ?:

void string fooBar(string s, int? i) {

  if(string.IsNullOrEmpty(s) || i == null) return null;

  var res = someFunction(s, i);

  foreach(var r in res) {
      if(!r.Passed) return null;
  }

  // Rest of code...

  return ret;
}

je me rends compte que l'exemple est quelque peu artificiel, mais je serais tenté de reformuler la boucle foreach en un énoncé LINQ qui pourrait alors être considéré comme une clause de garde. Encore une fois, dans un exemple artificiel l'intention du code n'est pas apparente et someFunction () peut avoir un autre effet secondaire ou le résultat peut être utilisé dans le / / reste du code... .

if (string.IsNullOrEmpty(s) || i == null) return null;
if (someFunction(s, i).Any(r => !r.Passed)) return null;

donnant la fonction remaniée suivante:

void string fooBar(string s, int? i) {

  if (string.IsNullOrEmpty(s) || i == null) return null;
  if (someFunction(s, i).Any(r => !r.Passed)) return null;

  // Rest of code...

  return ret;
}
9
répondu David Clarke 2015-03-11 23:46:44
la source

une bonne raison à laquelle je peux penser est pour la maintenance du code: vous avez un seul point de sortie. Si vous souhaitez modifier le format du résultat... il est juste beaucoup plus simple à mettre en œuvre. Aussi, pour le débogage, vous pouvez simplement y coller un point de rupture:)

cela dit, j'ai dû travailler une fois dans une bibliothèque où les normes de codage imposaient "une instruction de retour par fonction", et j'ai trouvé cela assez difficile. J'écris beaucoup de code de calcul numérique, et il y a souvent "cas particuliers", de sorte que le code a fini par être assez difficile à suivre...

7
répondu OysterD 2008-08-31 13:31:16
la source

les points de sortie multiples sont parfaits pour des fonctions assez petites -- c'est-à-dire, une fonction qui peut être vue sur une longueur d'écran sur sa totalité. Si une longue fonction comprend également plusieurs points de sortie, c'est un signe que la fonction peut être haché.

Que dit-je éviter de multiples fonctions quitter , sauf si absolument nécessaire . J'ai senti la douleur des insectes qui sont dus à un certain retour errant dans une ligne obscure dans plus complexe fonction.

7
répondu Jon Limjap 2008-08-31 17:38:46
la source

j'ai travaillé avec des normes de codage terribles qui ont forcé une seule voie de sortie sur vous et le résultat est presque toujours spaghetti non structuré si la fonction est quelque chose mais trivial -- vous finissez avec beaucoup de pauses et continue qui juste obtenir dans le chemin.

6
répondu Phil Bennett 2008-08-31 13:39:25
la source

Unique point de sortie, toutes choses égales rend le code beaucoup plus lisible. Mais il y a un hic: construction populaire

resulttype res;
if if if...
return res;

est un faux, "res=" n'est pas beaucoup mieux que le "retour". Il a l'instruction de retour simple, mais les points multiples où la fonction se termine réellement.

si vous avez une fonction avec des retours multiples (ou"res=" s), c'est souvent une bonne idée de la casser en plusieurs petites fonctions avec un seul point de sortie.

6
répondu ima 2008-09-11 11:39:18
la source

ma politique habituelle est de n'avoir qu'un seul retour à la fin d'une fonction à moins que la complexité du code soit grandement réduite en ajoutant plus. En fait, je suis plutôt un fan D'Eiffel, qui applique la seule règle de retour en n'ayant pas de déclaration de retour (il y a juste une variable "résultat" créée automatiquement pour mettre votre résultat).

il y a certainement des cas où le code peut être rendu plus clair avec des retours multiples que ne le serait la version évidente sans eux. Un pourrait argumenter que plus de travail est nécessaire si vous avez une fonction qui est trop complexe pour être compréhensible sans déclarations de retour multiples, mais parfois il est bon d'être pragmatique sur ces choses.

6
répondu Matt Sheppard 2008-09-11 11:48:45
la source

si vous avez plus de quelques retours, il peut y avoir un problème avec votre code. Dans le cas contraire, je conviens qu'il est parfois agréable de pouvoir revenir de plusieurs endroits dans un sous-programme, surtout quand cela rend le code plus propre.

Perl 6: Mauvais Exemple

sub Int_to_String( Int i ){
  given( i ){
    when 0 { return "zero" }
    when 1 { return "one" }
    when 2 { return "two" }
    when 3 { return "three" }
    when 4 { return "four" }
    ...
    default { return undef }
  }
}

serait mieux écrit comme ceci

Perl 6: Bon Exemple

@Int_to_String = qw{
  zero
  one
  two
  three
  four
  ...
}
sub Int_to_String( Int i ){
  return undef if i < 0;
  return undef unless i < @Int_to_String.length;
  return @Int_to_String[i]
}

Note c'était juste un exemple rapide

5
répondu Brad Gilbert 2008-09-15 19:53:45
la source

je vote pour un Seul retour à la fin comme une ligne directrice. Cela aide un nettoyage de code commun ... Par exemple, regardez le code suivant ...

void ProcessMyFile (char *szFileName)
{
   FILE *fp = NULL;
   char *pbyBuffer = NULL:

   do {

      fp = fopen (szFileName, "r");

      if (NULL == fp) {

         break;
      }

      pbyBuffer = malloc (__SOME__SIZE___);

      if (NULL == pbyBuffer) {

         break;
      }

      /*** Do some processing with file ***/

   } while (0);

   if (pbyBuffer) {

      free (pbyBuffer);
   }

   if (fp) {

      fclose (fp);
   }
}
5
répondu Alphaneo 2015-03-11 23:47:36
la source

c'est probablement une perspective inhabituelle, mais je pense que quiconque croit que les déclarations de retours multiples doivent être favorisées n'a jamais eu à utiliser un débogueur sur un microprocesseur qui supporte seulement 4 points de rupture du matériel. ;- )

alors que les problèmes de "code flèche" sont tout à fait corrects, un problème qui semble disparaître lorsque vous utilisez plusieurs déclarations de retour est dans la situation où vous utilisez un débogueur. Vous n'avez pas de pratique fourre-tout à un point d'arrêt pour garantir que vous allez voir de la sortie et donc le retour d'état.

4
répondu Andrew Edgecombe 2008-09-24 03:47:34
la source

plus vous avez d'instructions de retour dans une fonction, plus grande est la complexité de cette méthode. Si vous vous demandez si vous avez trop d'instructions de retour, vous pourriez vouloir vous demander si vous avez trop de lignes de code dans cette fonction.

mais, non, il n'y a rien de mal à une/plusieurs déclarations de retour. Dans certaines langues, c'est une meilleure pratique (c++) que dans d'autres (C).

4
répondu hazzen 2009-04-27 13:56:54
la source

Autres questions sur language-agnostic coding-style