Sur un projet récent, j'avais besoin de convertir d'octets en kilobytes kibibytes . Le code était assez simple:
var kBval = byteVal / 1024;
Après avoir écrit cela, j'ai fait fonctionner le reste de la fonction et je suis passé à autre chose.
Mais plus tard, j'ai commencé à me demander si je venais d'incorporer un nombre magique dans mon code. Une partie de moi dit que c'était bien parce que le nombre est une constante fixe et doit être facilement compris. Mais une autre partie de moi pense que cela aurait été super clair si elle était enveloppée dans une constante définie comme BYTES_PER_KBYTE
.
Alors, les nombres qui sont des constantes bien connues sont-ils vraiment magiques ou non?
Questions connexes:
Quand un nombre est-il un nombre magique? et chaque numéro du code est-il considéré comme un "nombre magique"? - sont similaires, mais sont des questions beaucoup plus larges que ce que je demande. Ma question porte sur des nombres constants bien connus, qui ne sont pas abordés dans ces questions.
Éliminer les nombres magiques: quand est-il temps de dire "Non"? est également liée, mais est axée sur la refactorisation, par opposition à la question de savoir si un nombre constant est un nombre magique.
la source
FOUR_HUNDRED_FOUR = 404
. J'ai travaillé sur un autre projet où ils étaient militants pour utiliser des chaînes constantes au lieu de littéraux, ils avaient donc des dizaines de lignes de code qui ressemblaient àDATABASE = "database"
1024
, parce que sinon votre équipe de développement passera tout son temps à se disputer pour savoir si c'est "kilo-octets" ou "kibibytes".#define
KIBI
que 1024,MEBI
1024 * 1024…ZERO=0, ONE=1, TWO=2
et lorsque les programmes sont portés dans d'autres langues (ou que les programmeurs ne changent pas de comportement lorsqu'ils changent de langue), vous le voyez aussi et vous devez prier pour que personne ne le change enONE=2
...Réponses:
Tous les nombres magiques ne sont pas identiques.
Je pense que dans ce cas, cette constante est OK. Le problème avec les nombres magiques, c’est quand ils sont magiques, c’est-à-dire qu’on ne sait pas quelle est leur origine, pourquoi la valeur est ce qu’elle est, ou si la valeur est correcte ou non.
Se cacher 1024 derrière BYTES_PER_KBYTE signifie également que vous ne voyez pas instantanément si c'est correct ou non.
Je m'attendrais à ce que quiconque sache immédiatement pourquoi la valeur est 1024. Par contre, si vous convertissiez des octets en mégaoctets, je définirais la constante BYTES_PER_MBYTE ou similaire, car la constante 1 048 576 n'est pas si évidente que sa valeur 1024 ^ 2, ou que c'est même correct.
Il en va de même pour les valeurs dictées par des exigences ou des normes, qui ne sont utilisées qu’à un seul endroit. Je trouve qu'il est plus facile de traiter le droit constant en place avec un commentaire à la source pertinente que de le définir ailleurs et de devoir poursuivre les deux parties, par exemple:
Je trouve mieux que
À
SOME_THRESHOLD_VALUE
mon avis, ce n’est qu’à partir du moment où le compromis devient utile pour définir une constante.la source
e^i*pi = -1
est beaucoup plus explicite (meilleur) que2.718^i*3.142 = -1
. Les variables sont importantes et elles ne concernent pas uniquement le code commun. Le code est écrit pour être lu en premier, puis en deuxième. En outre, les spécifications changent (beaucoup). Bien que le 1024 ne devrait probablement pas être dans la configuration, la version 3.5 sonne comme il se doit.1024*1024
plz!Je pose deux questions concernant les nombres magiques.
Le numéro a-t-il un nom?
Les noms sont utiles car nous pouvons lire le nom et comprendre l’utilité du numéro qui se trouve derrière. Les constantes de dénomination peuvent augmenter la lisibilité si le nom est plus facile à comprendre que le nombre qu'il remplace et si le nom de la constante est concis.
Clairement, des constantes telles que pi, e, et al. avoir des noms significatifs. Une valeur telle que 1024 pourrait être,
BYTES_PER_KB
mais je m'attendrais également à ce que tout développeur sache ce que 1024 signifie. Le public cible du code source est constitué de programmeurs professionnels qui devraient avoir l'expérience nécessaire pour connaître les différentes puissances des deux et la raison de leur utilisation.Est-il utilisé dans plusieurs endroits?
Alors que les noms sont une force des constantes, une autre est la réutilisabilité. Si une valeur est susceptible de changer, elle peut être modifiée à un endroit au lieu de devoir la rechercher à plusieurs endroits.
Ta question
Dans le cas de votre question, j'utiliserais le numéro tel quel.
Nom: il y a un nom pour ce numéro, mais ce n'est pas vraiment utile. Il ne représente pas une constante ou une valeur mathématique spécifiée dans un document d'exigences.
Emplacements: même s’ils sont utilisés dans plusieurs endroits, ils ne changeront jamais, annulant ainsi cet avantage.
la source
Cette citation
comme dit par Jörg W Mittag répond à cette question tout à fait bien.
Certains chiffres ne sont tout simplement pas magiques dans un contexte particulier. Dans l'exemple fourni dans la question, les unités de mesure étaient spécifiées par les noms de variables et l'opération en cours était parfaitement claire.
Ce
1024
n’est donc pas magique, car le contexte indique très clairement que c’est la valeur constante et appropriée à utiliser pour les conversions.De même, un exemple de:
est tout aussi clair et pas magique car il est bien connu qu'il y a 24 heures dans la journée.
la source
24
quand même! Comme mentionné par Izkata, les secondes intercalaires font mal. Peut-être auriez-vous plus de chance en utilisant la constante24
sur Mars que sur Terre!D'autres affiches ont mentionné que la conversion en cours est «évidente», mais je ne suis pas d'accord. La question initiale, à ce moment-ci, comprend:
Donc, je sais déjà que l'auteur est ou était confus. La page Wikipedia ajoute à la confusion:
Ainsi, «kilo-octet» peut être utilisé pour désigner à la fois un facteur de 1000 et 1024, la seule différence en abrégé étant la capitalisation du «k». De plus, 1024 peut signifier kilobyte (JEDEC) ou kibibyte (IEC). Pourquoi ne pas briser toute cette confusion avec une constante avec un nom significatif? En passant, ce fil de discussion a fréquemment utilisé "BYTES_PER_KBYTE", et ce n’est pas moins ambigu. KBYTE: est-ce KIBIBYTE ou KILOBYTE? Je préférerais ignorer JEDEC et avoir
BYTES_PER_KILOBYTE = 1000
etBYTES_PER_KIBIBYTE = 1024
. Plus de confusion.La raison pour laquelle des gens comme moi, et beaucoup d’autres, ont des opinions «militantes» (pour citer un commentateur ici) sur la désignation de nombres magiques est tout simplement de documenter ce que vous avez l’ intention de faire et de lever l’ambiguïté. Et vous avez en fait choisi une unité qui a conduit à beaucoup de confusion.
Si je vois:
Ensuite, ce que l'auteur avait l'intention de faire est immédiatement évident et il n'y a aucune ambiguïté. Je peux vérifier la constante en quelques secondes (même si c'est dans un autre fichier), alors même si ce n'est pas «instantané», c'est assez proche d'instantané.
En fin de compte, cela peut paraître évident lorsque vous l'écrivez, mais ce le sera moins lorsque vous y reviendrez plus tard, et encore moins lorsque quelqu'un l'éditera. Il faut 10 secondes pour faire une constante; cela pourrait prendre une demi-heure ou plus pour résoudre un problème avec des unités (le code ne vous sautera pas dessus et vous dira que les unités sont fausses, vous devrez faire le calcul vous-même pour le résoudre, et vous aurez probablement chercher 10 avenues différentes avant de vérifier les unités).
la source
KB
) différemment ne vont pas aider.Définir un nom comme faisant référence à une valeur numérique suggère que chaque fois qu'une valeur différente est requise dans un emplacement utilisant ce nom, elle le sera probablement dans tous les cas. Cela tend également à suggérer que la modification de la valeur numérique attribuée au nom est un moyen légitime de modifier la valeur. Une telle implication peut être utile quand c'est vrai et dangereuse quand c'est faux.
Le fait que deux endroits différents utilisent une valeur littérale particulière (par exemple, 1024) suggérera faiblement que les changements qui inciteraient un programmeur à en changer une sont quelque peu susceptibles d'inspirer le programmeur à vouloir en changer d'autres, mais cette implication est bien plus faible que ce qui serait appliqué si le programmeur a attribué un nom à une telle constante.
Un danger majeur avec quelque chose comme
#define BYTES_PER_KBYTE 1024
ceci est que cela pourrait suggérer à quelqu'un qui se trouveprintf("File size is %1.1fkB",size*(1.0/BYTES_PER_KBYTE));
qu'un moyen sûr de faire en sorte que le code utilise des milliers d'octets serait de changer la#define
déclaration. Toutefois, une telle modification pourrait être désastreuse si, par exemple, un autre code non lié recevait la taille d’un objet en kilo-octets et utilisait cette constante pour allouer un tampon.Il pourrait être raisonnable d’utiliser
#define BYTES_PER_KBYTE_FOR_USAGE_REPORT 1024
et d’#define BYTES_PER_KBYTE_REPORTED_BY_FNOBULATOR 1024
attribuer un nom différent à chaque utilisation de la constante 1024, mais il en résulterait que de nombreux identifiants seraient définis et utilisés exactement une fois. En outre, dans de nombreux cas, il est plus facile de comprendre ce que signifie une valeur si on voit le code où il est utilisé, et il est aussi plus simple de savoir où code signifie si on voit les valeurs des constantes qui y sont utilisées. Si un littéral numérique n'est utilisé qu'une seule fois dans un but particulier, l'écrire à l'endroit où il est utilisé produira souvent un code plus compréhensible que de lui attribuer une étiquette à un endroit et d'utiliser sa valeur ailleurs.la source
Je préférerais utiliser uniquement le nombre, mais je pense qu’un problème important n’a pas été soulevé: le même nombre peut signifier différentes choses dans différents contextes, ce qui peut compliquer le refactoring.
1024 est également le nombre de KiB par MiB. Supposons que nous utilisions 1024 pour représenter également ce calcul quelque part ou à plusieurs endroits et que nous devions maintenant le modifier pour calculer le Bio à la place. Changer la constante est plus facile qu'une recherche globale / remplacement où vous pouvez accidentellement changer le mauvais à certains endroits, ou le manquer à d'autres.
Ou ce pourrait même être un masque introduit par un programmeur paresseux qui doit être mis à jour un jour.
C'est un exemple un peu artificiel, mais dans certaines bases de code, cela peut poser des problèmes lors du refactoring ou de la mise à jour pour de nouvelles exigences. Pour ce cas particulier cependant, je ne considérerais pas le nombre simple comme une forme vraiment mauvaise, surtout si vous pouvez inclure le calcul dans une méthode de réutilisation, je le ferais probablement moi-même, mais je considérerais la constante plus "correcte".
Toutefois, si vous utilisez des constantes nommées, comme le dit supercat, il est important de déterminer si le contexte est également important et si vous avez besoin de plusieurs noms.
la source