¿Por qué las variables globales son malas?

Estaba tratando de encontrar una buena fuente que explique por qué el uso de global se considera una mala práctica en python (y en la progtwigción en general). ¿Alguien me puede señalar uno o explicar aquí?

Esto no tiene nada que ver con Python; Las variables globales son malas en cualquier lenguaje de progtwigción.

Sin embargo, las constantes globales no son conceptualmente lo mismo que las variables globales ; Las constantes globales son perfectamente inofensivas. Es solo que en Python no hay una diferencia forzada, solo por convención son CONSTANTS_CAPITALIZED y globals_are_not .

La razón por la que son malos es que permiten que las funciones tengan efectos secundarios ocultos (no obvios, sorprendentes y difíciles de detectar), lo que lleva a un aumento de la complejidad, lo que podría llevar al código Spaghetti .

Sin embargo, el uso sensato del estado global es aceptable (como lo es el estado local y la mutabilidad) incluso en la progtwigción funcional, ya sea para la optimización del algoritmo o la complejidad reducida, o para el almacenamiento en caché y la memoria, y por la practicidad de la lógica de portabilidad viene de una base de código 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 quieres profundizar más y descubrir por qué se tratan los efectos secundarios, y muchas otras cosas interesantes, deberías aprender la Progtwigción Funcional:

Sí, en teoría , los globales (y el “estado” en general) son malos. En la práctica, si observa el directorio de paquetes de su python, encontrará que la mayoría de los módulos allí comienzan con un montón de declaraciones globales. Obviamente, las personas no tienen 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 “verdaderos” globales que afecten a todo el progtwig, lo que los hace menos perjudiciales. Otro punto: no hay const , por lo que cuando necesitas una constante debes 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 de los globales sean más fáciles de rastrear.

Una opinión personal sobre el tema es que el uso de variables globales en una lógica de 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 grandes proyectos) y que la prueba sea más difícil también.

Además, si considera que otras personas que leen su código (comunidad de código abierto, colegas, etc.) tendrán dificultades para entender dónde se establece la variable global, dónde se ha cambiado y qué esperar de esta variable global como opuesta. a una función aislada que su funcionalidad se puede determinar leyendo la propia definición de la función.

(Probablemente) Violando la definición de la función pura

Creo que un código limpio y (casi) libre de errores debe tener funciones lo más puras posible (ver funciones puras ). Una función pura es la que tiene las siguientes condiciones:

  1. La función siempre evalúa el mismo valor de resultado dado el mismo valor de argumento (s) . El valor del resultado de la función no puede depender de ninguna información oculta o estado que pueda cambiar mientras avanza la ejecución del progtwig o entre diferentes ejecuciones del progtwig, ni puede depender de ninguna entrada externa de los dispositivos de E / S (generalmente, consulte más abajo).
  2. La evaluación del resultado no causa ningún efecto o efecto secundario observable semánticamente , como la mutación de objetos mutables o la salida a dispositivos de E / S.

Tener variables globales está violando al menos uno de los anteriores, si no ambos, ya que un código externo 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 o devuelve explícitamente.

(Probablemente) Violando las pruebas de la unidad del principio PRIMERO

Además, si considera la prueba unitaria y el principio FIRST (las pruebas F ast, las pruebas independientes, la repetición, la validación y la prueba de seguridad) probablemente violarán el principio de las pruebas independientes (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 los resultados a otras funciones. Esto viola este principio también. 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 probar la función X de la unidad debe ejecutar primero la función de prueba / ejecución Y.

Globales como constantes

Por otro lado, y como otras personas ya han mencionado, si la variable global se utiliza como una variable “constante” puede ser un poco mejor ya que el lenguaje no admite constantes. Sin embargo, siempre prefiero trabajar con clases y tener las “constantes” como miembro de una clase y no usar una variable global. Si tiene un código que requieren dos clases diferentes para compartir una variable global, entonces probablemente necesite refactorizar su solución y hacer que sus clases sean independientes.

No creo que los globales no deban ser usados. Pero si se usan, los autores deberían considerar algunos principios (los mencionados anteriormente y quizás otros principios de ingeniería de software y buenas prácticas) para un código más limpio y casi libre de errores.

Son esenciales, siendo la pantalla un buen ejemplo. Sin embargo, en un entorno de múltiples subprocesos o con muchos desarrolladores involucrados, en la práctica a menudo surge la pregunta: ¿quién la estableció o eliminó (por error)? Dependiendo de la architecture, el análisis puede ser costoso y ser requerido con frecuencia. Mientras que la lectura de la var global puede estar bien, escribir en ella debe estar controlada, por ejemplo, por un solo hilo o clase threadsafe. Por lo tanto, los vars globales surgen del temor a los altos costos de desarrollo posibles por las consecuencias por las cuales ellos mismos son considerados malos. Por lo tanto, en general, es una buena práctica mantener bajo el número de variables globales.