¿Es alguna vez una buena idea codificar los valores en nuestras aplicaciones?

43

¿Es alguna vez una buena idea codificar los valores en nuestras aplicaciones? ¿O es siempre lo correcto llamar a estos tipos de valores de forma dinámica en caso de que necesiten cambiar?

    
pregunta Edward 14.04.2011 - 02:26

14 respuestas

64

Sí, pero haz que sea objetivo .

Haz:

No:

respondido por el Jonathan Khoo 14.04.2011 - 02:31
22

Lo que me parece extraño de esta pregunta y respuesta hasta ahora es que en realidad nadie ha intentado definir claramente el "código duro" o, lo que es más importante, las alternativas.

tl; dr: Sí, es a veces es una buena idea para los valores de código duro, pero no hay una regla simple para cuándo ; depende completamente del contexto.

La pregunta la reduce a valores , lo que entiendo que significa números mágicos , pero la respuesta a si son o no una buena idea es relativa a para qué se usan realmente

Varios ejemplos de valores "codificados" son:

  • Valores de configuración

    Me estremezco cada vez que veo declaraciones como command.Timeout = 600 . ¿Por qué 600? ¿Quién decidió eso? ¿Se había agotado el tiempo antes y alguien planteó el tiempo de espera como un hack en lugar de solucionar el problema de rendimiento subyacente? ¿O es realmente una expectativa conocida y documentada para el tiempo de procesamiento?

    Estos no deben ser constantes de números mágicos o , deben ser externalizados en un archivo de configuración o base de datos en algún lugar con un nombre significativo, ya que su valor óptimo está determinado en gran parte o completamente por el entorno en el que la aplicación se está ejecutando en.

  • Fórmulas matemáticas

    Las fórmulas por lo general tienden a ser bastante estáticas, de modo que la naturaleza de los valores constantes no es particularmente importante. El volumen de una pirámide es (1/3) b * h. ¿Nos importa de dónde vienen los 1 o 3? Realmente no. Un comentarista anterior señaló acertadamente que diameter = radius * 2 es probablemente mejor que diameter = radius * RADIUS_TO_DIAMETER_CONVERSION_FACTOR , pero eso es una falsa dicotomía.

    Lo que deberías estar haciendo para este tipo de escenario es crear una función . No necesito saber cómo surgió con la fórmula, pero aún necesito saber para qué sirve . Si, en lugar de cualquiera de las tonterías escritas arriba, escribo volume = GetVolumeOfPyramid(base, height) , entonces de repente todo se vuelve mucho más claro, y está perfectamente bien tener números mágicos dentro de la función ( return base * height / 3 ) porque es obvio que solo son parte de la fórmula.

    La clave aquí es, por supuesto, tener las funciones corta y simple . Esto no funciona para funciones con 10 argumentos y 30 líneas de cálculos. Use la composición de funciones o constantes en ese caso.

  • Dominio / reglas de negocio

    Esta es siempre el área gris porque depende de cuál es exactamente el valor. La mayoría de la época, estos números mágicos particulares son candidatos para convertirse en constantes, porque eso hace que el programa sea más fácil de entender sin complicar la lógica del programa. Considere la prueba if Age < 19 vs. if Age < LegalDrinkingAge ; probablemente puedas descubrir qué está pasando sin la constante, pero es más fácil con el título descriptivo.

    Estos también pueden convertirse en candidatos para la abstracción de funciones, por ejemplo, function isLegalDrinkingAge(age) { return age >= 19 } . Lo único es que a menudo su lógica empresarial es mucho más complicada que eso, y puede que no tenga sentido comenzar a escribir docenas de funciones con 20-30 parámetros cada una. Si no hay una abstracción clara basada en objetos y / o funciones, entonces está bien recurrir a las constantes.

    La advertencia es que, si está trabajando para el departamento de impuestos, se vuelve realmente, realmente una carga y honestamente no tiene sentido escribir AttachForm(FORM_CODE_FOR_SINGLE_TAXPAYER_FILING_JOINTLY_FOR_DEPRECIATION_ON_ARMPIT_HAIR) . No va a hacer eso, va a AttachForm("B-46") porque todos los desarrolladores que hayan trabajado o que trabajarán allí sabrán que "B-46" es el código del formulario para un solo contribuyente que presenta la declaración de impuestos. bla bla: los códigos de formulario son parte del dominio en sí, nunca cambian, por lo que no son realmente números mágicos.

    Entonces, tienes que usar constantes con moderación en la lógica de negocios; básicamente tienes que entender si ese "número mágico" es realmente un número mágico o si es un aspecto bien conocido del dominio. Si se trata de un dominio, no lo codifiques a menos que haya una buena posibilidad de que cambie.

  • Códigos de error e indicadores de estado

    Estos son nunca bien para codificar, como puede decirte cualquier bastardo pobre que haya sido golpeado con Previous action failed due to error code 46 . Si su idioma lo admite, debe utilizar un tipo de enumeración. De lo contrario, normalmente tendrá un archivo / módulo completo lleno de constantes que especifican los valores válidos para un tipo de error en particular.

    ¿No me dejas ver return 42 en un controlador de errores, Capiche? No hay excusas.

