Estaba leyendo un artículo sobre malas prácticas de programación .
Mencionó
"Código YoYo" que convierte un valor en una representación diferente, luego lo convierte de nuevo a donde comenzó (por ejemplo: convertir un decimal en una cadena y luego volver a un decimal, o rellenar una cadena y luego recortarla)
No entiendo por qué el ejemplo particular que da es una mala manera de escribir programas. Me parece bien volver a convertir si la situación lo requiere para poder usar el valor.
¿Alguien puede explicar más sobre esto?
programming-practices
anti-patterns
usuario13107
fuente
fuente
"Roundabout code" that accomplishes in many instructions what could be done with far fewer (eg: rounding a number by converting a decimal into a formatted string, then converting the string back into a decimal)
.if the situation is so that they have to be used?
- ¿Qué situación sería esa?decimal myValue = decimal.Parse(dataReader["myColumn"].ToString())
es una manía mía.Respuestas:
Incluso si haces necesidad tanto la numérica y la representación de cadena de un número, que es mejor para convertir sólo una vez y también se aferran a su valor original, en lugar de convertir de nuevo cada vez que necesite uno o el otro.
El principio es, como siempre, que el código que no existe no puede tener defectos sutiles , mientras que el código que existe a menudo sí. Eso puede sonar paranoico, pero la experiencia nos enseña que es apropiado. Si te acercas a la programación con una leve ansiedad permanente de "No soy realmente lo suficientemente inteligente como para entender este complejo sistema", estás en el camino correcto.
fuente
Es malo por tres razones principales:
Sospecho que la razón 1 es la razón por la que su fuente estaba pensando en función del contexto en el que se mencionó.
fuente
Me gustaría reformular la descripción como "código que convierte un tipo a una representación diferente con el propósito de hacer algo que podría haber hecho igual de bien o mejor en el original y luego se convierte de nuevo. Hay muchas situaciones en las que convierten algo a una tipo diferente, actuando sobre ella, y convertir de nuevo es totalmente apropiado y el fracaso para hacerlo daría lugar a un comportamiento incorrecto.
Como un ejemplo donde la conversión es bueno:
Uno tiene cuatro
float
valores de señales arbitrarias cuyas magnitudes pueden diferir en un factor de hasta 1000, y uno tiene que calcular la suma a dentro de 0,625 unidades en el último lugar. La conversión de los cuatro valores quedouble
, calculando la suma, y la conversión de la parte posterior resultado afloat
será mucho más eficiente que sería cualquier enfoque usandofloat
solo.valores de coma flotante son en el mejor de una precisión de 0,5 unidades en el último lugar (ULP). En este ejemplo se requeriría que el peor de los casos el error de redondeo en no más del 25% por encima óptima peor caso de error. El uso de un doble producirá un valor que será preciso dentro de 0,5001 ULP. Mientras que un requisito ULP 0.625 puede parecer ideado, tales requisitos son a menudo importantes en los algoritmos de aproximación sucesiva. se especifica con más fuerza la cota de error, menor es el requisito iteración peor de los casos.
Como un ejemplo donde la conversión es malo:
Uno tiene un número de coma flotante, y desea dar salida a una cadena que representará su valor de forma única. Un método consiste en convertir el número en una cadena con un cierto número de dígitos, tratar de convertirlo de nuevo, y ver si los Resultados de los partidos.
Pero este es realmente un enfoque pobre. Si una cadena decimal representa un valor que se encuentra casi exactamente en el punto medio entre dos valores de coma flotante, que es bastante caro para un método de cadena-a-flotador para garantizar que siempre va a producir cuanto más
float
valor, y muchos de estos métodos de conversión don No mantenga esa garantía (entre otras cosas, hacerlo requeriría en algunos casos leer todos los dígitos de un número, incluso si tenía miles de millones de dígitos).Es mucho más barato que un método garantice que siempre devolverá un valor que esté dentro de 0.5625 unidades en el último lugar (ULP) del valor representado. Una rutina de formato de decimal a cadena "reversible" robusta debe calcular qué tan lejos está el valor de salida del valor correcto y continuar emitiendo dígitos hasta que el resultado esté dentro de 0.375 (ULP) si no 0.25 (ULP). De lo contrario, puede generar una cadena que algunos métodos de conversión procesarán correctamente, pero otros métodos de conversión no.
A veces es mejor generar un dígito que podría no ser "necesario" que generar un valor que podría ser malinterpretado. La parte clave es que la decisión de cuántos dígitos deben emitirse debe basarse en cálculos numéricos relacionados con el proceso de salida, en lugar del resultado del intento de un método en particular de convertir la cadena de nuevo en un número.
fuente
Varias razones
Es inútil y añade complejidad - tanto en la cantidad de código para escribir y mantener, y necesitaba la cantidad de tiempo de CPU
Puede perder precisión o peor, corromper el valor por completo
Pierde memoria (potencialmente, dependiendo del idioma) a medida que termina almacenando más representaciones de un número que necesita
Una buena práctica es sólo para mantener la primera representación, lo más exacta posible, para cualquier dato que recibe. Realice los cálculos con estos datos y solo conviértalos si necesita generarlos o mostrarlos en un formato más fácil de leer.
fuente
¿Por qué? Porque incluso los mejores de nosotros podemos cometer errores.
Mire lo que sucedió cuando Microsoft intentó implementar un formato de "ida y vuelta" específicamente para asegurarse de que las conversiones de cadena flotante <-> fueran seguras: https://stackoverflow.com/q/24299692/541686
fuente
Cuando estaba en la escuela (y después de la escuela en ingeniería eléctrica) nos enseñaron a dividir después de multiplicar. División a menudo muchos dígitos y se redondean. Multiplicar después de la división multiplica el error de división.
Las conversiones de tipos son las mismas, corre el riesgo de perder datos. CInt (1.3) = 1.
En mi lenguaje, Basic, solo hacemos conversiones de tipo (un programa VB6 pasa el 90% de su tiempo haciendo conversión ANSI / Unicode, para todas las llamadas API que realiza el tiempo de ejecución).
La conversión de tipos está implícita en todo lo que hacemos.
La cadena "5" se imprime desde el literal numérico.
El literal de cadena Unicode se convierte en una cadena ANSI y se envía a SetWindowsTextA por el paquete de formularios.
Incluso esto funciona en básico
Soy un programador de variantes en estos días, ni siquiera pienso en el tipo. Solo confío en las conversiones automáticas.
De todos modos mis 3 manías son
Asignación de literales de cadena a variables para usarlos (desperdicia memoria y ralentiza)
Funciones sin sentido cuando el código podría estar en línea (y el compilador probablemente deshacerá su función y la alineará de todos modos)
Establecer todos los objetos en nada como las últimas líneas antes de una función final o final del programa.
y un cuarto para programas cortos
Atenúa sin sentido sus 3 variables en un programa de 5 líneas.
fuente