language agnostic - ¿Los literales de codificación dura son aceptables?
language-agnostic hard-coding (21)
¿Y puede alguien pensar en algún lugar donde la codificación dura es una práctica aceptable?
- Pequeñas aplicaciones
- Proyectos de hombre soltero
- Tirar lejos
- Proyectos de vida corta
En resumen, cualquier cosa que no sea mantenida por otros.
Vaya, me acabo de dar cuenta de cuánto me duele el ser codificador de mantenimiento en el pasado :)
La base de código en la que estoy trabajando actualmente está llena de valores codificados.
Veo todos los valores codificados como un olor a código y trato de eliminarlos cuando sea posible ... sin embargo, hay algunos casos de los que no estoy seguro.
Aquí hay dos ejemplos en los que puedo pensar que me preguntan cuál es la mejor práctica:
1. MyTextBox.Text = someCondition ? "Yes" : "No"
2. double myPercentage = myValue / 100;
En el primer caso, es lo mejor que se puede hacer para crear una clase que me permita hacer MyHelper.Yes y MyHelper.No o tal vez algo similar en un archivo de configuración (aunque no es probable que cambie y quién sabe si podría alguna vez habrá un caso en el que su uso sea sensible a mayúsculas y minúsculas).
En el segundo caso, encontrar un porcentaje al dividir entre 100 no cambiará a menos que las leyes de las matemáticas cambien ... pero aún me pregunto si hay una mejor manera.
¿Alguien puede sugerir una forma apropiada de lidiar con este tipo de codificación difícil? ¿Y puede alguien pensar en algún lugar donde la codificación dura es una práctica aceptable?
"hardcoding" es lo incorrecto de lo que preocuparse. El punto no es si los valores especiales están en el código o en los archivos de configuración, el punto es:
- Si el valor podría alguna vez cambiar, ¿cuánto trabajo es eso y qué tan difícil es encontrarlo? Ponerlo en un lugar y hacer referencia a ese lugar en otro lugar no es mucho trabajo y, por lo tanto, una forma de ir a lo seguro.
- ¿Los programadores de mantenimiento definitivamente entenderán por qué el valor es lo que es? Si hay alguna duda, use una constante con nombre que explique el significado.
Ambos objetivos se pueden lograr sin necesidad de archivos de configuración; de hecho, evitaría esos si es posible. "poner cosas en archivos de configuración significa que es más fácil cambiar" es un mito, a menos que
- de hecho quieres apoyar a los clientes cambiando los valores ellos mismos
- ningún valor que pueda colocarse en el archivo de configuración puede causar un error (desbordamiento de búfer, ¿alguien?)
- su proceso de compilación y despliegue es una mierda
El código siempre evoluciona. Cuando inicialmente escribes cosas, la codificación dura es la forma más fácil de hacerlo. Más tarde, cuando llega la necesidad de cambiar el valor, puede mejorarse. En algunos casos, la necesidad nunca llega.
La necesidad puede llegar de muchas formas:
El valor se usa en muchos lugares y debe ser modificado por un programador. En este caso, una constante es claramente necesaria.
El usuario necesita poder cambiar el valor.
No veo la necesidad de evitar la codificación difícil. Veo la necesidad de cambiar las cosas cuando hay una necesidad clara.
El problema totalmente separado es que, por supuesto, el código debe ser legible y esto significa que puede haber una necesidad de un comentario para el valor codificado.
El primer caso te matará si alguna vez necesitas localizarlo. Moverlo a algo estático o constante que abarque toda la aplicación al menos facilitaría la localización.
Está bien siempre que no realices refactorizaciones, pruebas de unidades, revisiones de códigos de pares. Y, no quieres clientes repetidos. ¿A quien le importa?
La codificación dura debería estar prohibida para siempre. Aunque en usted, ejemplos muy simples, no veo nada de malo usándolos en ningún tipo de proyecto.
En mi opinión, la codificación dura es cuando crees que una variable / valor / definición, etc. nunca cambiará y creará todo tu código en función de esa creencia.
Ejemplo de codificación tan difícil es el libro Teach Yourself C en 24 horas que todos deberían evitar.
La mejor forma para su segundo ejemplo sería definir una función en línea:
double getpercentage(double myValue)
{
return(myValue / 100);
}
...
double myPercentage = getpercentage(myValue);
De esa forma, es mucho más obvio lo que estás haciendo.
La verdadera pregunta no es sobre la codificación difícil, sino más bien sobre la repetición. Si toma el excelente consejo que se encuentra en "El programador pragmático" , simplemente "No repetir" (SECO).
Tomando el principio de DRY, está bien codificar algo en cualquier punto. Sin embargo, una vez que use ese valor particular nuevamente, refactorice para que este valor solo esté codificado una vez.
No creo que tu segundo sea realmente un ejemplo de hardcoding. Es como tener un método Halve () que toma un valor para usar para dividir; no tiene sentido
Más allá de eso, ejemplo 1, si desea cambiar el idioma de su aplicación, no desea tener que cambiar la clase, por lo que debe estar absolutamente en una configuración.
La codificación difícil debe evitarse, como Drácula evita el sol. Volverá para morderte finalmente.
Normalmente agrego un conjunto de métodos auxiliares para cadenas y números.
Por ejemplo, cuando tengo cadenas como ''sí'' y ''no'', tengo una función llamada __, así que llamo a __ (''sí''); que comienza en el proyecto simplemente devolviendo el primer parámetro, pero cuando necesito hacer cosas más complejas (como internationaizaton) ya está allí y el param puede usarse una clave.
Otro ejemplo es el IVA (forma de impuesto del Reino Unido) en las tiendas en línea, recientemente cambió de 17.5% a 15%. Cualquiera que haya codificado el IVA duro haciendo esto:
$vat = $price * 0.175;
tuvo que revisar todas las referencias y cambiarlo a 0.15, en su lugar, la forma más útil de hacerlo sería tener una función o variable para el IVA.
En mi opinión, cualquier cosa que pueda cambiar debería escribirse de manera variable. Si me encuentro haciendo lo mismo más de 5 veces en el mismo día, entonces se convierte en una función o una configuración var.
Nunca es bueno y lo has probado ...
double myPercentage = myValue / 100;
Esto NO es un porcentaje Lo que quería escribir es:
double myPercentage = (myValue / 100) * 100;
O más correctamente:
double myPercentage = (myValue / myMaxValue) * 100;
Pero este disco duro 100 se metió en tu mente ... Así que ve por el método getPercentage que Colen sugirió :)
double getpercentage(double myValue, double maxValue)
{
return (myValue / maxValue) * 100;
}
También como sugirió ctacke, en el primer caso estarás en un mundo de dolor si alguna vez necesitas localizar estos literales. Nunca es demasiado problema agregar un par de variables y / o funciones adicionales
Para el primer valor, realmente depende. Si no anticipa ningún tipo de adopción generalizada de su aplicación y la internacionalización nunca será un problema, creo que está muy bien. Sin embargo, si está escribiendo algún tipo de software de código abierto o algo con un público más grande, considere el hecho de que algún día deberá ser traducido. En ese caso, es mejor que uses recursos de cadenas.
Por supuesto, la codificación difícil a veces es aceptable. Seguir el dogma rara vez es una práctica tan útil como usar el cerebro.
(Para un ejemplo de esto, tal vez es interesante volver a las guerras goto. ¿Cuántos programadores conoces que jurarán por todas las cosas sagradas que el goto es malo? ¿Por qué entonces Steve McConnell dedica una docena de páginas a una discusión mesurada de el sujeto en el Código Completo?)
Claro, hay una gran cantidad de experiencia adquirida que nos dice que las pequeñas aplicaciones desechables a menudo se transforman en código de producción, pero eso no es motivo de fanatismo. Los agilistas nos dicen que debemos hacer lo más simple que pueda funcionar y refactorizar cuando sea necesario.
Eso no quiere decir que la "cosa más simple" no deba ser un código legible. Puede tener mucho sentido, incluso en un punto de desecho para escribir:
const MAX_CACHE_RECORDS = 50
foo = GetNewCache(MAX_CACHE_RECORDS)
Esto es independientemente del hecho de que en tres iteraciones de tiempo, alguien podría pedir que se configure la cantidad de registros de caché, y podría terminar refaccionando la constante.
Solo recuerda, si vas a los extremos de cosas como
const ONE_HUNDRED = 100
const ONE_HUNDRED_AND_ONE = 101
todos acudiremos a The Daily WTF y nos reiremos de ti. :-)
¡Pensar! Eso es todo.
Recuerde que olvidará el significado de cualquier valor codificado no obvio.
Así que asegúrese de poner un breve comentario después de cada uno para recordarle.
Un ejemplo de Delphi:
Longitud: = Longitud * 0.3048; {0.3048 pies cuadrados a metros}
Tiendo a verlo en términos del alcance y tamaño del proyecto.
¿Algunos proyectos simples en los que soy solista? Claro, codifico muchas cosas. Herramientas que escribo que solo usaré alguna vez? Claro, si hace el trabajo bien.
Pero, al trabajar en proyectos de equipo más grandes? Estoy de acuerdo, son sospechosos y generalmente son producto de la pereza. Etiquetarlos para su revisión y ver si puede detectar un patrón donde se pueden abstraer.
En su ejemplo, el cuadro de texto debe ser localizable, ¿por qué no una clase que maneja eso?
Una vez tuve un jefe que se negó a no codificar algo porque, en su opinión, le daba control total sobre el software y los elementos relacionados con el software. El problema fue que cuando el hardware murió y se ejecutó el software, el servidor cambió de nombre ... lo que significa que tuvo que encontrar su código. Eso tomó un tiempo. Simplemente encontré un editor hexadecimal y lo pirateé en lugar de esperar.
no.
Lo que hoy es una simple aplicación de tirar conducirá a toda tu empresa mañana. Siempre use las mejores prácticas o lo lamentará.
Caso 1: ¿ Cuándo deberías codificar cosas: cuando no tienes motivos para pensar que alguna vez cambiará? Dicho eso, NUNCA deberías codificar cosas en línea. Tómese el tiempo para hacer variables estáticas o variables globales o lo que sea que su lenguaje le de. Hágalos en la clase en cuestión, y si nota que dos clases o áreas de su código comparten el mismo valor PARA LA MISMA RAZÓN (lo que significa que no es mera coincidencia), indíqueles el mismo lugar.
Caso 2: para el caso 2, tiene razón: las leyes del "porcentaje" no cambiarán (siendo razonable, aquí), por lo que puede codificar en línea.
Caso 3: El tercer caso es donde piensas que la cosa podría cambiar pero no quieres / tienes tiempo para molestarte en cargar ResourceBundles o XML o lo que sea. En ese caso, use cualquier mecanismo de centralización que pueda (la odiada clase Singleton es buena) y continúe con eso hasta que realmente tenga que lidiar con el problema.
Sin embargo, el tercer caso es complicado: es extraordinariamente difícil internacionalizar una aplicación sin realmente hacerlo ... por lo que querrás codificar cosas y solo esperar que, cuando los chicos de i18n toquen, tu código no sea el peor: código de degustación :)
Editar: Permítanme mencionar que acabo de terminar un proyecto de refactorización en el que el desarrollador anterior había colocado las cadenas de conexión MySql en más de 100 lugares en el código (PHP). A veces estaban en mayúsculas, a veces en minúsculas, etc., por lo que eran difíciles de buscar y reemplazar (aunque Netbeans y PDT ayudaron mucho). Hay razones por las que lo hizo (un proyecto llamado POG básicamente fuerza esta estupidez), pero no hay nada que parezca menos un buen código que repetir lo mismo en un millón de lugares.
El texto para las condiciones debe estar en un archivo de recursos; para eso está ahí.
Los literales codificados deben aparecer en pruebas unitarias para los valores de prueba, a menos que haya tanta reutilización de un valor dentro de una única clase de prueba que una constante local sea útil.
Las pruebas unitarias son una descripción de los valores esperados sin abstracción ni redirección. Imagínese leyendo la prueba: quiere la información literalmente frente a usted.
La única vez que uso constantes para valores de prueba es cuando muchas pruebas repiten un valor (en sí mismo un poco sospechoso) y el valor puede estar sujeto a cambios.
Utilizo constantes para cosas como nombres de archivos de prueba para comparar.
No normalmente (son literales de codificación dura aceptables)
Otra forma de ver esto es cómo el uso de una buena convención de nomenclatura para las constantes utilizadas en lugar de los literales codificados proporciona documentación adicional en el programa.
Incluso si el número se usa solo una vez, aún puede ser difícil de reconocer e incluso puede ser difícil de encontrar para futuros cambios.
En mi humilde opinión, hacer que los programas sean más fáciles de leer debería ser algo natural para un profesional experimentado en software. Los números en bruto rara vez se comunican de manera significativa.
El tiempo adicional que lleva usar una constante bien llamada hará que el código sea legible (fácil de recordar para la mente) y útil para volver a minar en el futuro (reutilización del código).