¿Cuándo está bien usar una variable global?

22

Ok, entonces esta es una pregunta de defensa de los demonios realmente.

¿Cuándo están bien las variables globales y, si nunca, qué usaría como alternativa?

Un caso secundario interesante para esta pregunta, ¿en qué se diferencia un campo de clase estática pública de un campo global?

ocodo
fuente
55
Código completo , 2a edición, §13.3.
Jerry Coffin
1
Las aplicaciones multiproceso requieren variables globales.
aqua
44
@aqua Las aplicaciones multiproceso son donde las variables globales pueden ser más perjudiciales. Todos odian la compleja lógica de bloqueo.
luiscubal
1
@JerryCoffin Si publicar un enlace como respuesta sin citar el pasaje relevante es una mala práctica, entonces también lo es citar una sección de un libro sin citar el pasaje relevante. Especialmente así, ya que los libros no se pueden obtener de forma libre y fácil como lo son las páginas web.
Braden Best

Respuestas:

18

Hasta donde yo sé, un campo estático público es básicamente global dado que se puede llamar desde cualquier lugar con la excepción de que no obstruye el espacio de nombres.

La única vez que uso personalmente las variables 'globales' en mi código es en forma de campos públicos estáticos que son inmutables. En este caso, no hay necesidad de preocuparse por el valor que otras partes del programa están alterando y, por supuesto, es mucho mejor que tener una docena de variables con los mismos valores permanentes en cada clase.


fuente
2
Llamaría a un campo inmutable una constante .
aioobe
14

Personalmente, uso globales para la configuración en tiempo de ejecución: si una propiedad de configuración se carga al inicio de la aplicación, y solo cambia con poca frecuencia (y solo desde un lugar), es terrible y propenso a errores pasarla a todos los métodos que puedan necesitar usar en algún momento Es mejor usar algo que pueda ponerse al alcance desde cualquier lugar que necesite usarlo, ya que eso no abarrota y oscurece las firmas de métodos y los sitios de llamadas.

Luego.
fuente
¿Usarías un global puro para esto o un static / Singleton público?
ocodo
1
@Slomojo: Definitivamente no es un singleton. Dependiendo de la situación, ya sea estática en una clase de configuración o globales con un prefijo CONFIG_o CFG_.
Anon
+1 el único cambio que sugeriría es decir "... propenso a errores para pasarlo a cualquier otro método en cualquier otra clase". De lo contrario, se puede abarcar a la clase con lo que sea que sirva, creo que singleton.
Michael Durrant
8

Excluyendo los sistemas en tiempo real / embebidos, en realidad solo debe usar valores globales para valores constantes. Si siente que no puede resolver su problema sin ellos, probablemente esté haciendo algo mal.

Además, observe el patrón Singleton , ya que proporciona una mejor solución para los globales en aquellas situaciones en las que necesita algo para tener un punto de acceso global.

Davor Ždralo
fuente
8
Probablemente sugeriría evitar Singletons.
ocodo
No estoy sugiriendo que los singletons sean geniales, pero sigo pensando que superan mucho a las variables globales.
Davor Ždralo
Los valores constantes solo necesitan ser accesibles en el área / módulo que son relevantes. Una constante TIMES_TO_ITERATE_THROUGH_THIS_PARTICULAR_LOOPsolo es relevante en el archivo / clase / sección donde aparece 'este ciclo particular'.
Cthulhu
1
Los campos de un singleton son variables globales, por lo que no veo cómo hay alguna diferencia.
sleske
1
@Cthulhu déjame citarme a mí mismo: "en esas situaciones en las que necesitas algo para tener un punto de acceso global".
Davor Ždralo
6

El problema con las variables globales es que debe conocerlas en todas partes en su código. Sin embargo, una vez que haya decidido que necesita saber acerca de un global en particular, se perderá un poco más al usarlo en gran medida. Por lo tanto, mi opinión es que debe tener muy pocas variables globales, pero de las pocas que tiene, debe obtener el máximo kilometraje.

Para otro ejemplo de algo que siento de esta manera, mira el uso de mixins en Ruby.

btilly
fuente
¿Qué casos de uso de ejemplo sugeriría para estos usos de los globales?
ocodo
1
@Slomojo: Un ejemplo de globales que no me importa es el uso de @ARGV y $ _ en Perl. Un ejemplo que me importa es el uso de globales para pasar parámetros baratos a subrutinas.
btilly
5

