En un proyecto reciente, necesitaba convertir de bytes a kilobytes de kibibyte . El código fue lo suficientemente sencillo:
var kBval = byteVal / 1024;
Después de escribir eso, conseguí que el resto de la función funcionara y seguí adelante.
Pero más tarde, comencé a preguntarme si acababa de incrustar un número mágico en mi código. Una parte de mí dice que estaba bien porque el número es una constante fija y debe entenderse fácilmente. Pero otra parte de mí piensa que habría sido súper claro si estuviera envuelto en una constante definida como BYTES_PER_KBYTE
.
Entonces, ¿los números que son constantes bien conocidos son realmente mágicos o no?
Preguntas relacionadas:
¿Cuándo es un número un número mágico? y ¿Cada número en el código se considera un "número mágico"? - son similares, pero son preguntas mucho más amplias de lo que estoy preguntando. Mi pregunta se centra en números constantes bien conocidos que no se abordan en esas preguntas.
Eliminando números mágicos: ¿Cuándo es el momento de decir "No"? también está relacionado, pero se centra en la refactorización en lugar de si un número constante es un número mágico o no.
fuente
FOUR_HUNDRED_FOUR = 404
. I trabajado en otro proyecto donde estaban militantes sobre el uso de cadenas constantes en lugar de literales, por lo que tenían decenas de líneas de código que parecían,DATABASE = "database"
1024
, porque de lo contrario su equipo de desarrollo pasará todo su tiempo discutiendo sobre si es "kilobytes" o "kibibytes".#define
KIBI
como 1024,MEBI
como 1024 * 1024 ...ZERO=0, ONE=1, TWO=2
y cuando los programas son portados a otras lenguas (o los programadores no cambiar el comportamiento cuando se cambia su lenguaje) verás que allí también y hay que rezar que jamás alguien a cambiar aONE=2
...Respuestas:
No todos los números mágicos son iguales.
Creo que en ese caso, esa constante está bien. El problema con los números mágicos es cuando son mágicos, es decir, no está claro cuál es su origen, por qué el valor es lo que es o si el valor es correcto o no.
Ocultar 1024 detrás de BYTES_PER_KBYTE también significa que no ves al instante si es correcto o no.
Esperaría que alguien supiera de inmediato por qué el valor es 1024. Por otro lado, si estuviera convirtiendo bytes a megabytes, definiría la constante BYTES_PER_MBYTE o similar porque la constante 1.048.576 no es tan obvia que es 1024 ^ 2, o que es incluso correcto
Lo mismo ocurre con los valores dictados por requisitos o estándares, que solo se utilizan en un lugar. Encuentro que poner la constante en su lugar con un comentario a la fuente relevante es más fácil de tratar que definirlo en otro lugar y tener que perseguir ambas partes, por ejemplo:
Me parece mejor que
Solo cuando
SOME_THRESHOLD_VALUE
se usa en varios lugares, la compensación se convierte en algo valioso para definir una constante, en mi opinión.fuente
e^i*pi = -1
es mucho más explícito (mejor) que2.718^i*3.142 = -1
. Las variables importan y no son solo para el código común. El código está escrito para leer primero, compilando segundo. Además, las especificaciones cambian (mucho). Mientras que el 1024 probablemente no debería estar en configuración, el 3.5 suena como debería estar.1024*1024
por favor!Hay dos preguntas que hago cuando se trata de números mágicos.
¿El número tiene un nombre?
Los nombres son útiles porque podemos leer el nombre y comprender el propósito del número detrás de él. Nombrar constantes puede aumentar la legibilidad si el nombre es más fácil de entender que el número que reemplaza y el nombre constante es conciso.
Claramente, constantes como pi, e, et al. tener nombres significativos Podría ser un valor como 1024
BYTES_PER_KB
pero también esperaría que cualquier desarrollador supiera lo que significa 1024. La audiencia prevista para el código fuente son los programadores profesionales que deben tener los antecedentes para conocer los diversos poderes de dos y por qué se utilizan.¿Se usa en múltiples ubicaciones?
Mientras que los nombres son una fuerza de las constantes, otra es la reutilización. Si es probable que cambie un valor, se puede cambiar en un lugar en lugar de tener que buscarlo en varias ubicaciones.
Tu pregunta
En el caso de su pregunta, usaría el número tal como está.
Nombre: hay un nombre para ese número, pero no es nada realmente útil. No representa una constante matemática o un valor especificado en ningún documento de requisitos.
Ubicaciones: incluso si se usa en múltiples ubicaciones, nunca cambiará, negando este beneficio.
fuente
Esta cita
como se ha dicho por Jörg W Mittag responde a esta pregunta bastante bien.
Algunos números simplemente no son mágicos dentro de un contexto particular. En el ejemplo proporcionado en la pregunta, las unidades de medida fueron especificadas por los nombres de las variables y la operación que estaba teniendo lugar era bastante clara.
Entonces
1024
no es mágico porque el contexto deja muy claro que es el valor apropiado y constante para las conversiones.Asimismo, un ejemplo de:
es igualmente claro y no mágico porque es bien sabido que hay 24 horas en el día.
fuente
24
todos modos! Como mencionó Izkata, los segundos de salto duelen. ¡Tal vez tendrías mejor suerte usando la constante24
en Marte que en la Tierra!Otros carteles han mencionado que la conversión que está ocurriendo es 'obvia', pero no estoy de acuerdo. La pregunta original, en este momento, incluye:
Entonces ya sé que el autor está o estaba confundido. La página de Wikipedia se suma a la confusión:
Por lo tanto, "Kilobyte" puede usarse para significar tanto un factor de 1000 como 1024, con la única diferencia en taquigrafía que es la capitalización de la 'k'. Además de eso, 1024 puede significar kilobyte (JEDEC) o kibibyte (IEC). ¿Por qué no destruir toda esa confusión directamente con una constante con un nombre significativo? Por cierto, este hilo ha usado "BYTES_PER_KBYTE" con frecuencia, y eso no es menos ambiguo. KBYTE: ¿es KIBIBYTE o KILOBYTE? Prefiero ignorar a JEDEC y tener
BYTES_PER_KILOBYTE = 1000
yBYTES_PER_KIBIBYTE = 1024
. No más confusión.La razón por la cual la gente como yo, y muchos otros por ahí, tienen opiniones 'militantes' (para citar a un comentarista aquí) sobre nombrar números mágicos se trata de documentar lo que pretendes hacer y eliminar la ambigüedad. Y en realidad elegiste una unidad que ha generado mucha confusión.
Si yo veo:
Entonces es inmediatamente obvio lo que el autor pretendía hacer, y no hay ambigüedad. Puedo verificar la constante en cuestión de segundos (incluso si está en otro archivo), por lo que, aunque no es 'instantáneo', está lo suficientemente cerca de instantáneo.
Al final, puede ser obvio cuando lo estás escribiendo, pero será menos obvio cuando vuelvas a hacerlo más tarde, y puede ser aún menos obvio cuando alguien más lo edite. Se necesitan 10 segundos para hacer una constante; Podría tomar media hora o más para depurar un problema con las unidades (el código no te saltará a la vista y te dirá que las unidades están equivocadas, tendrás que hacer los cálculos tú mismo para resolverlo, y probablemente cazarás 10 avenidas diferentes antes de revisar las unidades).
fuente
KB
) de manera diferente no ayudarán.La definición de un nombre como referencia a un valor numérico sugiere que siempre que se necesite un valor diferente en un lugar que use ese nombre, probablemente sea necesario en todos. También tiende a sugerir que cambiar el valor numérico asignado al nombre es una forma legítima de cambiar el valor. Tal implicación puede ser útil cuando es verdadera y peligrosa cuando es falsa.
El hecho de que dos lugares diferentes utilicen un valor literal particular (por ejemplo, 1024) sugerirá débilmente que los cambios que incitarían a un programador a cambiar uno probablemente inspirarán al programador a querer cambiar a otros, pero esa implicación es mucho más débil de lo que se aplicaría si el programador asignó un nombre a tal constante.
Un peligro importante con algo así
#define BYTES_PER_KBYTE 1024
es que podría sugerirle a alguien que encuentraprintf("File size is %1.1fkB",size*(1.0/BYTES_PER_KBYTE));
que una forma segura de hacer que el código use miles de bytes sería cambiar la#define
declaración. Sin embargo, dicho cambio podría ser desastroso si, por ejemplo, algún otro código no relacionado recibe el tamaño de un objeto en Kbytes y usa esa constante al asignarle un búfer.Puede ser razonable usar
#define BYTES_PER_KBYTE_FOR_USAGE_REPORT 1024
y#define BYTES_PER_KBYTE_REPORTED_BY_FNOBULATOR 1024
asignar un nombre diferente para cada propósito diferente que cumple la constante 1024, pero eso resultaría en que muchos identificadores se definan y usen exactamente una vez. Además, en muchos casos, es más fácil entender qué significa un valor si uno ve el código donde se usa, y es más fácil averiguar dónde significa el código si uno ve los valores de las constantes utilizadas en él. Si un literal numérico solo se usa una vez para un propósito particular, escribir el literal en el lugar donde se usa a menudo producirá un código más comprensible que asignarle una etiqueta en un lugar y usar su valor en otro lugar.fuente
Me inclinaría por usar solo el número, sin embargo, creo que no se ha planteado una cuestión importante: el mismo número puede significar cosas diferentes en diferentes contextos, y esto puede complicar la refactorización.
1024 es también el número de KiB por MiB. Supongamos que usamos 1024 para representar también ese cálculo en algún lugar, o en varios lugares, y ahora necesitamos cambiarlo para calcular GiB en su lugar. Cambiar la constante es más fácil que una búsqueda / reemplazo global donde puede cambiar accidentalmente la incorrecta en algunos lugares, o perderla en otros.
O incluso podría ser una máscara de bits introducida por un programador perezoso que necesita actualizarse algún día.
Es un ejemplo un poco artificial, pero en algunas bases de código esto puede causar problemas al refactorizar o actualizar los nuevos requisitos. Sin embargo, para este caso en particular, no consideraría que el número simple sea una forma realmente mala, especialmente si puede incluir el cálculo en un método para su reutilización, probablemente lo haría yo mismo, pero consideraría la constante más 'correcta'.
Sin embargo, si usa constantes con nombre, como dice supercat, es importante considerar si el contexto también es importante y si necesita varios nombres.
fuente