Question

Je suis novice en programmation et je me demande s’il existe un moyen correct de commander la logique de votre structure de contrôle.

Il semble plus naturel de rechercher le cas le plus probable en premier lieu, mais j’ai le sentiment que certaines structures de contrôle ne fonctionneront que si elles vérifient tout ce qui est faux pour arriver à quelque chose de vrai (déduction logique?)

Il serait difficile de s’adapter à cette vision "négative", je préfère une vision plus positive, en supposant que tout soit vrai:)

Était-ce utile?

La solution

Dans la plupart des situations, la lisibilité est plus importante que la vitesse d'exécution. J'essaye donc optimiser pour faciliter la compréhension, en utilisant l’approche suivante:

Tous les "assertion" les contrôles sont faits à l'avance. cela garantit que tous les cas erronés sont traités au tout début. Ceci est particulièrement important pour les vérifications null-pointeur, par exemple

.
    if(arg == null){ 
      throw new IllegalArgumentException();  // harsh (correct)
    }
    // or 
    if(arg == null){
        arg = "";  // forgiving (lazy)
    }

Ensuite, j'essaie de vérifier 1 condition seulement dans chaque instruction if. au lieu de

    if(condition1 && condition2) {
        ...
    } else {
        ...
    }

je préfère généralement

    if(condition1) {
        if(condition2) {
            ...
        } else {
            ...
        }
    } else {
        ...
    }

Cette approche est plus facile pour définir des points d'arrêt et rend la logique plus évidente.

j'évite les négations; au lieu de

    if(! condition) {
        ...a...
    } else {
        ...b...
    }

les choses sont mieux arrangées pour

    if(condition) {
        ...b...
    } else {
        ...a...
    }

Enfin, toutes les méthodes qui renvoient un résultat booléen doivent avoir un résultat "positif". nom qui indique la signification du résultat:

    boolean checkSomething(Something x){ ... }     // bad -- whats the result?
    boolean isSomethingInvalid(Something x){ ... } // better, but ...
    boolean isSomethingValid(Something x){ ... }   // best, no "mental negation"

Autres conseils

Il existe une excellente discussion sur ce sujet dans le code complet de McConnell. . C'est un livre que je recommande fortement. Quoi qu’il en soit, la discussion pertinente se trouve aux pages 706 à 708 de la première édition ou à la page. 749-750 de deuxième édition (merci plinth). De ce livre:

  

Organisez des tests pour que celui qui est   le plus rapide et le plus susceptible d'être vrai est   joué en premier. Il devrait être facile de   passer à travers le cas normal, et si   il y a des inefficacités, ils devraient   être en traitement des exceptions.

Il y a des éléments à prendre en compte en plus de la valeur de l'instruction de condition. Par exemple, si la taille des blocs de code est très différente, vous pouvez choisir de placer le petit bloc en premier afin qu'il soit plus facile à voir. (Si le bloc le plus grand est vraiment volumineux, il peut être nécessaire de le remanier ou de le retirer dans une méthode distincte.)

if( condition is true ) {
    do something small;
} else { 
    do something;
    and something else; 
    . . .
    and the 20th something;
}

Dans la condition, oui, certaines langues cesseront d’évaluer une expression dès qu’une partie de celle-ci est fausse. Il est important de se rappeler si vous incluez une sorte de logique définie par votre code dans votre code: si votre langue évalue l'expression entière, procédez comme suit:

if( variable is defined ) {
    if( variable == value ) {
        ...
    }
}

plutôt que cela:

if( (variable is defined) && (variable == value) ) {
     ...
}

Je ne pense pas qu'il existe un "correct" façon de concevoir vos conditions. Si vous travaillez pour une entreprise qui a des normes de codage, vous devriez vérifier si cela est inclus dans les normes. (Au dernier endroit où j'ai travaillé, un nombre raisonnable de normes avait été défini, sans préciser comment écrire une logique conditionnelle.)

En règle générale, je vérifie d’abord les éléments inattendus, ce qui m’oblige à gérer un déroulement exceptionnel du programme.

De cette manière, je peux lancer des exceptions / abandonner des opérations avant de commencer à "configurer". pour le déroulement normal du programme.

Je souhaite structurer mes conditions de manière à minimiser la quantité d'informations que le lecteur doit assimiler. Parfois, il est plus facile de tester le négatif pour prouver le positif:

Un exemple - le test pour voir si une période de 2 dates intersecte avec une autre période de 2 dates est plus facile à écrire en tant que test sans intersection de 2 périodes

S'il s'agit d'une simple question de type oui ou d'erreur, je structure généralement les choses de sorte que la branche de gestion des erreurs constitue la clause else. Si la question est oui ou non (c’est-à-dire qu’aucune des deux branches n’est une erreur), il s’agit simplement de faire appel à son jugement pour ce qui est plus naturel. S'il y a beaucoup de tests qui doivent être faits avant que le coeur du code puisse s'exécuter, j'essaye généralement de structurer les choses de manière à ce que les tests négatifs arrivent en premier et, d'une manière ou d'une autre, ignorent le code qui suit (retour de la fonction, pause ou continuation de une boucle).

Ou / Ou. J'utilise généralement l'approche "négative" cependant.

if (! quelque chose) {

}

Ceci est un peu en dehors du champ de la question, mais vous voulez généralement que vos méthodes échouent rapidement. Pour cette raison, j'ai tendance à faire toute la validation de mes arguments en haut de la méthode, même si je ne les utiliserai que plus tard dans le code. Cela nuit à la lisibilité, mais seulement dans le cas où la méthode est vraiment longue (il faut faire défiler l'écran pour la voir). Bien sûr, il s’agit d’une odeur de code en soi qui a tendance à être remaniée.

D'un autre côté, si la vérification n'est pas simple et que je la transmettrai à une autre méthode qui la vérifiera de toute façon, je ne répéterai pas le code pour archiver la méthode actuelle. Comme dans la plupart des cas, il existe un équilibre.

(Contexte: Java)

READABILITY1: La condition qui résout un bloc de code plus petit commence en premier

if (condition) {
  smallBlock();
} else {
  bigBlockStart();
  ........
  bigBlockEnd();
}

READABILITY2: l'assertion positive commence en premier, car il est plus facile de ne pas remarquer un signe de négation

MAKE SENSE: Assert toutes les conditions préalables pour une méthode à l'aide de Assert.blabla () et n'utilise des conditions que pour ce que fait la méthode.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top