Todos somos conscientes de que los números mágicos (valores codificados) pueden causar estragos en su programa, especialmente cuando es hora de modificar una sección de código que no tiene comentarios, pero ¿dónde dibuja la línea?
Por ejemplo, si tiene una función que calcula el número de segundos entre dos días, ¿reemplaza
seconds = num_days * 24 * 60 * 60
con
seconds = num_days * HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE
¿En qué momento decide que es completamente obvio lo que significa el valor codificado y lo deja en paz?
refactoring
coding-standards
maintainability
oosterwal
fuente
fuente
seconds = CALC_SECONDS(num_days);
TimeSpan.FromDays(numDays).Seconds;
HOURS_PER_DAY will never need to be altered
), nunca codificará el software implementado en Marte. : PRespuestas:
Hay dos razones para usar constantes simbólicas en lugar de literales numéricos:
Para simplificar el mantenimiento si cambian los números mágicos. Esto no se aplica a su ejemplo. Es extremadamente improbable que cambie la cantidad de segundos en una hora o la cantidad de horas en un día.
Para mejorar la lectura. La expresión "24 * 60 * 60" es bastante obvia para casi todos. "SECONDS_PER_DAY" también lo es, pero si está buscando un error, es posible que deba verificar que SECONDS_PER_DAY se haya definido correctamente. Hay valor en la brevedad.
Para los números mágicos que aparecen exactamente una vez y son independientes del resto del programa, decidir si crear un símbolo para ese número es cuestión de gustos. Si hay alguna duda, continúe y cree un símbolo.
No hagas esto:
fuente
publid final int FOUR = 3;
public static int THREE = 3;
... nota:final
¡ no !Mantendría la regla de nunca tener números mágicos.
Mientras
Es perfectamente legible la mayor parte del tiempo, después de haber codificado durante 10 horas al día durante tres o cuatro semanas en modo crujiente
Es mucho más fácil de leer.
La sugerencia de FrustratedWithFormsDesigner es mejor:
o mejor
Las cosas dejan de ser obvias cuando estás muy cansado. Código defensivo .
fuente
El momento de decir que no es casi siempre. Los momentos en los que encuentro que es más fácil usar números codificados es en lugares como el diseño de la interfaz de usuario: crear una constante para el posicionamiento de cada control en el formulario se vuelve muy cubmersone y agotador, y si ese código generalmente lo maneja un diseñador de interfaz de usuario, no importa mucho ... a menos que la IU se presente dinámicamente, o use posiciones relativas a algún ancla o se escriba a mano. En ese caso, diría que es mejor definir algunas constantes significativas para el diseño. Y si necesita un factor fudge aquí o allá para alinear / posicionar algo "justo", eso también debe definirse.
Pero en su ejemplo, creo que reemplazar
24 * 60 * 60
porDAYS_TO_SECONDS_FACTOR
es mejor.Admito que los valores codificados también están bien cuando el contexto y el uso son completamente claros. Esto, sin embargo, es un juicio ...
Ejemplo:
Como señaló @rmx, usar 0 o 1 para verificar si una lista está vacía, o tal vez en los límites de un bucle, es un ejemplo de un caso en el que el propósito de la constante es muy claro.
fuente
0
o1
creo.if(someList.Count != 0) ...
es mejor queif(someList.Count != MinListCount) ...
. No siempre, pero en general.Detente cuando no puedas precisar un significado o un propósito para el número.
es mucho más fácil de leer que simplemente usar los números. (Aunque podría hacerse más legible al tener una sola
SECONDS_PER_DAY
constante, pero es un problema completamente separado).Suponga que un desarrollador que mira el código puede ver lo que hace. Pero no asuma que ellos también saben por qué. Si su constante ayuda a entender el por qué, hágalo. Si no, no lo hagas.
Si termina con demasiadas constantes, como sugirió una respuesta, considere usar un archivo de configuración externo, ya que tener docenas de constantes en un archivo no mejora exactamente la legibilidad.
fuente
Probablemente diría "no" a cosas como:
Y definitivamente diría "no" a:
fuente
Uno de los mejores ejemplos que he encontrado para promover el uso de constantes para cosas obvias como
HOURS_PER_DAY
es:Estábamos calculando cuánto tiempo estuvieron las cosas en la cola de trabajo de una persona. Los requisitos se definieron en términos generales y el programador codificó
24
en varios lugares. Finalmente, nos dimos cuenta de que no era justo castigar a los usuarios por estar sentados en un problema durante 24 horas, cuando realmente solo funcionan 8 horas al día. Cuando llegó la tarea de arreglar esto Y ver qué otros informes podrían tener el mismo problema, fue bastante difícil buscar / buscar en el código para 24 hubiera sido mucho más fácil de buscar / buscarHOURS_PER_DAY
fuente
Creo que mientras el número sea completamente constante y no tenga posibilidad de cambiar, es perfectamente aceptable. Entonces, en su caso,
seconds = num_days * 24 * 60 * 60
está bien (suponiendo, por supuesto, que no hace algo tonto como hacer este tipo de cálculo dentro de un ciclo) y podría decirse que es mejor para la legibilidad queseconds = num_days * HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE
.Cuando haces cosas como esta es malo:
lineOffset += 24; // 24 lines to a page
Incluso si no puede ajustar más líneas en la página o incluso si no tiene intenciones de cambiarla, use una variable constante en su lugar, porque algún día volverá a perseguirlo. En última instancia, el punto es la legibilidad, no guardar 2 ciclos de cálculo en la CPU. Esto ya no es 1978 cuando se apretaron los preciosos bytes para todo su valor.
fuente
Está perfectamente bien. Estos no son realmente números mágicos, ya que nunca cambiarán.
Cualquier número que pueda cambiar razonablemente o que no tenga un significado obvio debe ponerse en variables. Lo que significa casi todos ellos.
fuente
seconds = num_days * 86400
Aún sería aceptable? Si un valor como ese se usara varias veces en muchos archivos diferentes, ¿cómo verificaría que alguien no haya escrito accidentalmenteseconds = num_days * 84600
en uno o dos lugares?Evitaría crear constantes (valores mágicos) para convertir un valor de una unidad a otra. En caso de convertir, prefiero un nombre de método de voz. En este ejemplo, esto sería, por ejemplo,
DayToSeconds(num_days)
interno, el método no necesita valores mágicos porque el significado de "24" y "60" está claro.En este caso nunca usaría segundos / minutos / horas. Solo usaría TimeSpan / DateTime.
fuente
Use el contexto como parámetro para decidir
Por ejemplo, tiene una función llamada "CalculateSecondsBetween: aDay y: anotherDay", no necesitará hacer mucha explicación sobre lo que hacen esos números, porque el nombre de la función es bastante representativo.
Y otra pregunta es, ¿cuáles son las posibilidades de calcularlo de una manera diferente? A veces hay muchas maneras de hacer lo mismo, así que para guiar a los futuros programadores y mostrarles qué método usó, definir constantes podría ayudar a resolverlo.
fuente