Como desarrollador de software experimentado, he aprendido a evitar las cadenas mágicas.
Mi problema es que hace tanto tiempo que no los uso, que he olvidado la mayoría de las razones. Como resultado, tengo problemas para explicar por qué son un problema para mis colegas menos experimentados.
¿Qué razones objetivas hay para evitarlos? ¿Qué problemas causan?
anti-patterns
Kramii
fuente
fuente
Respuestas:
En un lenguaje que compila, el valor de una cadena mágica no se verifica en el momento de la compilación . Si la cadena debe coincidir con un patrón en particular, debe ejecutar el programa para garantizar que se ajuste a ese patrón. Si usó algo como una enumeración, el valor es al menos válido en tiempo de compilación, incluso si puede ser el valor incorrecto.
Si una cadena mágica se escribe en varios lugares , debe cambiarlos todos sin ningún tipo de seguridad (como un error en tiempo de compilación). Sin embargo, esto puede contrarrestarse declarándolo solo en un lugar y reutilizando la variable.
Los errores tipográficos pueden convertirse en errores graves. Si tienes una función:
y alguien escribe accidentalmente:
Esto es peor cuanto más rara o compleja sea la cadena, especialmente si tiene programadores que no están familiarizados con el idioma nativo del proyecto.
Las cadenas mágicas rara vez se documentan por sí mismas. Si ve una cadena, eso no le dice nada de qué otra cosa podría / debería ser la cadena. Probablemente tendrá que investigar la implementación para asegurarse de haber elegido la cadena correcta.
Ese tipo de implementación tiene fugas , ya que necesita documentación externa o acceso al código para comprender lo que debe escribirse, especialmente porque debe ser perfecto (como en el punto 3).
Además de las funciones de "buscar cadena" en IDEs, hay una pequeña cantidad de herramientas que admiten el patrón.
Por coincidencia, puedes usar la misma cuerda mágica en dos lugares, cuando en realidad son cosas diferentes, por lo que si hiciste Buscar y reemplazar y cambiaste ambas, una de ellas podría romperse mientras la otra funcionaba.
fuente
La cumbre de lo que las otras respuestas han captado no es que los "valores mágicos" sean malos, sino que deberían ser:
Lo que típicamente distingue las "constantes" aceptables de los "valores mágicos" es una violación de una o más de estas reglas.
Bien usadas, las constantes simplemente nos permiten expresar ciertos axiomas de nuestro código.
Lo que me lleva a un punto final, que un uso excesivo de constantes (y, por lo tanto, un número excesivo de supuestos o restricciones expresados en términos de valores), incluso si cumple con los criterios anteriores (pero especialmente si se desvía de ellos), puede implicar que la solución que se está ideando no es lo suficientemente general o bien estructurada (y, por lo tanto, ya no estamos hablando de los pros y los contras de las constantes, sino de los pros y los contras de un código bien estructurado).
Los lenguajes de alto nivel tienen construcciones para patrones en lenguajes de nivel inferior que tendrían que emplear constantes. Los mismos patrones también pueden usarse en el lenguaje de nivel superior, pero no deberían serlo.
Pero ese puede ser un juicio experto basado en una impresión de todas las circunstancias y cómo debería ser una solución, y exactamente cómo se justificará ese juicio dependerá en gran medida del contexto. De hecho, puede no ser justificable en términos de ningún principio general, excepto afirmar "¡Soy lo suficientemente mayor como para haber visto este tipo de trabajo, con el que estoy familiarizado, hecho mejor"!
EDITAR: después de haber aceptado una edición, rechazado otra, y ahora haber realizado mi propia edición, ¿puedo considerar ahora el estilo de formato y puntuación de mi lista de reglas para resolver de una vez por todas jaja!
fuente
value / 2
, en lugar de quevalue / VALUE_DIVISOR
este último se defina como en2
otro lugar. Si pretendía generalizar un método que maneja CSV, probablemente desee que el separador se pase como un parámetro y no se defina como una constante. Pero todo es una cuestión de juicio en el contexto: el ejemplo de @ WGroleauSPEED_OF_LIGHT
es algo que querría nombrar explícitamente, pero no todos los literales necesitan esto.fuente
Ejemplo de la vida real: estoy trabajando con un sistema de terceros en el que las "entidades" se almacenan con "campos". Básicamente un sistema EAV . Como es bastante fácil agregar otro campo, obtienes acceso a uno usando el nombre del campo como cadena:
(tenga en cuenta la cadena mágica "ProductName")
Esto puede conducir a varios problemas:
Entonces, mi solución para esto fue generar constantes para estos nombres, organizados por tipo de entidad. Entonces ahora puedo usar:
Todavía es una cadena constante y se compila exactamente al mismo binario, pero tiene varias ventajas:
Siguiente en mi lista: esconder estas constantes detrás de clases generadas fuertemente tipadas, entonces también el tipo de datos está asegurado.
fuente
nameField = myEntity.ProductName;
.Las cuerdas mágicas no siempre son malas , por lo que esta podría ser la razón por la que no se te ocurre una razón general para evitarlas. (Por "cadena mágica" supongo que se refiere a la cadena literal como parte de una expresión, y no se define como una constante).
En algunos casos particulares, se deben evitar las cuerdas mágicas:
Pero en algunos casos, las "cuerdas mágicas" están bien. Digamos que tiene un analizador simple:
Realmente no hay magia aquí, y ninguno de los problemas descritos anteriormente se aplica. No habría ningún beneficio en mi humilde opinión para definir,
string Plus="+"
etc. Mantenlo simple.fuente
if (dx != 0) { grad = dy/dx; }
."+"
y"-"
conTOKEN_PLUS
yTOKEN_MINUS
. ¡Cada vez que lo leía, sentía que era más difícil de leer y depurar por eso! Definitivamente un lugar donde estoy de acuerdo en que usar cadenas simples es mejor.Para agregar a las respuestas existentes:
Internacionalización (i18n)
Si el texto que se mostrará en la pantalla está codificado y oculto dentro de capas de funciones, tendrá dificultades para proporcionar traducciones de ese texto a otros idiomas.
Algunos entornos de desarrollo (por ejemplo, Qt) manejan las traducciones mediante la búsqueda de una cadena de texto del idioma base al idioma traducido. Las cadenas mágicas generalmente pueden sobrevivir a esto, hasta que decida que desea usar el mismo texto en otro lugar y obtenga un error tipográfico. Incluso entonces, es muy difícil encontrar qué cadenas mágicas deben traducirse cuando desea agregar soporte para otro idioma.
Algunos entornos de desarrollo (por ejemplo, MS Visual Studio) adoptan otro enfoque y requieren que todas las cadenas traducidas se mantengan dentro de una base de datos de recursos y se vuelvan a leer para el entorno local actual mediante la ID única de esa cadena. En este caso, su aplicación con cadenas mágicas simplemente no se puede traducir a otro idioma sin una revisión importante. El desarrollo eficiente requiere que todas las cadenas de texto se ingresen en la base de datos de recursos y se les proporcione una identificación única cuando se escribe el código por primera vez, y posteriormente es relativamente fácil. Intentar rellenar esto después del hecho generalmente requerirá un esfuerzo muy grande (¡y sí, he estado allí!), Así que es mucho mejor hacer las cosas bien en primer lugar.
fuente
Esto no es una prioridad para todos, pero si alguna vez desea poder calcular las métricas de acoplamiento / cohesión en su código de manera automatizada, las cadenas mágicas lo hacen casi imposible. Una cadena en un lugar se referirá a una clase, método o función en otro lugar, y no existe una manera fácil y automática de determinar que la cadena está acoplada a la clase / método / función simplemente analizando el código. Solo el marco subyacente (angular, p. Ej.) Puede determinar que hay un enlace, y solo puede hacerlo en tiempo de ejecución. Para obtener la información de acoplamiento usted mismo, su analizador tendría que saber todo sobre el marco que estaba utilizando, más allá del idioma base en el que está codificando.
Pero, de nuevo, esto no es algo que a muchos desarrolladores les importe.
fuente