Donc, chaque nombre dans le code que nous envoyons à une méthode comme argument est considéré comme un nombre magique? Pour moi, ça ne devrait pas. Je pense que si un certain nombre est disons que c'est pour la longueur minimale du nom d'utilisateur et que nous commençons à utiliser "6" dans le code ... alors oui nous avons un problème de maintenance et ici "6" est un nombre magique .... mais si nous appelons une méthode que l'un de ses arguments accepte par exemple un entier comme le ième membre d'une collection et que nous passons ensuite "0" à cet appel de méthode, dans ce cas je ne vois pas "0" comme une magie nombre. Qu'est-ce que tu penses?
21
Réponses:
Si la signification du nombre est très claire dans le contexte, je ne pense pas que ce soit un problème de "nombre magique".
Exemple: disons que vous essayez d'obtenir la sous-chaîne d'une chaîne, du début à un jeton et que le code ressemble à ceci (langage et bibliothèque imaginaires):
Dans ce contexte, la signification du nombre 0 est suffisamment claire. Je suppose que vous pouvez le définir
START_OF_SUBSTRING
et le mettre à 0, mais dans ce cas, je pense que ce serait exagéré (bien que ce soit la bonne approche si vous saviez que le début de votre sous-chaîne pourrait ne pas être 0, mais cela dépend des spécificités de ta situation).Un autre exemple pourrait être si vous essayez de déterminer si un nombre est pair ou impair. L'écriture:
n'est pas aussi étrange que:
Test des nombres négatifs comme
me semble aussi bizarre, je préfère de loin
la source
360
pour marquer une rotation complète en sachant que la plupart des gens sauront ce que cela signifie (bien que cela est un cas où cela ne ferait pas de mal de fournir une constante)0
dans le contexte de l'exemple ma sous-chaîne. Dans ce cas, cela pourrait être le moins de dégâts possible. Cela fait longtemps que je n'ai fait aucun codage qui a fait des calculs géométriques, mais généralement, les valeurs 15, 30, 45, 60, 90, 180, 360 étaient des constantes qui ont été acceptées. Je n'ai jamais vu personne définirFIFTEEN_DEGREES
, ...Il est évident que zéro signifie absence. Je trouve 0 plus facile à comprendre qu'une variable nommée "absenceValue".
Il est évident que 0 est la position de départ. Je serais confus par une variable nommée "firstPosition". Une telle variable me ferait me demander si la position de départ pouvait changer.
la source
Je suggérerais trois facteurs clés pour décider si quelque chose devrait être une déclaration constante:
Quelque chose comme pi devrait probablement être écrit comme une constante nommée, plutôt que comme un littéral numérique, car un littéral numérique est susceptible d'être inutilement verbeux, inutilement imprécis, ou les deux. Quelque chose comme le nombre d'emplacements dans un cache devrait probablement être une constante nommée (bien que voir la note ci-dessous) pour permettre la possibilité d'étendre le cache sans avoir à modifier tout le code qui l'utilise. Des choses comme les nombres «4», «28» et «29» dans l'instruction
if ((year % 4)==0) FebruaryDays = 29; else FebruaryDays = 28;
ne devraient probablement pas être nommées constantes, car l'expression est presque certainement plus lisible queif ((year % YearsBetweenLeapYears)==0) FebruaryDays = FebruaryDaysInLeapYear; else FebruaryDays = FebruaryDaysInNonLeapYear;
. Notez que les responsables des normes ont indiqué que la durée du 21 février de cette année ne correspondra pas à la formule ci-dessus, obstacle au traitement correct de ces dates (c'est-à-dire que le code ne sera pas déclenché par un débordement d'entier ou d'autres problèmes de ce type)Une mise en garde importante avec la règle n ° 2 est que, dans certains cas, le code peut s'appuyer sur des nombres codés en dur d'une manière qui ne peut pas être facilement représentée par une constante nommée. Par exemple, une méthode qui calcule un produit croisé de deux vecteurs passés comme paramètres discrets n'aura de sens que lorsqu'elle est utilisée sur des vecteurs tridimensionnels. Le nombre requis de dimensions n'est pas une valeur qui pourrait être modifiée de manière significative sans réécrire complètement la routine. Même si l'on prévoyait un besoin éventuel de calculer le produit croisé de trois vecteurs à quatre dimensions, l'utilisation d'une constante nommée pour la valeur "3" ne contribuerait guère à faciliter la satisfaction de ce besoin.
la source
Comme tous les principes, c'est une question de degré. De manière générale, les littéraux numériques dans le code source sont d'autant plus suspects qu'ils sont grands. Une longueur maximale comme 10 ou une adresse mémoire comme 0x587FB0 est évidemment une mauvaise pratique - il est presque certain que tôt ou tard vous devrez répéter ces valeurs plus d'une fois, créant un risque d'incompatibilité et d'erreurs subtiles introduites dans des endroits qui n'étaient pas modifié.
0 est à l'autre extrémité de l'échelle; c'est encore suspect mais pas autant. Utilisez-vous 0 comme valeur sentinelle? Ensuite, vous devriez probablement utiliser une constante symbolique à la place, simplement parce que la constante peut expliquer ce que cela signifie. S'agit-il d'un accord culturel extrêmement enraciné tel que «0 signifie une réussite»? C'est probablement OK. Cela signifie-t-il "le premier article d'une collection"? Cela peut être inoffensif, mais s'il existe une autre méthode telle que
first()
je préférerais probablement cela.la source
Chaque nombre sans nom qui n'est pas immédiatement évident du contexte est un nombre magique. C'est un peu idiot de définir des nombres qui ont une signification immédiatement évidente du contexte.
Dans django (framework web python), je peux définir un champ de base de données avec un nombre brut comme:
qui est plus clair (et le pratique recommandée ) que de dire
car je ne vais probablement jamais avoir besoin de changer la longueur (et je peux toujours la comparer à celle
max_length
du champ). Si j'ai besoin de modifier la longueur du champ après avoir déployé l'application initialement, je dois le changer à exactement un emplacement par champ dans mon code django, puis écrire en outre une migration pour modifier le schéma de la base de données. Si j'ai besoin de référencermax_length
un champ défini d'un type d'objet, je peux le faire directement - si ces champs définissaient unePerson
classe, je peux l'utiliserPerson._meta.get_field('firstname').max_length
pour obtenir lemax_length
utilisé (qui est défini en un seul endroit). Le fait que le même 40 ait été utilisé pour plusieurs champs n'est pas pertinent car je peux vouloir les changer indépendamment. La longueur du prénom ne doit jamais dépendre de la longueur du prénom ou du nom de famille; ce sont des valeurs distinctes et peuvent changer indépendamment.Souvent, les indices matriciels peuvent utiliser des nombres sans nom; comme si j'avais un fichier CSV de données que je voulais mettre dans un dictionnaire python, avec le premier élément de la ligne comme dictionnaire
key
j'écrirais:Bien sûr, je pourrais nommer
index_column = 0
et faire quelque chose comme:ou pire définir
after_index_col = index_col + 1
pour se débarrasser deindex_col+1
, mais cela ne rend pas le code plus clair à mon avis. De plus, si je donneindex_col
un nom, je ferais mieux de faire fonctionner le code même si la colonne n'est pas 0 (d'où larow[:index_col] +
partie).la source
max_lngth=40
vsmax_length=MAX_LENGTH_NAME
est un exemple classique d'un nombre magique qui crie pour être un symbole. Le jour viendra où vous voudrez prendre en charge 45 noms de caractères, et maintenant chaque utilisation de "40" est suspecte et doit être soigneusement examinée.40
à1
. Vous devez penser au contexte.