Question

Je l'ai souvent écrit ce genre de fonction dans les deux formats, et je me demandais si un format est 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 habituellement du code avec le premier puisque c'est la façon dont mon cerveau fonctionne pendant le codage, même si je crois que je préfère le 2e car il prend soin de toute erreur de manipulation tout de suite et je trouve plus facile à lire

Était-ce utile?

La solution

Je préfère le second style. Obtenez des cas invalides de la première manière, que ce soit simplement sortir ou déclencher des exceptions, le cas échéant, mettre une ligne vide là-bas, puis ajouter le corps « réel » de la méthode. Je trouve plus facile à lire.

Autres conseils

Certainement celui-ci. L'ancien ne regarde pas mal en ce moment, mais quand vous obtenez le code plus complexe, je ne peux pas imaginer que quelqu'un penserait ceci:

public int SomeFunction(bool cond1, string name, int value, AuthInfo perms)
{
    int retval = SUCCESS;
    if (someCondition)
    {
        if (name != null && name != "")
        {
            if (value != 0)
            {
                if (perms.allow(name)
                {
                    // Do Something
                }
                else
                {
                    reval = PERM_DENY;
                }
            }
            else
            {
                retval = BAD_VALUE;
            }
        }
        else
        {
            retval = BAD_NAME;
        }
    }
    else
    {
        retval = BAD_COND;
    }
    return retval;
}

est plus lisible que

public int SomeFunction(bool cond1, string name, int value, AuthInfo perms)
{
    if (!someCondition)
        return BAD_COND;

    if (name == null || name == "")
        return BAD_NAME;

    if (value == 0)
        return BAD_VALUE;

    if (!perms.allow(name))
        return PERM_DENY;

    // Do something
    return SUCCESS;
}

Je reconnais bien que je ne comprenais pas l'avantage des points de sortie unique.

Cela dépend - En général, je ne vais pas sortir de mon chemin pour essayer de déplacer un tas de code autour de sortir de la fonction début - le compilateur prendra généralement soin de cette pour moi. Cela dit cependant, s'il y a des paramètres de base en haut que j'ai besoin et ne peut pas continuer sinon, je Breakout tôt. De même, si une condition génère un bloc géant if en fonction, je l'aurai breakout tôt à la suite de cela aussi.

Cela dit cependant, si une fonction nécessite des données lorsqu'elle est appelée, je vais habituellement à lancer une exception (voir exemple) par opposition à un retour.

public int myFunction(string parameterOne, string parameterTwo) {
  // Can't work without a value
  if (string.IsNullOrEmpty(parameterOne)) {
    throw new ArgumentNullException("parameterOne");
  } 
  if (string.IsNullOrEmpty(parameterTwo)) {
    throw new ArgumentNullException("parameterTwo");
  }

  // ...      
  // Do some work
  // ...

  return value;
}

Je préfère le retour rapide.

Si vous avez un point d'entrée et un point de sortie, vous devez toujours suivre tout le code dans votre tête tout le chemin jusqu'au point de sortie (on ne sait jamais si un autre morceau de soufflet de code fait quelque chose d'autre au résultat , donc vous devez le suivre jusqu'à la exist). Vous le faites pas mater quelle branche détermine le résultat final. Il est difficile à suivre.

Avec une entrée et plusieurs existe, vous revenez quand vous avez votre résultat et ne se soucient pas suivi tout le chemin vers le bas pour voir que personne ne fait rien d'autre à (car il n'y aura pas autre chose depuis votre retour) . Il est comme avoir la scission du corps de la méthode en plusieurs étapes, qui chaque étape avec la possibilité de retourner le résultat ou laisser l'étape suivante tenter sa chance.

Dans la programmation C où vous devez nettoyer manuellement il y a beaucoup à dire pour le retour d'un point. Même s'il n'y a pas besoin en ce moment à quelque chose de propre, quelqu'un pourrait modifier votre fonction, allouer quelque chose et la nécessité de le nettoyer avant le retour. Si cela arrive, il sera un travail cauchemardesque en regardant à travers toutes les déclarations de retour.

En C ++ de programmation que vous avez et même maintenant Destructeurs gardes-champ de sortie. Tous ces aspects doivent être ici pour assurer que le code est exception de sécurité en premier lieu, si le code est bien gardé contre la sortie précoce et donc faire n'a donc aucun inconvénient logique et est purement une question de style.

Je ne suis pas assez bien informés sur Java, si le code de bloc « enfin » sera appelé et si finalizers peuvent gérer la situation de devoir assurer quelque chose qui se passe.

C # Je ne peut certainement pas répondre à.

D-langue vous donne des gardes-champ de sortie appropriée, intégrée et est donc bien préparé pour la sortie précoce et ne devrait donc pas présenter un problème autre que le style.

Fonctions devrait être de bien sûr pas si longtemps, en premier lieu, et si vous avez une déclaration énorme commutateur votre code est probablement aussi mal pris en compte.

Les premiers retours pour-la-victoire. Ils peuvent sembler laid, mais beaucoup moins laid que les gros emballages de if, surtout s'il y a plusieurs conditions à vérifier.

J'utilise les deux.

Si DoSomething est de 3-5 lignes de code, puis le code regarder tout simplement magnifique en utilisant la première méthode mise en forme.

Mais si elle a beaucoup plus de lignes que cela, alors je préfère le second format. Je ne aime pas quand les crochets d'ouverture et de fermeture ne sont pas sur le même écran.

