Question Qu'est-ce qu'un chiffre magique, et pourquoi est-ce mauvais?


Qu'est-ce qu'un chiffre magique?

Pourquoi devrait-il être évité?

Y a-t-il des cas où c'est approprié?


434
2017-09-06 22:24


origine


Réponses:


Un nombre magique est une utilisation directe d'un nombre dans le code.

Par exemple, si vous avez (en Java):

public class Foo {
    public void setPassword(String password) {
         // don't do this
         if (password.length() > 7) {
              throw new InvalidArgumentException("password");
         }
    }
}

Cela devrait être refait à:

public class Foo {
    public static final int MAX_PASSWORD_SIZE = 7;

    public void setPassword(String password) {
         if (password.length() > MAX_PASSWORD_SIZE) {
              throw new InvalidArgumentException("password");
         }
    }
}

Il améliore la lisibilité du code et il est plus facile à maintenir. Imaginez le cas où je définis la taille du champ mot de passe dans l'interface graphique. Si j'utilise un nombre magique, chaque fois que la taille maximale change, je dois changer dans deux emplacements de code. Si j'en oublie un, cela conduira à des incohérences.

Le JDK est plein d’exemples comme dans Integer, Character et Math Des classes.

PS: Les outils d'analyse statique tels que FindBugs et PMD détectent l'utilisation de nombres magiques dans votre code et suggèrent le refactoring.


490
2017-09-06 22:46



Un nombre magique est une valeur codée en dur qui peut changer à un stade ultérieur, mais cela peut être difficile à mettre à jour.

Par exemple, supposons que vous ayez une page affichant les 50 dernières commandes dans une page d'aperçu "Vos commandes". 50 est le nombre magique ici, car il n'est pas défini par la norme ou la convention, c'est un nombre que vous avez composé pour les raisons décrites dans la spécification.

Maintenant, ce que vous faites est que vous avez le 50 dans des endroits différents - votre script SQL (SELECT TOP 50 * FROM orders), votre site Web (Vos 50 dernières commandes), votre identifiant de commande (for (i = 0; i < 50; i++)) et éventuellement beaucoup d'autres endroits.

Maintenant, que se passe-t-il quand quelqu'un décide de changer de 50 à 25 ans? ou 75? ou 153? Vous devez maintenant remplacer le 50 dans tous les endroits, et vous risquez fort de le manquer. Trouver / Remplacer peut ne pas fonctionner, car 50 peut être utilisé pour d'autres choses, et remplacer 50 à 25 peut avoir d'autres effets secondaires (à savoir Session.Timeout = 50 appel, qui est également défini sur 25 et les utilisateurs commencent à signaler des dépassements de délai trop fréquents).

En outre, le code peut être difficile à comprendre, c'est-à-dire "if a < 50 then bla"- si vous rencontrez cela au milieu d'une fonction compliquée, d'autres développeurs qui ne sont pas familiers avec le code peuvent se demander" WTF est 50 ??? "