Se trata de espacios de nombres.

Imagine por un momento que todos en el mundo tuvieran el mismo apellido. Que desastre.

(En la India, los sikhs tienen el mismo apellido: Singh - Echa un vistazo)

Christopher Mahan
fuente
66
Se utiliza a ser todo sobre los espacios de nombres, pero ahora se trata de la seguridad hilo.
dan04
66
@ dan04 Se trata de no tener un diseño horrible con acción espeluznante a distancia.
Tom Hawtin - tackline
2
@Tom: Tal vez podamos llamar a eso, irónico, "Programación cuántica"
Christopher Mahan
4

Versión corta: cuando facilita razonar sobre el programa. Por lo general, los casos son algún tipo de estado global o recurso estático que se usa ampliamente.

Versión larga: Tom Hawtin dijo "con una acción espeluznante a distancia" ... ese es exactamente el problema con los globales: tienes que saber dónde se está usando y cómo, o puedes conseguir algo realmente extraño y difícil de rastrear loco. Los locales no son más ni menos que una estrategia para reducir el alcance de lo que el programador necesita comprender para razonar sobre el programa.

Otro lado del problema de saber dónde se usan es que puede terminar con globals duplicados, en cuyo caso las cosas pueden ponerse realmente extrañas a medida que la mayoría de los programas obtienen y establecen var1 mientras que en un par de lugares se usa var2 para mantener La misma información. Particularmente cuando varias personas están trabajando en el mismo código. Los IDE pueden ser útiles para encontrar el uso que reduce el costo de los globales, pero no hacen nada por los duplicados.

Mientras más globales tenga, más difícil será hacer un seguimiento de lo que sucede con ellos. Deben ser pocos y distantes entre sí.

jmoreno
fuente
En última instancia, tener globales mutables es una muy mala idea. La única excepción decente es cuando se trabaja en huellas de hardware extremadamente estrechas, como con la programación integrada. Por lo menos, los candidatos a globales en la programación regular deben dividirse en miembros estáticos de clases o módulos, cualquier cosa que sea mutable también debe considerarse un caso especial, doblemente cuando se trabaja en un entorno de subprocesos múltiples. Uso de bloqueo / futuros / promesas o algún otro método de seguridad de hilo / transacción. - Como nadie más lo mencionó, vean el problema de los filósofos gastronómicos.
ocodo
1
Sin duda, los subprocesos pueden dificultar el trabajo de los glóbulos mutables, pero puede tener el mismo problema básico debido a los eventos. Estoy de acuerdo con la sugerencia de poner el dobladillo como miembros estáticos, iría más allá y diría que idealmente deberían ser miembros estáticos PRIVADOS.
jmoreno
3

Las dos trampas con globales y singletons son la capacidad de prueba y la capacidad de implementación.

Para las pruebas, he visto demasiados arneses de pruebas demasiado complejos solo para lidiar con vidas globalmente planificadas y únicas. Asegúrese de que dicho objeto tenga reglas claras y simples de inicio y desmontaje.

En cuanto a la capacidad de implementación, hay dos casos a considerar. En primer lugar, ¿cómo vivirá su objeto global? ¿Está en una biblioteca estática o dinámica? Si ese objeto global se reutiliza para un complemento, ¿obtendrá copias adicionales? En segundo lugar, ¿qué sucede cuando ese objeto global se coloca en una aplicación paralela? ¿Es seguro para subprocesos?

En general, creo que esas razones significan que los globales y los singletons se usan solo excepcionalmente.

smithco
fuente
2

El desarrollo de sistemas incrustados críticos generalmente implica el uso de variables globales.

Los tamaños de pila son pequeños, todo está estáticamente asignado ( malloc()está prohibido), las variables globales están ocultas desde fuera de la biblioteca a la que pertenecen.

Mouviciel
fuente
0

En una horrible base de código VB6 que abusa de los globales como si no hubiera un mañana, soy culpable de presentar uno nuevo:

Global CsExt As New TheAppBeingRewrittenInCSharpWhileVb6CodeIsStillBeingMaintained

Creo que es uno de los pocos casos de uso válidos para un objeto global.

Mathieu Guindon
fuente