Probablemente dejé de lado varios escenarios pero creo que eso cubre la mayoría de ellos.

Entonces, sí, a veces es una práctica aceptable para el código duro. Simplemente no seas perezoso al respecto; debe ser una decisión consciente en lugar de un código descuidado viejo y simple.

    
respondido por el Aaronaught 14.04.2011 - 20:23
5

Como una adición a otras respuestas. Use constantes para cadenas cuando sea posible. Por supuesto, no quieres tener

const string server_var="server_var";

pero deberías tener

const string MySelectQuery="select * from mytable;";

(asumiendo que realmente tiene una consulta en la que desea obtener todos los resultados de una tabla específica, siempre)

Aparte de eso, use constantes para cualquier número que no sea 0 (generalmente). Si necesita una máscara de bits de permiso de 255, no la use

const int 8th_bit=255; //or some other obscure naming scheme that equates to 255.

en lugar de utilizar

const int AllowGlobalRead=255;

Por supuesto, junto con las constantes, saber cuándo usar enumeradores. El caso anterior probablemente encajaría bien en uno.

    
respondido por el Earlz 14.04.2011 - 04:57
5

Hay varias razones para asignar un identificador a un número.

  • Si el número puede cambiar, debería tener un identificador. Es mucho más fácil encontrar NUMBER_OF_PLANETS que buscar cada instancia de 9 y considerar si se debe cambiar a 8. (Tenga en cuenta que las cadenas visibles por el usuario podría tener que cambiar si alguna vez se tiene que usar el software en un idioma diferente, y eso es algo difícil de predecir con anticipación.)
  • Si el número es difícil de escribir de alguna manera. Para constantes como pi, es mejor dar una definición de máxima precisión que volver a escribirla en varios lugares, posiblemente de forma incorrecta.
  • Si el número aparece en diferentes lugares. No debería tener que mirar dos usos de 45 en las funciones adyacentes y preguntarse si significan lo mismo.
  • Si el significado no se reconoce al instante. Es seguro asumir que todo el mundo sabe lo que es 3.14159265 ... No es seguro asumir que todos reconocerán la constante gravitacional, o incluso pi / 2. ("Todo el mundo" depende de la naturaleza del software. Se puede esperar que los programadores de sistemas conozcan la representación octal de los bits de permiso de Unix o similares. En el software de arquitectura naval / marina, verificar el número de Froude de un casco propuesto y la velocidad para ver si es 1.1 o mayor podría ser perfectamente auto-explicativo para cualquiera que debería estar trabajando en ello.)
  • Si el contexto no es reconocible. Todo el mundo sabe que hay 60 minutos en una hora, pero multiplicar o dividir por 60 puede no estar claro si no hay indicaciones inmediatas de que la cantidad sea un valor de tiempo o un valor de tasa .

Esto nos da criterios para los literales de codificación rígida. Deben ser inmutables, no difíciles de escribir, que ocurren en un solo lugar o contexto, y con un significado reconocible. No tiene sentido definir 0 como ARRAY_BEGINNING, por ejemplo, o 1 como ARRAY_INCREMENT.

    
respondido por el David Thornley 14.04.2011 - 16:10
4
  