Une raison classique pour une seule entrée-sortie est unique qui, autrement, la sémantique formelle deviennent effroyablement laid autrement (même raison GOTO a été considéré comme nocif).

Autrement dit, il est plus facile de raisonner quand votre logiciel quittera la routine si vous avez seulement 1 retour. Ce qui est également un argument contre des exceptions.

En général, je minimiser l'approche précoce retour.

Personnellement, je préfère faire réussite / échec des contrôles de l'état au début. Cela me permet de regrouper la plupart des communes la plupart des échecs au sommet de la fonction avec le reste de la logique à suivre.

Cela dépend.

retour tôt s'il y a une condition d'impasse évidente pour vérifier tout de suite qui ferait courir le reste de l'inutile fonction. *

Set retVal + retour simple si la fonction est plus complexe et pourrait avoir plusieurs points de sortie autrement (émettre de la lisibilité).

* Cela peut souvent indiquer un problème de conception. Si vous trouvez que beaucoup de vos méthodes ont besoin de vérifier un état externe / ou de paramater comme avant d'exécuter le reste du code, qui est probablement quelque chose qui devrait être pris en charge par l'appelant.

Utilisez un Si

Dans Don livre de Knuth sur I GOTO lui donner lecture une raison pour avoir toujours la plus probable état venir d'abord dans une instruction if. En supposant que cela est encore une idée raisonnable (et non une considération de pure pour la vitesse de l'époque). Je dirais que premiers rendements ne sont pas bonnes pratiques de programmation, en particulier compte tenu du fait qu'ils sont le plus souvent utilisé pour le traitement des erreurs, à moins que votre code est plus susceptible d'échouer que ne manquera pas :-)

Si vous suivez les conseils ci-dessus, vous aurez besoin de mettre ce retour en bas de la fonction, et vous pourriez aussi appeler bien même pas un retour là-bas, il suffit de définir le code d'erreur et le retourner deux lignes donc . réalisant ainsi la 1 entrée 1 sortie idéale.

Delphi spécifique ...

Je suis de l'esprit que c'est une bonne pratique de programmation pour les programmeurs Delphi, bien que je n'ai aucune preuve. Pré-D2009, nous ne disposons pas d'une manière atomique pour renvoyer une valeur, nous avons exit; et result := foo; ou nous pourrions simplement jeter des exceptions.

Si vous deviez remplacer

if (true) {
 return foo;
} 

pour

if true then 
begin
  result := foo; 
  exit; 
end;

vous pourriez tomber malade de voir qu'au sommet de chacun de vos fonctions et préfèrent

if false then 
begin
  result := bar;

   ... 
end
else
   result := foo;

et juste éviter exit tout à fait.

Je suis d'accord avec l'énoncé suivant:

Je suis personnellement fan de clauses de garde (Le deuxième exemple), car elle réduit la indentation de la fonction. Quelques personnes ne pas comme eux parce qu'il en résulte de multiples points de retour de la fonction, mais je pense qu'il est plus clair avec eux.

cette question dans stackoverflow .

J'utilise presque exclusivement des rendements au début de nos jours, à l'extrême. Je vous écris cette

self = [super init];

if (self != nil)
{
    // your code here
}

return self;

self = [super init];
if (!self)
    return;

// your code here

return self;

mais il n'a pas d'importance. Si vous avez plus d'un ou deux niveaux d'imbrication dans vos fonctions, ils doivent être abîmés.

Je préférerais écrire:

if(someCondition)
{
    SomeFunction();
}

Comme vous, je l'habitude d'écrire le premier, mais préfère le dernier. Si j'ai beaucoup de contrôles imbriqués i factoriser généralement à la deuxième méthode.

Je ne aime pas comment la gestion des erreurs est déplacé loin de la vérification.

if not error A
  if not error B
    if not error C
      // do something
    else handle error C
  else handle error B
else handle error A

Je préfère ceci:

if error A
  handle error A; return
if error B
  handle error B; return
if error C
  handle error C; return

// do something

Les conditions sur le dessus sont appelées « conditions préalables ». En mettant if(!precond) return;, vous énumérez visuellement toutes les conditions.

Utilisation du grand « if-else » bloc peut augmenter les frais généraux tiret (j'ai oublié la citation sur 3 niveaux indentations).

Je préfère garder si les déclarations de petite taille.

Ainsi, le choix entre:

if condition:
   line1
   line2
    ...
   line-n

et

if not condition: return

line1
line2
 ...
line-n

Je choisis ce que vous avez décrit comme « retour rapide ».

Rappelez-vous, je ne se soucient pas des retours précoces ou peu importe, je viens vraiment de simplifier le code, raccourcir les corps des instructions if, etc.

si Nested et pour de son et alors que ce sont horribles , les éviter à tout prix.

Comme d'autres disent, cela dépend. Pour de petites fonctions qui renvoient des valeurs, je code retourne tôt. Mais pour des fonctions importantes, je aime avoir toujours une place dans le code où je sais que je peux mettre quelque chose qui va s'exécuter avant qu'il ne revienne.

Je pratique l'échec rapide au niveau de la fonction. Il maintient le code cohérent et propre (pour moi et ceux que j'ai travaillé). A cause de cela, je reviens toujours au début.

Pour certaines conditions souvent vérifiées, vous pouvez mettre en œuvre les aspects de ces contrôles si vous utilisez AOP.

Licencié sous: CC-BY-SA avec attribution
scroll top