¿Por qué son malas las variables globales? [cerrado]

120

Estoy tratando de averiguar por qué el uso de globalse 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.

LarsVegas
fuente
Votación para reabrir: edité la pregunta para cambiar el enfoque hacia las explicaciones y lejos de los recursos externos. (Supongo que por eso estaba cerrado, pero en caso de que sea algo que ver con ser una pregunta acerca de las malas prácticas, comparar estas otras preguntas sobre las malas prácticas que todavía están abiertos: eval, import *, la concatenación de cadenas , variablesid , sombras de atributos )
wjandrea

Respuestas:

156

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 las mismas 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_CAPITALIZEDy 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 en 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 optimización de algoritmos, complejidad reducida, almacenamiento en caché y memorización, o la practicidad de portar estructuras que se originan en una base de código predominantemente imperativa.

En general, su pregunta puede responderse de muchas maneras, por lo que su mejor opción es simplemente buscar en Google "por qué las variables globales son malas". Algunos ejemplos:

Si desea profundizar y descubrir por qué se tratan los efectos secundarios y muchas otras cosas esclarecedoras, debe aprender Programación funcional:

Erik Kaplun
fuente
35

Sí, en teoría , los globales (y el "estado" en general) son malvados. En la práctica, si busca en el directorio de paquetes de su 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 menos dañinos. Otro punto: no hay const, así 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 hay necesidad de eso, como en:

cache = {}

def foo(args):
    global cache

    cache[args] = ...

Esto hace que las manipulaciones globales sean más fáciles de rastrear.

georg
fuente
3
En muchos sentidos, un módulo en Python es similar a una clase singleton, y los globales del módulo son similares a las propiedades de la clase.
Corley Brigman
9
@CorleyBrigman: las clases singleton en realidad a menudo sufren los mismos problemas que normalmente se atribuyen a los globales :)
Erik Kaplun
4
La visibilidad de los módulos de Python no se limita a un módulo. Están disponibles en todo el intérprete, y (aquí está lo importante) los cambios allí afectan a todo el intérprete. No es como una cadena que crea instancias ... es como modificar todas las instancias de cadena. Olor a parches de mono.
graffic
2
La mayoría de los módulos no comienzan con la definición de globales, excepto las constantes. Los globales son malas variables de medios / estado global, no constantes.
BlackJack
2
Usar globales es una idea horrible, una de las razones podría ser la incapacidad de probar correctamente las funciones que actualizan algún diccionario arbitrario que existe "en algún lugar". En realidad, no se puede probar que una base de código con globales sea funcional.
Tomasz Sosiński
10

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 la salida esperada de esa función, lo que hará que la depuración sea muy difícil (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.), tendrán dificultades para tratar de comprender dónde se establece la variable global, dónde se ha cambiado y qué esperar de esta variable global en lugar de a una función aislada que su funcionalidad se puede determinar leyendo la propia definición de función.

(Probablemente) Violación de 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:

  1. La función siempre evalúa el mismo valor de resultado dado 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 se ejecuta el programa o entre diferentes ejecuciones del programa, ni puede depender de ninguna entrada externa de los dispositivos de E / S (por lo general, ver más abajo).
  2. 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 es violar al menos una de las anteriores, si no ambas, 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 da ni se devuelve explícitamente.

(Probablemente) Violación del principio de prueba unitaria PRIMER

Además de eso, si se tiene en cuenta la unidad de pruebas y el primer principio ( F pruebas AST, I pruebas ndependent, R epeatable, S Elf-Validar y T imely) probablemente violaría el principio independiente de prueba (lo que significa que las pruebas no dependen 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 preparar y pasar resultados a otras funciones. Esto también viola este principio. Si la variable global se ha utilizado de esa forma (es decir, la variable global utilizada en la función X debe configurarse primero en una función Y), significa que para probar unitariamente la función X, primero debe ejecutar la función de prueba / ejecución Y.

Globales como constantes

Por otro lado y como ya han comentado otras personas, si se utiliza la variable global como variable "constante" puede ser algo mejor ya que el lenguaje no soporta constantes. Sin embargo, siempre prefiero trabajar con clases y tener las "constantes" como miembro de la clase y no usar una variable global en absoluto. Si tiene un código que dos clases diferentes requieren para compartir 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 (los mencionados anteriormente, quizás, y otros principios y buenas prácticas de ingeniería de software) para un código más limpio y casi libre de errores.

Rafael
fuente
1
Me gusta el "global como constantes es un problema" ... porque si estás haciendo diseño OO ... realmente lo es. ¿Por qué alguien, excepto la clase IdCreator, necesita conocer el ID_LEN?
Erik Aronesty
3

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ó (erróneamente) o lo borró? Dependiendo de la arquitectura, el análisis puede resultar costoso y ser necesario con frecuencia. Si bien la lectura de la var global puede estar bien, la escritura debe ser controlada, por ejemplo, por un solo hilo o una clase segura para hilos. De ahí que las vars globales surjan el temor a los altos costos de desarrollo posibles por las consecuencias por las cuales ellos mismos son considerados malvados. Por lo tanto, en general, es una buena práctica mantener bajo el número de variables globales.

Horst Schlawutzke
fuente