¿Es siempre una buena idea para codificar?   valores en nuestras aplicaciones?

Los valores de código duro solo si los valores están especificados en la Especificación (en una versión final de la especificación), por ejemplo. La respuesta HTTP OK siempre será 200 (a menos que cambie en el RFC), por lo tanto, verá (en algunos de mis códigos) constantes como:

public static final int HTTP_OK = 200;

De lo contrario, almaceno constantes en el archivo de propiedades.

La razón por la que especifiqué las especificaciones, es que las constantes cambiantes en las especificaciones requieren una administración de cambios, en la cual, las partes interesadas revisarán el cambio y aprobarán / rechazarán. Nunca sucede durante la noche y toma meses / años para una aprobación. No olvide que muchos desarrolladores utilizan especificaciones (por ejemplo, HTTP), por lo que cambiarlo significa romper millones de sistemas.

    
respondido por el Buhake Sindi 14.04.2011 - 15:27
3
  • si el valor puede cambiar, y de hecho podría cambiar, entonces codifíquelo siempre que sea posible siempre y cuando el esfuerzo involucrado no exceda el rendimiento esperado
  • algunos valores no pueden tener un código suave; siga las pautas de Jonathan en esos (raros) casos
respondido por el Steven A. Lowe 14.04.2011 - 04:28
3

Depende de lo que consideres hardcoding. Si intentas evitar todas y cada una de las cosas codificadas, terminas en el territorio de softcoding , y creas un sistema que solo el creador puede administrar (y ese es el código definitivo)

Muchas de las cosas están codificadas en cualquier marco razonable y funcionan. es decir, no hay ninguna razón técnica por la que no pueda cambiar el punto de entrada de una aplicación de C # (estático vacío principal), pero la codificación no crea ningún problema para ningún usuario (excepto el ocasional SOSO )

La regla de oro que utilizo es que todo lo que pueda y vaya a cambiar, sin afectar el estado de todo el sistema, debería ser confugerable.

Así que, IMHO, es una tontería no codificar cosas que nunca cambian (pi, constante gravitacional, una constante en una fórmula matemática - piense en el volumen de una esfera).

También es tonto no codificar cosas o procesos que tendrán un impacto en su sistema que requerirá programación en cualquier caso, es decir, es inútil permitir que el usuario agregue campos dinámicos a un formulario, si algún campo agregado requiera la desarrollador de mantenimiento para entrar y escribir algunos scripts que harán que esa cosa funcione. También es estúpido (y lo he visto varias veces en entornos empresariales) crear alguna herramienta de configuración, por lo que nada está codificado, sin embargo, solo los desarrolladores del departamento de TI pueden usarlo, y es un poco más fácil de usar que para hacerlo en Visual Studio.

Por lo tanto, en definitiva, si una cosa debe estar codificada en forma rígida es una función de dos variables:

  • cambiará el valor
  • ¿Cómo afectará el sistema un cambio en el valor?
respondido por el SWeko 14.04.2011 - 09:21
2

Recientemente codifiqué una función MySQL para calcular correctamente la distancia entre dos pares de latitud / longitud. No puedes simplemente hacer pitagoro; las líneas de longitud se acercan a medida que la latitud aumenta hacia los polos, por lo que hay un poco de truco peludo involucrado. El punto es que estaba bastante preocupado acerca de si codificar el valor que representa el radio de la Tierra en millas.

Terminé haciéndolo, aunque el hecho es que las líneas de latencia / latencia están mucho más juntas en, digamos, la luna. Y mi función subestimaría drásticamente las distancias entre los puntos en Júpiter. Pensé que las posibilidades del sitio web que estoy construyendo al tener una ubicación extraterrestre para ingresar son muy escasas.

    
respondido por el Dan Ray 14.04.2011 - 14:27
1

He notado que cada vez que puedes extraer datos de tu código, mejora lo que queda. Comienza a notar nuevas refactorizaciones y mejora secciones completas de su código.

