python - procedimientos - ¿Por qué las variables globales son malvadas?
parametros por omision python (4)
Estaba intentando encontrar una buena fuente que explica por qué el uso de global
se considera una mala práctica en python (y en la programación en general). ¿Puede alguien señalarme uno o explicar aquí?
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 están perfectamente bien de usar. Es solo que en Python no hay diferencia sintáctica.
La razón por la que son malos es que permiten que las funciones se hayan ocultado (como en "no obvio" y "no declarado") y, por lo tanto, son difíciles de comprender. Además, esto puede conducir al código de Spaghetti .
Además, el uso limitado / controlado / consciente de los globales es aceptable, al igual que el estado local, es decir, las variables mutables, es aceptable en la programación funcional, ya sea por razones de rendimiento o simplicidad, o para el almacenamiento en memoria caché / memo.
Pero, por supuesto, su pregunta tiene muchas respuestas, por lo que su mejor opción es simplemente buscar en Google "por qué las variables globales son malas". Algunos ejemplos:
- http://c2.com/cgi/wiki?GlobalVariablesAreBad
- https://softwareengineering.stackexchange.com/questions/148108/why-is-global-state-so-evil
- ¿Son malas las variables globales?
Si quieres profundizar y descubrir por qué se tratan los efectos secundarios, y muchas otras cosas iluminadoras, debes aprender la Programación Funcional:
Sí, en teoría , los globales (y el "estado" en general) son malvados. En la práctica, si observa el directorio de paquetes de su python encontrará que la mayoría de los módulos comienzan con un montón de declaraciones globales. Obviamente, las personas no tienen ningún problema con ellos.
Específicamente para python, la visibilidad global se limita a un módulo, por lo tanto, no hay variables globales "verdaderas" que afecten a todo el programa, eso las hace menos dañinas. Otro punto: no hay const
, entonces cuando necesitas una constante tienes que usar un 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.
Son esenciales, la pantalla es 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 (erróneamente) estableció o borró? Dependiendo de la arquitectura, el análisis puede ser costoso y requerirse a menudo. Mientras lee la var global puede estar bien, la escritura en ella debe controlarse, por ejemplo, mediante un único hilo o clase threadsafe. Por lo tanto, los vars globales surgen 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 baja la cantidad de vars globales.
Una opinión personal sobre el tema es que tener variables globales utilizadas en una lógica de funciones significa que algún otro código puede alterar la lógica y el resultado esperado 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 entender dónde se está estableciendo la variable global, dónde se ha cambiado y qué esperar de esta variable global en oposición a una función aislada que su funcionalidad puede determinarse leyendo la definición de la función en sí misma.
(Probablemente) Violar la definición de la Función Pura
Creo que un código limpio y (casi) libre de errores debería tener las funciones que son lo más pura posible (ver funciones puras ). Una función pura es la que tiene las siguientes condiciones:
- 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 durante 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 está violando al menos uno de los anteriores, sino ambos, ya que un código externo probablemente puede causar resultados inesperados.
Otra definición clara de funciones puras: "función pura es una función que toma todas sus entradas como argumentos explícitos y produce todos sus resultados como resultados explícitos ". [1] Tener variables globales viola la idea de funciones puras, ya que una entrada y tal vez uno de los resultados (la variable global) no se da ni se devuelve explícitamente.
(Probablemente) Violación de la prueba de la unidad PRIMER principio
Además, si considera las pruebas unitarias y el PRIMER PRINCIPIO (pruebas físicas, pruebas independientes, repetible, validación y validación) probablemente viole 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 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 establecerse en una función Y primero) significa que para probar la función X de la unidad, primero debe ejecutar la función de prueba / ejecución Y.
Globales como constantes
Por otro lado, y como ya han mencionado otras personas, si la variable global se utiliza como una variable "constante" puede ser ligeramente mejor ya que el lenguaje no admite constantes. Sin embargo, siempre prefiero trabajar con clases y tener las "constantes" como miembro de la 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 deberían usarse. Pero si se están utilizando, los autores deberían considerar algunos principios (los mencionados anteriormente tal vez y otros principios de ingeniería de software y buenas prácticas) para un código más limpio y libre de errores.