¿Cambiar el tipo de una variable a la mitad de un procedimiento en un estilo de lenguaje de tipo dinámico es malo?

8

En Python (y ocasionalmente PHP) donde las variables no tienen tipos fijos, frecuentemente realizaré 'transformaciones de tipo' en una variable a medio camino a través de la lógica de mi código. No estoy hablando (necesariamente) de conversiones simples, sino de funciones que cambian el tipo de una variable y la dejan básicamente representando el mismo valor o datos.

Por ejemplo, podría escribir un código como este al hacer una solicitud web, utilizando la responsevariable para almacenar un objeto addurlinfo, luego el contenido de la cadena de ese objeto y el diccionario devuelto al analizar la cadena como JSON:

response = urlopen(some_url)
assert response.info().type == 'application/json'

response = response.read()
logger.debug('Received following JSON response: ' + response)

response = json.loads(response)
do_something(response)

(Bien, es un ejemplo un poco artificial, pero creo que demuestra bien la idea). Mi sensación es que esto es mejor que usar tres nombres de variables separados porque a) transmite que la responsevariable contiene básicamente la misma información, simplemente 'transformada' en un tipo diferente, yb) transmite que los objetos anteriores no van a se necesitará más abajo en la función, ya que al reasignar su variable, he dejado de estar disponible para su posterior código.

La compensación, supongo, es que el lector podría confundirse acerca de qué tipo es la variable en un momento dado.

¿Es este un mal estilo, y debería usar tres variables diferentes en el ejemplo anterior en lugar de reasignar a una? Además, ¿es esta práctica estándar en lenguajes de tipo dinámico, o no? No he visto suficiente código de otras personas para saber.

Mark Amery
fuente

Respuestas:

9

Me arriesgaré y diré: No, esta es una idea terrible.

Es solo un caso especial de reutilización de una variable, lo cual es una mala idea, principalmente porque dificulta la comprensión de lo que contiene una variable en un punto dado del flujo del programa. Ver, por ejemplo, ¿debería reutilizar variables?

Acerca de sus puntos: Los puntos que plantea son válidos, es solo que reutilizar la variable no es una buena solución :-).

a) transmite que la variable de respuesta contiene básicamente la misma información, simplemente 'transformada' en un tipo diferente

Proporcionar esta información es una buena idea. Sin embargo, no hagas esto usando la misma variable, porque entonces oscureces el hecho de que la información se transformó. En cambio, use nombres con un prefijo / prefijo común. En tu ejemplo:

rawResponse = urlopen(some_url)
[...]    
jsonResponse = response.read()
[...]    
responseData = json.loads(response)
[...]

Esto deja en claro que las variables están estrechamente relacionadas, pero también que no contienen los mismos datos.

b) transmite que los objetos anteriores no serán necesarios más adelante en la función, ya que al reasignar su variable, los he dejado no disponibles para el código posterior.

Nuevamente, comunicar esto "ya no es necesario" es bueno, pero no lo haga reutilizando la variable: la asignación de reutilización generalmente será difícil de ver, por lo que solo confunde al lector.

Más bien, si una variable vive mucho tiempo después de su último uso, eso es una indicación de que el método / función es demasiado largo. Divida la parte con las variables de corta duración en una subfunción; eso hace que el código sea más fácil de leer y limita la vida útil de la variable.

Nota: Por lo general, incluso voy un paso más allá de no reutilizar variables, e intento incluso asignar solo un valor una vez (es decir, nunca cambiar el valor, hacerlo inmutable). Esta es una idea principalmente de lenguajes funcionales, pero descubrí que puede hacer que el código sea mucho más claro. Por supuesto, en lenguajes no funcionales, a veces necesita cambiar una variable (por ejemplo, una variable de bucle), pero una vez que comience a buscar, verá que en la mayoría de los casos una variable "fresca" hace que sea más legible y menos código propenso a errores.

sleske
fuente
6

Sé que estás leyendo desde una URL en tu ejemplo, pero si intentaste lo mismo con un archivo, no podrías cerrar el archivo porque la respuesta ya no apunta al archivo, ahora tiene una picadura que recuperaste del archivo

Ese es el gran peligro, puede olvidar qué valor tiene porque cambia durante la vida del programa o módulo. Será confuso para alguien que lea su código porque nunca sabrá qué tipo de valor contiene.

Estos son los bichos divertidos que intentan y aplastan.

mhoran_psprep
fuente
4

En general, diría que sí, es un mal estilo, pero que hay casos en que es necesario y útil reutilizar una variable; Solo recomiendo evitar el uso casual y perezoso.

El problema con su ejemplo no se debe a la tipificación dinámica, sino a que usa la misma variable para referirse a tres cosas diferentes. Este código es menos claro para mí porque cuando lo leo, tengo que pensar mucho más para entender a qué se responserefiere.

Podría hacer algo igualmente desagradable en un lenguaje de tipo estático como Java (con la restricción de que las diferentes cosas están relacionadas a través de una jerarquía de tipos). El punto clave es que usar una sola variable para apuntar a diferentes objetos puede ser confuso, independientemente del sistema de tipos.


fuente
Esto parece una objeción razonable, y creo que intentaré eliminar este tipo de estilo de mi código. Seguimiento: ¿cómo nombraría diferentes variables que conceptualmente se refieren a la misma cosa, pero con diferentes tipos? La notación húngara es un poco feo, y posterior tipos (como tener response_addurlinfo, response_str, response_dict) son más feo todavía. ¿Qué haces?
Mark Amery
@ MarkAmery Creo que la clave es que las variables no se refieren conceptualmente a lo mismo. El primero es solo una respuesta del servidor que puede ser un error, el segundo es una cadena de texto que puede no ser json válida, y el tercero es una estructura de datos. Hay más semántica que solo una respuesta y un tipo. En mi experiencia, un buen nombre variable es muy difícil, pero generalmente vale la pena. Lo siento, no puedo ser más concreto!