C'est pourquoi il est préférable d'avoir des chiffres aussi ambigus et arbitraires à exactement 1 endroit - "const int NumOrdersToDisplay = 50", parce que cela rend le code plus lisible ("if a < NumOrdersToDisplay", cela signifie également que vous avez seulement besoin de le changer dans un endroit bien défini.

Les endroits où les numéros de magie sont appropriés sont tout ce qui est défini par une norme, à savoir SmtpClient.DefaultPort = 25 ou TCPPacketSize = whatever (Je ne sais pas si c'est standardisé) De même, tout ce qui n'est défini que dans 1 fonction peut être acceptable, mais cela dépend du contexte.


134
2017-09-06 22:31



Avez-vous jeté un coup d'oeil à l'entrée Wikipedia pour nombre magique?

Cela revient à un détail sur toutes les façons dont la référence au nombre magique est faite. Voici une citation sur le nombre magique en tant que mauvaise pratique de programmation

Le terme nombre magique fait également référence à la mauvaise pratique de programmation consistant à utiliser des nombres directement dans le code source sans explication. Dans la plupart des cas, cela rend les programmes plus difficiles à lire, à comprendre et à maintenir. Bien que la plupart des guides fassent une exception pour les nombres zéro et un, il est recommandé de définir tous les autres nombres du code comme des constantes nommées.


29
2017-09-06 22:29



Un nombre magique est une séquence de caractères au début d'un format de fichier, ou un échange de protocole. Ce numéro sert de test de santé mentale.

Exemple: Ouvrez n'importe quel fichier GIF, vous verrez au tout début: GIF89. "GIF89" étant le nombre magique.

D'autres programmes peuvent lire les premiers caractères d'un fichier et identifier correctement les GIF.

Le danger est que les données binaires aléatoires puissent contenir ces mêmes caractères. Mais c'est très improbable.

En ce qui concerne l'échange de protocoles, vous pouvez l'utiliser pour identifier rapidement que le message en cours qui vous est transmis est corrompu ou non valide.

Les nombres magiques sont toujours utiles.


17
2017-09-06 22:27



Nombre magique vs. Constante symbolique: Quand remplacer?

Magic: Sémantique inconnue

Constante symbolique -> Fournit à la fois une sémantique correcte et un contexte correct pour l'utilisation

Sémantique: Le sens ou le but d'une chose.

"Créez une constante, nommez-la après le sens, et remplacez le nombre avec." - Martin Fowler

Premièrement, les nombres magiques ne sont pas seulement des nombres. Toute valeur de base peut être "magique". Les valeurs de base sont des entités manifestes telles que des entiers, des réels, des doubles, des flottants, des dates, des chaînes, des booléens, des caractères, etc. Le problème n'est pas le type de données, mais l'aspect "magique" de la valeur telle qu'elle apparaît dans notre texte de code.

Qu'entendons-nous par "magie"? Pour être précis: Par "magie", nous avons l'intention de pointer vers la sémantique (signification ou but) de la valeur dans le contexte de notre code; qu'il est inconnu, inconnaissable, incertain ou déroutant. C'est la notion de "magie". Une valeur fondamentale n'est pas magique lorsque sa signification sémantique ou son but-d'être-est rapidement et facilement connu, clair et compris (sans confusion) du contexte ambiant sans mots auxiliaires spéciaux (par exemple, une constante symbolique).

Par conséquent, nous identifions les nombres magiques en mesurant la capacité d'un lecteur de code à connaître, être clair, et comprendre la signification et le but d'une valeur de base de son contexte environnant. Moins le lecteur est connu, moins clair et plus confus, plus la valeur de base est «magique».

Définitions utiles

  • confondre: causer (quelqu'un) de devenir désorienté ou perplexe.
  • égaré: cause (quelqu'un) de devenir perplexe et confus.
  • perplexe: complètement déconcerté; très perplexe.
  • dérouté: totalement déroutant ou perplexe.
  • perplexe: incapable de comprendre; perplexe.
  • comprendre: percevoir le sens voulu de (mots, une langue ou un locuteur).
  • ce qui signifie: ce que l'on entend par un mot, un texte, un concept ou une action.
  • signifiait: avoir l'intention de transmettre, d'indiquer ou de se référer à (une chose ou une notion particulière); signifier.
  • signifier: être une indication de.
  • indication: un signe ou une information indiquant quelque chose.
  • indiquer: signaler; montrer.
  • signe: un objet, une qualité ou un événement dont la présence ou l'occurrence indique la présence ou l'occurrence probable d'autre chose.

Notions de base

Nous avons deux scénarios pour nos valeurs de base magiques. Seul le second est primordial pour les programmeurs et le code:

  1. Une valeur de base isolée (par exemple un nombre) dont sa signification est inconnue, inconnaissable, imprécise ou confuse.
  2. Une valeur de base (par exemple un nombre) dans le contexte, mais sa signification reste inconnue, inconnaissable, imprécise ou confuse.

Une dépendance primordiale de la "magie" est la façon dont la valeur de base isolée (par exemple le nombre) n'a pas de sémantique communément connue (comme Pi), mais une sémantique localement connue (par exemple votre programme), qui n'est pas dans un bon ou un mauvais contexte.

La sémantique de la plupart des langages de programmation ne nous permettra pas d'utiliser des valeurs de base isolées, sauf (peut-être) en tant que données (c'est-à-dire des tables de données). Lorsque nous rencontrons des "nombres magiques", nous le faisons généralement dans un contexte. Par conséquent, la réponse à

"Est-ce que je remplace ce nombre magique par une constante symbolique?"

est:

"Avec quelle rapidité pouvez-vous évaluer et comprendre la signification sémantique du   nombre (son but d'être là) dans son contexte? "

Sorte de magie, mais pas tout à fait

Avec cette pensée à l'esprit, nous pouvons rapidement voir comment un nombre comme Pi (3.14159) n'est pas un "nombre magique" lorsqu'il est placé dans un contexte approprié (par exemple, 2 x 3,14159 x rayon ou 2 * Pi * r). Ici, le nombre 3.14159 est reconnu mentalement Pi sans l'identifiant de la constante symbolique.

Cependant, nous remplaçons généralement 3.14159 par un identificateur de constante symbolique comme Pi en raison de la longueur et de la complexité du nombre. Les aspects de la longueur et de la complexité de Pi (associés à un besoin de précision) signifient généralement que l'identifiant symbolique ou la constante est moins sujet aux erreurs. La reconnaissance de "Pi" comme un nom est simplement un bonus pratique, mais ce n'est pas la raison principale pour laquelle la constante est maintenue.

Pendant ce temps, au ranch

Mettant de côté les constantes communes comme Pi, concentrons-nous principalement sur les nombres ayant une signification particulière, mais que ces significations sont limitées à l’univers de notre système logiciel. Un tel nombre pourrait être "2" (en tant que valeur entière de base).

Si j'utilise le numéro 2 seul, ma première question pourrait être: Que signifie "2"? La signification de "2" en elle-même est inconnue et inconnaissable sans contexte, laissant son utilisation peu claire et confuse. Même si le simple fait d'avoir "2" dans notre logiciel ne se produira pas à cause de la sémantique du langage, nous voulons voir que "2" en lui-même ne comporte aucune sémantique particulière ou objectif évident étant seul.

Mettons notre seul "2" dans un contexte de: padding := 2, où le contexte est un "conteneur GUI". Dans ce contexte, la signification de 2 (en tant que pixels ou autre unité graphique) nous donne une idée rapide de sa sémantique (signification et but). Nous pourrions nous arrêter ici et dire que 2 est acceptable dans ce contexte et que nous n'avons rien d'autre à savoir. Cependant, peut-être que dans notre univers logiciel, ce n’est pas tout. Il y a plus, mais "padding = 2" en tant que contexte ne peut pas le révéler.

Supposons en outre que 2 comme pixel remplissage dans notre programme est de la variété "default_padding" dans notre système. Par conséquent, écrire l'instruction padding = 2 n'est pas assez bon. La notion de "défaut" n'est pas révélée. Seulement quand j'écris: padding = default_paddingen tant que contexte et ensuite ailleurs: default_padding = 2 est-ce que je réalise pleinement une signification meilleure et plus complète (sémantique et but) de 2 dans notre système?

L'exemple ci-dessus est assez bon parce que "2" en soi pourrait être n'importe quoi. Seulement quand on limite la portée et le domaine de compréhension à "mon programme" où 2 est le default_padding dans les parties GUI UX de "mon programme", avons-nous finalement compris "2" dans son contexte propre? Ici "2" est un nombre "magique", qui est factorisé à une constante symbolique default_padding dans le contexte de l'UI GUI de "mon programme" afin de l'utiliser comme default_padding rapidement compris dans le plus grand contexte du code englobant.

Ainsi, toute valeur de base, dont la signification (sémantique et but) ne peut être suffisamment et rapidement comprise, est un bon candidat pour une constante symbolique à la place de la valeur de base (par exemple le nombre magique).

Aller plus loin

Les nombres sur une échelle peuvent également avoir une sémantique. Par exemple, prétendez que nous faisons un jeu D & D, où nous avons la notion de monstre. Notre objet monstre a une fonctionnalité appelée life_force, qui est un nombre entier. Les nombres ont des significations qui ne sont pas identifiables ou claires sans mots pour donner un sens. Ainsi, nous commençons par dire arbitrairement:

  • full_life_force: INTEGER = 10 - Très vivant (et non blessé)
  • minimum_life_force: INTEGER = 1 - À peine vivant (très blessé)
  • dead: INTEGER = 0 - Mort
  • Undead: INTEGER = -1 - Min Undead (presque mort)
  • zombie: INTEGER = -10 - Max mort-vivant (très mort-vivant)

À partir des constantes symboliques ci-dessus, nous commençons à avoir une image mentale de la vivacité, de la mort et de la «malchance» (et des ramifications ou conséquences possibles) pour nos monstres dans notre jeu D & D. Sans ces mots (constantes symboliques), il ne reste que les nombres allant de -10 .. 10. Seule la plage sans les mots nous laisse dans un endroit de grande confusion et potentiellement avec des erreurs dans notre jeu si différentes parties du jeu ont des dépendances sur ce que cette gamme de nombres signifie pour diverses opérations comme attack_elves ou seek_magic_healing_potion.

Par conséquent, lors de la recherche et du remplacement de «nombres magiques», nous souhaitons poser des questions très précises sur les nombres dans le contexte de notre logiciel et même comment les nombres interagissent sémantiquement les uns avec les autres.

Conclusion

Passons en revue les questions que nous devrions poser:

Vous pourriez avoir un nombre magique si ...

  1. La valeur de base peut-elle avoir une signification ou un but particulier dans votre univers de logiciels?
  2. La signification ou le but particulier peuvent-ils être inconnus, inconnaissables, imprécis ou déroutants, même dans leur contexte propre?
  3. Une valeur de base appropriée peut-elle être utilisée de manière inappropriée avec de mauvaises conséquences dans le mauvais contexte?
  4. Une valeur de base incorrecte peut-elle être correctement utilisée avec de mauvaises conséquences dans le bon contexte?
  5. La valeur de base a-t-elle un rapport sémantique ou objectif avec d'autres valeurs de base dans des contextes spécifiques?
  6. Une valeur de base peut-elle exister dans plus d'un endroit de notre code avec une sémantique différente dans chaque code, ce qui crée une confusion chez notre lecteur?

Examinez les valeurs de base constantes du manifeste autonome dans votre texte de code. Posez chaque question lentement et pensivement sur chaque exemple d'une telle valeur. Considérez la force de votre réponse. Plusieurs fois, la réponse n'est pas en noir et blanc, mais a des nuances de sens et de but incompris, de rapidité d'apprentissage et de rapidité de compréhension. Il est également nécessaire de voir comment il se connecte à la machine logicielle qui l'entoure.

En fin de compte, la réponse au remplacement est de répondre à la mesure (dans votre esprit) de la force ou de la faiblesse du lecteur à faire le lien (par exemple, «l'obtenir»). Plus vite ils comprennent le sens et le but, moins vous avez de «magie».

CONCLUSION: Remplacer les valeurs de base par des constantes symboliques uniquement lorsque la magie est suffisamment importante pour provoquer des bogues difficiles à détecter dus à des confusions.


16
2017-10-25 02:10



En programmation, un "nombre magique" est une valeur qui devrait recevoir un nom symbolique, mais qui a été glissé dans le code sous forme littérale, généralement à plusieurs endroits.

C'est mauvais pour la même raison que SPOT (Single Point of Truth) est bon: si vous vouliez changer cette constante plus tard, vous devrez parcourir votre code pour trouver chaque instance. C'est aussi mauvais parce que cela pourrait ne pas être clair pour les autres programmeurs ce que ce nombre représente, d'où la "magie".

Les gens prennent parfois davantage d'élimination des nombres magiques en déplaçant ces constantes dans des fichiers séparés pour agir en tant que configuration. Ceci est parfois utile, mais peut aussi créer plus de complexité que ce qu’il vaut.


10
2017-09-06 22:36



Un problème qui n'a pas été mentionné avec l'utilisation de nombres magiques ...

Si vous en avez beaucoup, les chances sont relativement bonnes que vous ayez deux fins que vous utilisez des nombres magiques pour, où le valeurs arriver à être le même.

Et puis, bien sûr, vous devez changer la valeur ... pour un seul but.


10
2017-12-13 00:12