Entonces, ¿cada número en el código que estamos enviando a un método como argumento se considera un Número Mágico? Para mí, no debería. Creo que si hay algún número, digamos que es para la longitud mínima del nombre de usuario y comenzamos a usar "6" en el código ... entonces sí, tenemos un problema de mantenimiento y aquí "6" es un número mágico ... pero si estamos llamando a un método en el que uno de sus argumentos acepta un número entero, por ejemplo, como el miembro i-ésimo de una colección y luego pasamos "0" a esa llamada al método, en este caso no veo que "0" sea mágico número. ¿Qué piensas?
programming-practices
Blake
fuente
fuente
Respuestas:
Si el significado del número es muy claro en el contexto, no creo que sea un problema de "número mágico".
Ejemplo: supongamos que está tratando de obtener la subcadena de una cadena, desde el principio hasta un token y el código se ve así (lenguaje y biblioteca imaginarios):
En este contexto, el significado del número 0 es lo suficientemente claro. Supongo que podría definirlo
START_OF_SUBSTRING
y establecerlo en 0, pero en este caso creo que sería excesivo (aunque sería el enfoque correcto si supiera que el inicio de su subcadena podría no ser 0, pero eso depende de los detalles específicos de tu situación).Otro ejemplo podría ser si está tratando de determinar si un número es par o impar. Escritura:
no es tan extraño como:
Prueba de números negativos como
también me parece raro, preferiría ver
fuente
360
para marcar una rotación completa con el entendimiento de que la mayoría de la gente sabrá lo que eso significa (aunque esto es un caso en el que no habría daño para proporcionar una constante)0
en el contexto del ejemplo de mi subcadena. En cuyo caso, esta podría ser la menor cantidad de daño que pueden causar. Ha pasado mucho tiempo desde que hice cualquier codificación que hiciera cálculos geométricos, pero en general, los valores 15, 30, 45, 60, 90, 180, 360 fueron constantes que fueron aceptadas. Nunca he visto a nadie definirFIFTEEN_DEGREES
, ...Es obvio que cero significa ausencia. Encuentro 0 más fácil de entender que una variable llamada "ausenciaValor".
Es obvio que 0 es la posición inicial. Me confundiría con una variable llamada "firstPosition". Tal variable me haría preguntarme si la posición inicial podría cambiar.
fuente
Sugeriría tres factores clave para decidir si algo debería ser una declaración constante:
Algo como pi probablemente debería escribirse como una constante con nombre, en lugar de como un literal numérico, ya que un literal numérico puede ser innecesariamente detallado, innecesariamente impreciso o ambos. Algo así como el número de ranuras en un caché probablemente debería ser una constante con nombre (aunque vea la nota a continuación) para permitir la posibilidad de expandir el caché sin tener que modificar todo el código que lo usa. Cosas como los números "4", "28" y "29" en el enunciado
if ((year % 4)==0) FebruaryDays = 29; else FebruaryDays = 28;
probablemente no deberían denominarse constantes, ya que la expresión es casi ciertamente más legible queif ((year % YearsBetweenLeapYears)==0) FebruaryDays = FebruaryDaysInLeapYear; else FebruaryDays = FebruaryDaysInNonLeapYear;
. Tenga en cuenta que los mantenedores de las normas han indicado que la duración de febrero de 2100 en ese año no coincidirá con la fórmula anterior, impedimento para manejar correctamente tales fechas (es decir, el código no se disparará por desbordamiento de enteros u otros problemas similares).Una advertencia importante con la regla # 2 es que, en algunos casos, el código puede depender de números codificados de una manera que no puede representarse fácilmente por una constante con nombre. Por ejemplo, un método que calcula un producto cruzado de dos vectores pasados como parámetros discretos solo será significativo cuando se use en vectores tridimensionales. El número requerido de dimensiones no es un valor que pueda cambiarse significativamente sin reescribir completamente la rutina. Incluso si se preveía una posible necesidad de calcular el producto cruzado de tres vectores de 4 dimensiones, usar una constante con nombre para el valor "3" haría poco para facilitar la satisfacción de esa necesidad.
fuente
Esto, como todos los principios, es una cuestión de grado. En términos generales, los literales de números en el código fuente son más sospechosos cuanto más grandes son. Una longitud máxima como 10 o una dirección de memoria como 0x587FB0 es obviamente una mala práctica: es casi seguro que tarde o temprano tendrá que repetir estos valores más de una vez, creando un riesgo de incompatibilidad y errores sutiles introducidos en lugares que no fueron cambiado
0 está en el otro extremo de la escala; todavía es sospechoso pero no tanto. ¿Estás usando 0 como valor centinela? Entonces probablemente deberías usar una constante simbólica, solo porque la constante puede explicar lo que significa. ¿Es un acuerdo cultural extremadamente arraigado como "0 significa finalización exitosa"? Eso probablemente está bien. ¿Significa "el primer elemento de una colección"? Eso puede ser inofensivo, pero si hay un método alternativo como el
first()
que probablemente prefiera.fuente
Cada número sin nombre que no es inmediatamente obvio por el contexto es un número mágico. Es un poco tonto definir números que tienen un significado que es inmediatamente obvio por el contexto.
En django (python web framework), puedo definir algún campo de base de datos con un número sin formato como:
que es más claro (y la práctica recomendada ) que decir
como es poco probable que necesite cambiar la longitud (y siempre se puede comparar con la
max_length
del campo). Si necesito cambiar la longitud del campo después de implementar inicialmente la aplicación, necesito cambiarlo exactamente en una ubicación por campo en mi código django, y luego escribir una migración para cambiar el esquema de la base de datos. Si alguna vez necesito hacer referenciamax_length
a un campo definido de un tipo de objeto, puedo hacerlo directamente; si esos campos definían unaPerson
clase, puedo usarPerson._meta.get_field('firstname').max_length
para obtener elmax_length
siendo utilizado (que se define en un lugar). El hecho de que se usó el mismo 40 para múltiples campos es irrelevante, ya que es posible que desee cambiarlos de forma independiente. La longitud del nombre nunca debe depender de la longitud del segundo nombre o apellido; son valores separados y pueden cambiar de forma independiente.A menudo, los índices de matriz pueden usar números sin nombre; como si tuviera un archivo CSV de datos que quiero poner en un diccionario de Python, con el primer elemento en la fila como el diccionario
key
que escribiría:Claro que podría nombrar
index_column = 0
y hacer algo como:o peor, definir
after_index_col = index_col + 1
para deshacerse de élindex_col+1
, pero eso no hace que el código sea más claro en mi opinión. Además, si le doyindex_col
un nombre, mejor hago que el código funcione incluso si la columna no es 0 (de ahí larow[:index_col] +
parte).fuente
max_lngth=40
vs.max_length=MAX_LENGTH_NAME
es un ejemplo clásico de un número mágico que grita como símbolo. Llegará el día en que desee admitir 45 nombres de caracteres, y ahora cada uso de "40" es sospechoso y debe ser examinado cuidadosamente.40
a1
. Tienes que pensar en el contexto.