Es solo una buena idea trabajar para extraer constantes, no lo consideres una regla estúpida, piénsalo como una oportunidad para codificar mejor.

La mayor ventaja sería la forma en la que podría encontrar constantes similares, ya que es la única diferencia en los grupos de código: abstraerlos en arreglos me ha ayudado a reducir algunos archivos en un 90% de su tamaño y corregir algunas copias & pegar errores mientras tanto.

Todavía no he visto una sola ventaja para no extraer datos.

    
respondido por el Bill K 14.04.2011 - 08:13
1

Bueno, depende de si tu lenguaje está compilado. Si no está compilado, no es un gran problema, simplemente edite el código fuente, incluso si será un poco delicado para un programador.

Si está programando con un lenguaje compilado, esto claramente no es una buena idea, porque si las variables cambian, tiene que volver a compilar, lo que es una gran pérdida de tiempo si desea ajustar esta variable.

No es necesario crear un control deslizante o una interfaz para cambiar dinámicamente su variable, pero lo menos que puedes hacer es un archivo de texto.

Por ejemplo, con mi proyecto de ogro, siempre estoy usando la clase ConfigFile para cargar una variable que he escrito en un archivo de configuración.

    
respondido por el jokoon 14.04.2011 - 14:06
1

Dos ocasiones en que las constantes son (en mi opinión al menos) OK:

  1. Constantes que no se relacionan con nada más; Puedes cambiar esas constantes cuando quieras sin tener que cambiar nada más. Ejemplo: El ancho predeterminado de una columna de la cuadrícula.

  2. Constantes obvias, absolutamente inmutables, precisas, como "número de días por semana". days = weeks * 7 Reemplazar 7 con una constante DAYS_PER_WEEK casi no proporciona ningún valor.

respondido por el user281377 14.04.2011 - 14:26
0

Estoy completamente de acuerdo con Jonathan pero como todas las reglas hay excepciones ...

"Número mágico en la especificación: Número mágico en el código"

Básicamente establece que cualquier número mágico que permanezca en la especificación después de intentos razonables de obtener un contexto descriptivo para ellos debe reflejarse como tal en el código. Si los números mágicos permanecen en el código, se deben hacer todos los esfuerzos para aislarlos y vincularlos claramente a su punto de origen.

He realizado algunos contratos de interconexión donde es necesario rellenar mensajes con valores asignados desde la base de datos. En la mayoría de los casos, el mapeo es bastante sencillo y encajaría en las líneas de guía general de Jonathan, pero he encontrado casos en los que la estructura del mensaje de destino era simplemente horrible. Más del 80% de los valores que debían transmitirse en la estructura eran constantes aplicadas por la especificación del sistema distante. esto, junto con el hecho de que la estructura del mensaje era gigantesca, hizo que MUCHAS de tales constantes tuvieran que ser pobladas. En la mayoría de los casos, no proporcionaron un significado o razón, solo dijeron "ponga M aquí" o "ponga 4.10.53.10100.889450.4452 aquí". Tampoco intenté poner un comentario junto a todos ellos habría hecho ilegible el código resultante. Sin embargo, me aseguré de que las secciones de código en las que aparecen estos valores mágicos estén bien aisladas y que sus contenedores (clases, paquetes) tengan el nombre adecuado para apuntar directamente a la especificación que los aplica.

Dicho esto, cuando lo piensas ... todo se trata de hacerlo obvio ...

    
respondido por el Newtopian 14.04.2011 - 07:40
0

Si está codificando el valor de la constante gravitacional de la Tierra, a nadie le importará. Si codifica la dirección IP de su servidor proxy, tendrá problemas.

    
respondido por el jwenting 14.04.2011 - 09:02
0

Mayormente no, pero creo que vale la pena señalar que tendrá la mayoría de los problemas cuando comience a duplicar el valor codificado. Si no lo duplica (por ejemplo, úselo solo una vez en la implementación de una clase), entonces no usar una constante podría estar bien.

    
respondido por el user22908 14.04.2011 - 09:23

Lea otras preguntas en las etiquetas