2010-10-15 25 views
5

J'ai répondu à des discussions ici (ou au moins commented) avec des réponses contenant du code comme celui-ci, mais je me demande s'il est bon ou mauvais d'écrire une série de branches avec une (ou plusieurs) des branches rien en eux, généralement pour éliminer la vérification de null dans chaque branche.Est-ce qu'une branche Si ne fait rien d'une odeur de code ou d'une bonne pratique?

Un exemple (code C#):

if (str == null) { /* Do nothing */ } 
else if (str == "SomeSpecialValue") 
{ 
    // ... 
} 
else if (str.Length > 1) 
{ 
    // ... 
} 

au lieu de:

if (str != null && str == "SomeSpecialValue") 
{ 
    // ... 
} 
else if (str != null && str.Length > 1) 
{ 
    // ... 
} 

Et, bien sûr, cela est juste un exemple, comme je l'ai tendance à les utiliser avec un complexe plus grand et plus Des classes. Et dans la plupart de ces cas, une valeur null indiquerait de ne rien faire.

Pour moi, cela réduit la complication de mon code et a du sens quand je le vois. Alors, est-ce une bonne ou une mauvaise forme (une odeur de code, même)?

+1

Je pense que c'est bien si cela rend votre code plus lisible et évite les conditions alambiquées. Voter pour fermer, "est-ce bon ou mauvais" est trop subjectif. – casablanca

+3

Le fait que tous ces contrôles sont nécessaires "juste au cas où" la valeur est nulle est une odeur en soi, à mon humble avis. En faisant cela, vous cachez des bugs. – SimonJ

+1

@SimonJ: Bon point. Au moins dans ce cas, il devrait lancer une exception si une valeur null n'est pas attendue. – casablanca

Répondre

5

il est en effet bon d'éviter ce qui suit, car il inutilement revérifie l'une des conditions (le fait que le compilateur d'optimiser cette distance est à côté du point - il potentiellement marques plus de travail pour les gens qui essaient de lire votre code):

if (str != null && str == "SomeSpecialValue") 
{ 
    // ... 
} 
else if (str != null && str.Length > 1) 
{ 
    // ... 
} 

Mais il est plutôt bizarre de faire aussi ce que vous suggérez, ci-dessous:

if (str == null) { /* Do nothing */ } 
else if (str == "SomeSpecialValue") 
{ 
    // ... 
} 
else if (str.Length > 1) 
{ 
    // ... 
} 

Je dis cela est bizarre parce qu'il obscurcit votre intention et défie les attentes du lecteur.Si vous vérifiez une condition, les gens s'attendent à ce que vous fassiez quelque chose si elle est satisfaite - mais vous ne l'êtes pas. Ceci est parce que votre intention est de ne pas réellement processus la condition nulle, mais plutôt pour éviter un pointeur NULL lorsque vous vérifiez les deux conditions que vous êtes réellement intéressé. En effet, plutôt que d'avoir deux états conceptuels handle, avec une clause de santé mentale (entrée non nulle), il lit à la place comme vous avez trois états conceptuels à gérer. Le fait que, computationnellement, vous pourriez dire qu'il y a trois tels états est à côté du point - c'est moins clair.

L'approche habituelle de cas dans ce genre de situation est comme Oren A suggéré - vérifier l'hypothèse nulle, puis vérifiez les autres conditions à l'intérieur du bloc de résultat:

if (str != null) 
{ 
if (str == "SomeSpecialValue") 
{ 
    // ... 
} 
else if (str.Length > 1) 
{ 
    // ... 
} 
} 

Ceci est un peu plus d'une question style de lisibilité-amélioration, par opposition à un problème d'odeur de code.

EDIT: Cependant, si vous êtes prêt à la condition de ne rien faire, je ne très semblable à celle que vous avez inclus un commentaire « ne rien faire ». Sinon, les gens pourraient penser que vous avez simplement oublié de compléter le code.

+0

Voir edit - J'ai pris ça (la chaîne "[NULL]") parce que les gens se sont accrochés à ça. – palswim

+0

@palswim Okay. Mais notez que ce n'était pas vraiment le point principal de ma réponse. (Mais en même temps, ce code vient de quelque part - si c'est le code de production, c'est presque certainement une mauvaise chose). – user359996

+0

@ user359996: Non; Je ne voulais pas copier et coller mon code de production. J'essayais de penser à un exemple sur place. – palswim

21

Je préfère le faire comme this-

if (str != null) 
{ 
if (str == "[NULL]") 
{ 
    // ... 
} 
else if (str.Length > 1) 
{ 
    // ... 
} 
} 

Je pense que vous pouvez toujours « reformule » un if avec un corps vide en elle est la négation avec un corps, et qu'il semble mieux et est plus logique.

+1

Je pense que j'ai une aversion pour trop d'indentation Cela me sauve aussi un peu d'espace vertical, et en C#, au moins, je suis sûr que le compilateur le gérera bien – palswim

+1

Le compilateur le gérera bien, mais à mon humble avis, ce que vous dites a une logique maladroite Pourquoi dire "si ... alors ne rien faire", quand vous pouvez dire "sinon ... que faire .." A propos de l'identité, vous pouvez réduire le nombre d'espaces a l'onglet prend, ce qui peut aider au moins un peu –

+2

Ne pas vouloir correctement mettre en forme le code n'est pas un bon argument contre l'écriture correcte du code – nearlymonolith

2

Votre premier exemple est parfaitement lisible pour moi - ne sent pas du tout.

4

Dans ce cas particulier, je vais revenir au début et il rend le code plus facile à lire

if (string.IsNullOrEmpty(str)) { return; } 

Je tiens à mettre une déclaration de retour explicite.

+1

Cela ne fonctionne que si la fonction ne fait rien d'autre que le bloc 'if ... else'. – palswim

+0

Cela dépend vraiment de la sémantique du problème. Très rarement un argument nul signifie "ne rien faire". Trop souvent, cela signifie que quelqu'un a fait une erreur, et en revenant silencieusement, vous ne faites qu'aggraver le problème. Si ce n'est pas le soutien de la vie ou l'armée, l'échec rapide est souvent une bonne idée. – user359996

+0

Je suis complètement d'accord avec vous et je fais toujours échouer rapidement. Je ne réponds qu'à cette question particulière où l'utilisation pour quelque raison que ce soit veut revenir. Cela arrive souvent dans le traitement par lots où, au lieu d'échouer, il suffit d'ignorer et éventuellement de consigner quelle entité a été ignorée. – softveda

2

Tout dépend du contexte. Si mettre une instruction if vide rend le code plus lisible, alors allez-y.

+0

Oui, mais documentez-le toujours lorsque vous faites cela. Ou, si vous êtes comme moi et essayez de faire du code qui n'a pas besoin de commentaires et que vous ne travaillez pas dans un langage qui force tout à être dans une classe, appelez une méthode nommée Nothing(). –

+0

Je suis habitué à travailler avec Python, qui inclut 'pass' (une instruction pour ne rien faire). –

2

Il est lisible, que ce soit bon ou mauvais dépend de ce que vous essayez d'atteindre - généralement embêté "va-pour-toujours" de type if instructions sont mauvaises. Ne pas oublier les méthodes de chaînes statiques cuites dans le cadre: string.IsNullOrEmpty() et string.IsNullOrWhiteSpace().

Votre ligne if (str == null) { /* Do nothing */ } est inhabituelle, mais elle a un point positif: elle fait savoir aux autres développeurs que vous ne faites délibérément rien dans ce cas, avec votre longue structure if/else si vos intentions pourraient devenir floues si vous changé à

if (str != null) 
{ 
    /* carry on with the rest of the tests */ 
} 
6

Normalement je mettre un return ou quelque chose comme ça dans la première if:

void Foo() 
{ 
    if (str == null) { return; } 
    if (str == "SomeSpecialValue") 
    { 
     // ... 
    } 
    else if (str.Length > 1) 
    { 
     // ... 
    } 
} 

Si vous ne pouvez pas faire cela, parce que la fonction fait quelque chose d'autre après la if/else, je dirais Il est temps de refactoriser, et diviser la partie if/else dans une fonction distincte, à partir de laquelle vous pouvez revenir tôt.

+0

Je n'aime pas votre style d'indentation, mais ce morceau de code est la meilleure façon, à mon humble avis, de résoudre le problème de l'OP. +1 – rmeador

+0

@rmeador: Intéressant; quel style d'indentation aimez-vous? – palswim

+0

ce n'est pas vraiment "mon" style d'indentation, j'ai juste essayé de coller avec les OP. :) – jalf

3

Oui C'est une odeur de code.

Une indication est que vous avez pensé à poser cette question.

Une autre indication est que le code semble incomplet - comme si quelque chose devait y appartenir. Il peut être lisible, mais il se sent off. Lors de la lecture de ce code, un étranger doit s'arrêter pendant une seconde et utiliser son intelligence pour déterminer si le code est valide/complet/correct/comme prévu/adjectif.

user359996 mis le doigt sur la tête:

Je dis cela est bizarre parce qu'il obscurcit votre intention et défie les attentes du lecteur.

+0

Je ne pense pas que "penser à poser la question" est nécessairement un mauvais indicateur. Presque aucun des codes que je vois, même des exemples classiques de «bon code», me semble bien. Presque chaque modèle de conception ressemble à une odeur de code pour moi, par exemple. Presque chaque exemple de code de procédure me fait «arrêter une seconde et utiliser des cerveaux» pour comprendre ce qui était prévu. – Ken

+1

@Ken En général "penser à demander" peut ne pas être un signe d'une odeur de code, mais dans cette situation Id dire que c'était. Si aucun code ne vous convient, vous lisez la mauvaise source ou, pour une raison quelconque, vous n'aimez pas l'aspect du code. (Beaucoup) Les modèles de conception ne sont pas des odeurs de code ... des expositions de faiblesse dans une langue peut-être. Pour l'exemple ci-dessus, il y a de meilleures choses à faire cesser et dépenser de la puissance cérébrale pour un simple code qui semble incomplet. Je suis désolé code de procédure vous cause des problèmes. –

+0

instanceofTom: Je suis désolé une paire d'accolades sans déclaration vous cause des problèmes. – Ken