¿Por qué las variables globales son malas?
Estoy tratando de descubrir por qué el uso de global
se considera una mala práctica en Python (y en la programación en general). ¿Alguien puede explicar? También se agradecerían enlaces con más información.
Esto no tiene nada que ver con Python; Las variables globales son malas en cualquier lenguaje de programación.
Sin embargo, las constantes globales no son conceptualmente lo mismo que las variables globales ; Las constantes globales son perfectamente inofensivas. En Python la distinción entre los dos es puramente por convención: CONSTANTS_ARE_CAPITALIZED
y globals_are_not
.
La razón por la que las variables globales son malas es que permiten que las funciones tengan efectos secundarios ocultos (no obvios, sorprendentes, difíciles de detectar, difíciles de diagnosticar), lo que lleva a un aumento de la complejidad, lo que potencialmente conduce al código Spaghetti .
Sin embargo, el uso sensato del estado global es aceptable (al igual que el estado local y la mutabilidad) incluso en la programación funcional, ya sea para la optimización de algoritmos, la reducción de la complejidad, el almacenamiento en caché y la memorización, o la practicidad de portar estructuras que se originan en una base de código predominantemente imperativa.
Con todo, su pregunta puede responderse de muchas maneras, por lo que lo mejor que puede hacer es simplemente buscar en Google "¿por qué las variables globales son malas?". Algunos ejemplos:
- Las variables globales son malas - Wiki Wiki Web
- ¿Por qué el Estado Global es tan malvado? - Intercambio de pila de ingeniería de software
- ¿Son malas las variables globales?
Si quieres profundizar y descubrir por qué se tratan los efectos secundarios, y muchas otras cosas esclarecedoras, deberías aprender Programación Funcional:
- Efecto secundario (informática) - Wikipedia
- ¿Por qué los efectos secundarios se consideran malos en la programación funcional? - Intercambio de pila de ingeniería de software
- Programación funcional - Wikipedia
Sí, en teoría , los globales (y el "estado" en general) son malos. En la práctica, si observa el directorio de paquetes de Python, encontrará que la mayoría de los módulos comienzan con un montón de declaraciones globales. Evidentemente la gente no tiene ningún problema con ellos.
Específicamente para Python, la visibilidad de los globales se limita a un módulo, por lo tanto, no hay globales "verdaderos" que afecten a todo el programa, lo que los hace mucho menos dañinos. Otro punto: no hay const
, por lo que cuando necesitas una constante tienes que usar una global.
En mi práctica, si modifico un global en una función, siempre lo declaro con global
, incluso si técnicamente no es necesario, como en:
cache = {}
def foo(args):
global cache
cache[args] = ...
Esto hace que las manipulaciones globales sean más fáciles de rastrear.
Una opinión personal sobre el tema es que el uso de variables globales en la lógica de una función significa que algún otro código puede alterar la lógica y el resultado esperado de esa función, lo que dificultará mucho la depuración (especialmente en proyectos grandes) y dificultará las pruebas. también.
Además, si considera que otras personas leen su código (comunidad de código abierto, colegas, etc.), les resultará difícil comprender dónde se establece la variable global, dónde se ha modificado y qué esperar de esta variable global en lugar de a una función aislada que su funcionalidad se puede determinar leyendo la definición de la función misma.
(Probablemente) violando la definición de función pura
Creo que un código limpio y (casi) libre de errores debería tener funciones lo más puras posible (ver funciones puras ). Una función pura es aquella que tiene las siguientes condiciones:
- La función siempre evalúa el mismo valor de resultado dados los mismos valores de argumento . El valor del resultado de la función no puede depender de ninguna información oculta o estado que pueda cambiar mientras continúa la ejecución del programa o entre diferentes ejecuciones del programa, ni puede depender de ninguna entrada externa de dispositivos de E/S (generalmente, ver más abajo).
- La evaluación del resultado no causa ningún efecto secundario o salida semánticamente observable , como la mutación de objetos mutables o la salida a dispositivos de E/S.
Tener variables globales viola al menos uno de los puntos anteriores, si no ambos, ya que un código externo probablemente puede causar resultados inesperados.
Otra definición clara de funciones puras: "La función pura es una función que toma todas sus entradas como argumentos explícitos y produce todas sus salidas como resultados explícitos ". [1] . Tener variables globales viola la idea de funciones puras, ya que una entrada y tal vez una de las salidas (la variable global) no se proporciona ni devuelve explícitamente.
(Probablemente) violando el PRIMER principio de pruebas unitarias
Además, si considera las pruebas unitarias y el PRIMER principio ( pruebas rápidas , pruebas independientes , repetibles , autovalidantes y oportunas ) probablemente violará el principio de pruebas independientes (lo que significa que las pruebas no dependen de ellas). el uno del otro).
Tener una variable global (no siempre) pero en la mayoría de los casos (al menos de lo que he visto hasta ahora) es para preparar y pasar resultados a otras funciones. Esto también viola este principio. Si la variable global se ha utilizado de esa manera (es decir, la variable global utilizada en la función X debe configurarse primero en una función Y), significa que para realizar una prueba unitaria de la función X primero debe ejecutar la prueba/ejecutar la función Y.
Globales como constantes
Por otro lado y como ya han comentado otras personas, si la variable global se usa como variable "constante" puede ser ligeramente mejor ya que el lenguaje no soporta constantes. Sin embargo, siempre prefiero trabajar con clases y tener las "constantes" como miembros de la clase y no usar una variable global en absoluto. Si tiene un código que requiere que dos clases diferentes compartan una variable global, entonces probablemente necesite refactorizar su solución y hacer que sus clases sean independientes.
No creo que no se deban utilizar globales. Pero si se utilizan, los autores deberían considerar algunos principios (quizás los mencionados anteriormente y otros principios y buenas prácticas de ingeniería de software) para un código más limpio y casi libre de errores.
Son imprescindibles, siendo la pantalla un buen ejemplo. Sin embargo, en un entorno multiproceso o con muchos desarrolladores involucrados, en la práctica a menudo surge la pregunta: ¿quién lo configuró o borró (erróneamente)? Dependiendo de la arquitectura, el análisis puede ser costoso y necesario con frecuencia. Si bien leer la var global puede estar bien, la escritura en ella debe controlarse, por ejemplo, mediante un único subproceso o una clase segura para subprocesos. De ahí que las variables globales surjan el temor de los posibles altos costos de desarrollo por las consecuencias por las cuales ellos mismos se consideran malos. Por lo tanto, en general, es una buena práctica mantener bajo el número de variables globales.