Le variabili globali sono sbagliate? [chiuso]


247

In C / C ++, le variabili globali sono cattive come pensa il mio professore?


17
Ti morderò nel caso in cui stia cercando di raccontare una barzelletta ... "quanto sono cattivi"?
Zach Scrivena,

13
Penso che questa domanda fosse piuttosto interessante! Lo sviluppo del software sta ancora affrontando le stesse vecchie insidie ​​sin dall'inizio e i programmatori spesso non sanno ancora che l'uso di variabili globali, goto, variabili con nome breve NON è il problema. Il codice errato viene scritto ogni giorno senza usarli. +1
Sylvain Rodrigue,

69
Come possiamo eventualmente rispondere? Non ci ha detto quanto il suo professore pensi che siano cattivi. :)
Steve Fallows,

9
@Juan Mendes Sono d'accordo al 100% con te! Il problema di cui parlavo è che molti sviluppatori sanno che non dovrebbero usare le variabili globali ma semplicemente NON sanno perché! E così ho visto molti software di grandi dimensioni in cui ogni singola funzione ha ricevuto la stessa megastruttura contenente +100 campi - Guarda mamma, nessuna variabile globale! Stesso problema delle cosiddette "buone pratiche": sono buone pratiche in ALCUNI contesti, non in tutti i contesti. Usandoli PUO 'creare codice non manutenibile. Saluti.
Sylvain Rodrigue,

3
Ci sono pochissimi buoni usi per le variabili globali. Un uso possibile, ma discutibile, sarebbe un oggetto "configurazione" globale, che legge all'avvio in un file di configurazione.
Siler,

Risposte:


257

Il problema con le variabili globali è che dal momento che ogni funzione ha accesso a queste, diventa sempre più difficile capire quali funzioni effettivamente leggono e scrivono queste variabili.

Per capire come funziona l'applicazione, devi praticamente prendere in considerazione ogni funzione che modifica lo stato globale. Questo può essere fatto, ma man mano che l'applicazione cresce, diventerà più difficile al punto da essere praticamente impossibile (o almeno una completa perdita di tempo).

Se non si fa affidamento su variabili globali, è possibile passare lo stato tra le diverse funzioni secondo necessità. In questo modo hai maggiori possibilità di capire cosa fa ogni funzione, poiché non è necessario tenere conto dello stato globale.


10
Questa risposta è davvero buona. Combinate questo con il 'minimizzare la portata variabile' risposta stackoverflow.com/questions/357187/...
bobobobo

17
Sostituisci "class" per "application" e "object state" con "global state" e fai esattamente lo stesso argomento per non usare variabili membro (aka campi) nelle classi. La vera risposta è usarli quando appropriato.
Ian Goldby,

2
Poche (forse stupide) domande: 1) Se vuoi sapere quali funzioni leggono e scrivono queste variabili, non potresti semplicemente usare la funzione "trova" in un editor per individuare i casi in cui i valori di queste variabili sono modificati? 2) "Questo può essere fatto, ... una completa perdita di tempo)." Puoi fare un esempio? 3) "Se non fai affidamento su variabili globali, ... non devi prendere in considerazione lo stato globale." Non capisco come sia un vantaggio. Forse un esempio di ciò avrebbe funzionato per me.
Andrei,

2
@bobobobo link non funzionante, possiamo ottenere uno screenshot da te, un utente 10k +?
noɥʇʎԀʎzɐɹƆ

3
@ noɥʇʎԀʎzɐɹƆ Ecco qua! i.imgur.com/RwRgJLZ.jpg
Mateen Ulhaq,

85

L'importante è ricordare l'obiettivo generale: la chiarezza

La regola "nessuna variabile globale" è lì perché la maggior parte delle volte, le variabili globali rendono meno chiaro il significato del codice.

Tuttavia, come molte regole, le persone ricordano la regola e non ciò che la regola doveva fare.

Ho visto programmi che sembrano raddoppiare la dimensione del codice passando un numero enorme di parametri semplicemente per evitare il male delle variabili globali. Alla fine, l'uso dei globali avrebbe reso il programma più chiaro a coloro che lo leggevano. Aderendo inconsapevolmente alla parola della regola, il programmatore originale aveva fallito l'intento della regola.

Quindi, sì, i globi sono spesso cattivi. Ma se senti che alla fine, l'intento del programmatore è reso più chiaro dall'uso delle variabili globali, allora vai avanti. Tuttavia, ricorda il calo di chiarezza che ne consegue automaticamente quando costringi qualcuno ad accedere a un secondo pezzo di codice (i globi) per capire come funziona il primo pezzo.


8
Suggerire di utilizzare una variabile globale anziché passare variabili è una ricetta per rendere il codice non riutilizzabile e non sicuro per il multi-threading
Juan Mendes,

16
Suggerire i globi nelle giuste circostanze è una ricetta per un codice più chiaro e con prestazioni più elevate. Il "passaggio" richiede un'allocazione dinamica costante della memoria dello stack, e ciò sarebbe sciocco per qualcosa che dovrebbe essere un globale, come un buffer globale per i dati dei socket in entrata. Ad esempio, se si dispone di una funzione che legge Winsock recv (), perché creare e deallocare costantemente questo buffer in ogni chiamata? Rendi il buffer un globale. Più thread non lo leggeranno comunque.
James,

Solo curioso, quale programma raddoppia la dimensione del codice passando parametri per evitare variabili globali? Nella mia esperienza, l'uso di variabili globali può risolvere i problemi di esposizione dei dati, ma di solito ci sono ulteriori logiche complesse che è necessario aggiungere per assicurarsi che queste variabili magiche si comportino correttamente.
user2167582,

3
Se qualcuno sta passando intorno a 100 variabili, allora non hanno imparato cosa sia un oggetto. L'uso del riferimento a questo oggetto è quindi nel peggiore dei casi passare attorno a un puntatore. Direi che la regola non è solo chiarezza, ma anche testabilità - e l'uso di un non globale tende a rendere le cose molto più facili da testare.
UKMonkey,

2
"Se qualcuno sta passando intorno a 100 variabili, allora non hanno imparato cosa sia un oggetto." D'accordo, ma non tutto il mondo è orientato agli oggetti. Il mio esempio personale di raddoppiare le dimensioni del codice è stato un grande programma Fortran, intorno al 1986. Come nuovo impiegato universitario, l'ho "migliorato", aggiungendo circa 30 parametri a ciascuna chiamata, eliminando tutti i globi. Quindi ho annullato il mio miglioramento quando ho capito cosa avevo fatto.
Tom West,

64

Il mio professore diceva qualcosa del genere: usare le variabili globali va bene se le usi correttamente. Non credo di essere mai riuscito a usarli correttamente, quindi li ho usati raramente.


25
Così vero. Sono come goto, se non sai quando usarli, non farlo mai.
David Holm,

5
Nella mia attuale azienda, usano staticmolto le variabili globali, il linguaggio è C. Essendo limitato a unità di traduzione relativamente piccole, iniziano a somigliare alle variabili di classe degli oggetti C ++.
Vorac,

1
Le variabili statiche @Vorac non sono variabili globali, sono variabili locali. Una variabile globale è una variabile disponibile ovunque nel programma (quindi "globale", duh). Da non confondere con le variabili dell'ambito del file , che sono variabili dichiarate al di fuori di qualsiasi funzione. Una variabile con ambito di file statico non è una variabile globale.
Lundin,

1
Per correggere me stesso, program lifetime, file scope variables. E diventano abbastanza globali quando si passa un puntatore alla variabile verso il mondo esterno (cosa impossibile con le variabili automatiche) ..
Vorac,

@Lundin Sono d'accordo, staticle variabili globali hanno portata limitata alla stessa unità di traduzione. Ma hanno una durata fino alla fine del programma come qualsiasi variabile globale.
akhilesh1988,

38

Le variabili globali dovrebbero essere utilizzate solo quando non si hanno alternative. E sì, questo include Singletons. Nel 90% dei casi, vengono introdotte variabili globali per risparmiare sui costi di passaggio di un parametro. Quindi si verifica il multithreading / test unit / codifica di manutenzione e si verifica un problema.

Quindi sì, nel 90% delle situazioni le variabili globali sono cattive. È improbabile che le eccezioni siano visibili da te negli anni del college. Un'eccezione che mi viene in mente è quella di occuparmi di oggetti intrinsecamente globali come le tabelle di interrupt. Cose come la connessione DB sembrano essere globali, ma non lo sono.


2
L'unica eccezione che ho visto negli anni del college sono state le funzioni di richiamata grafica. In XWindows, i callback del mouse non avevano argomenti di dati * vuoti che ti permettevano di aggirare blocchi arbitrari dello stato del programma ... (non che ciò finisca per essere MOLTO migliore di un globale comunque ...)
Brian Postow

10
+1 per "Cose come la connessione DB sembrano essere globali, ma non lo sono."
R .. GitHub smette di aiutare ICE il

1
Le tabelle di interruzione non sono globali, ce n'è una per processore - ma c'è anche un'istanza del programma per processore, quindi "annulla".
user253751

1
Qualcuno può illuminarmi sul perché le connessioni DB non sono globali (e quale sarebbe una buona alternativa)? Ho sempre pensato alle connessioni come uno dei rari casi in cui i globali erano accettabili.
Floella,

33

Il problema che le variabili globali creano per il programmatore è che espande la superficie di accoppiamento tra i componenti tra i vari componenti che utilizzano le variabili globali. Ciò significa che all'aumentare del numero di componenti che utilizzano una variabile globale, può aumentare anche la complessità delle interazioni. Questo maggiore accoppiamento di solito rende più facile iniettare i difetti nel sistema quando si apportano modifiche e rende anche i difetti più difficili da diagnosticare e correggere. Questo aumento dell'accoppiamento può anche ridurre il numero di opzioni disponibili quando si apportano modifiche e può aumentare lo sforzo richiesto per le modifiche, poiché spesso è necessario tracciare attraverso i vari moduli che utilizzano anche la variabile globale al fine di determinare le conseguenze delle modifiche.

Lo scopo dell'incapsulamento , che è sostanzialmente l'opposto dell'uso delle variabili globali, è di ridurre l'accoppiamento al fine di rendere la comprensione e la modifica della fonte più semplice e sicura e più facilmente testata. È molto più semplice utilizzare i test unitari quando non vengono utilizzate variabili globali.

Ad esempio, se si dispone di una semplice variabile intera globale che viene utilizzata come indicatore enumerato che vari componenti utilizzano come macchina a stati e quindi si effettua una modifica aggiungendo un nuovo stato per un nuovo componente, è quindi necessario tracciare tutti gli altri componenti per garantire che la modifica non li riguardi. Un esempio di un possibile problema potrebbe essere se switchun'istruzione per testare il valore della variabile globale di enumerazione con caseistruzioni per ciascuno dei valori correnti viene utilizzata in vari punti e succede che alcune delle switchistruzioni non hanno un defaultcaso da gestire un valore inaspettato per il globale all'improvviso hai un comportamento indefinito per quanto riguarda l'applicazione.

D'altra parte, l'uso di un'area di dati condivisa potrebbe essere utilizzata per contenere un insieme di parametri globali a cui viene fatto riferimento in tutta l'applicazione. Questo approccio viene spesso utilizzato con applicazioni integrate con ingombri di memoria ridotti.

Quando si utilizzano variabili globali in questo tipo di applicazioni, in genere la responsabilità di scrivere nell'area dati viene assegnata a un singolo componente e tutti gli altri componenti vedono l'area come conste letta da essa, senza mai scriverla. Adottare questo approccio limita i problemi che possono svilupparsi.

Alcuni problemi dovuti alle variabili globali che devono essere risolti

Quando l'origine di una variabile globale come una struttura viene modificata, tutto ciò che la utilizza deve essere ricompilato in modo che tutto ciò che utilizza la variabile conosca la sua dimensione reale e il modello di memoria.

Se più di un componente può modificare la variabile globale, è possibile riscontrare problemi con dati incoerenti nella variabile globale. Con un'applicazione multi-thread, sarà probabilmente necessario aggiungere un tipo di blocco o area critica per fornire un modo in modo che solo un thread alla volta possa modificare la variabile globale e quando un thread modifica la variabile, tutte le modifiche sono complete e impegnati prima che altri thread possano interrogare la variabile o modificarla.

Il debug di un'applicazione multi-thread che utilizza una variabile globale può essere più difficile. È possibile imbattersi in condizioni di gara che possono creare difetti difficili da replicare. Con diversi componenti che comunicano attraverso una variabile globale, specialmente in un'applicazione multi-thread, essere in grado di sapere quale componente sta cambiando la variabile quando e come sta cambiando la variabile può essere molto difficile da capire.

Lo scontro tra nomi può essere un problema con l'utilizzo di variabili globali. Una variabile locale che ha lo stesso nome di una variabile globale può nascondere la variabile globale. Si verifica anche il problema della convenzione di denominazione quando si utilizza il linguaggio di programmazione C. Una soluzione consiste nel dividere il sistema in sottosistemi con le variabili globali per un particolare sottosistema che iniziano tutte con le stesse prime tre lettere (vedere questo sulla risoluzione delle collisioni dello spazio dei nomi nell'obiettivo C ). C ++ fornisce spazi dei nomi e con C puoi aggirare il problema creando una struttura visibile a livello globale i cui membri sono vari elementi di dati e puntatori a dati e funzioni che sono forniti in un file come statici, quindi con visibilità del file solo in modo che possano essere referenziati solo attraverso la struttura visibile a livello globale.

In alcuni casi, l'intento originale dell'applicazione viene modificato in modo da modificare le variabili globali che hanno fornito lo stato di un singolo thread per consentire l'esecuzione di più thread duplicati. Un esempio potrebbe essere una semplice applicazione progettata per un singolo utente che utilizza variabili globali per stato e quindi una richiesta scende dalla direzione per aggiungere un'interfaccia REST per consentire alle applicazioni remote di agire come utenti virtuali. Quindi ora ti imbatti nel dover duplicare le variabili globali e le loro informazioni sullo stato in modo che il singolo utente e ciascuno degli utenti virtuali delle applicazioni remote abbiano il proprio set unico di variabili globali.

Utilizzando C ++ namespacee la structtecnica per C

Per il linguaggio di programmazione C ++ la namespacedirettiva è di grande aiuto nel ridurre le possibilità di uno scontro di nomi. namespaceinsieme a classe le varie parole chiave di accesso ( private, protectede public) forniscono la maggior parte degli strumenti necessari per incapsulare le variabili. Tuttavia, il linguaggio di programmazione C non fornisce questa direttiva. Questa pubblicazione di stackoverflow, Namespace in C , fornisce alcune tecniche per C.

Una tecnica utile è quella di avere una singola area dati residente in memoria definita come una structche abbia visibilità globale e all'interno di essa vi structsiano puntatori alle varie variabili e funzioni globali che vengono esposte. Alle definizioni effettive delle variabili globali viene assegnato l'ambito del file utilizzando la staticparola chiave. Se poi usi la constparola chiave per indicare quali sono di sola lettura, il compilatore può aiutarti a imporre l'accesso in sola lettura.

L'uso della structtecnica può anche incapsulare il globale in modo che diventi una specie di pacchetto o componente che sembra essere un globale. Avendo un componente di questo tipo diventa più facile gestire i cambiamenti che influenzano il globale e la funzionalità usando il globale.

Tuttavia, mentre namespaceo la structtecnica può aiutare a gestire gli scontri con i nomi, esistono ancora i problemi sottostanti dell'accoppiamento tra componenti che l'uso di globuli introduce soprattutto in una moderna applicazione multi-thread.


Questa è la migliore esaplanazione a mani basse, spiega tutto ciò che c'è da fare. Complimenti!
johndoevodka,

La tua lingua dovrebbe avere una regola di codice per impedirti di usare troppi accoppiamenti di classe.
Melbourne Developer

19

Sì, ma non devi sostenere il costo delle variabili globali finché non smetti di lavorare nel codice che utilizza le variabili globali e inizi a scrivere qualcos'altro che utilizza il codice che utilizza le variabili globali. Ma il costo è ancora lì.

In altre parole, è un costo indiretto a lungo termine e come tale la maggior parte delle persone pensa che non sia male.


19

Se è possibile, il tuo codice verrà sottoposto a un'attenta revisione durante un processo alla Corte Suprema , quindi assicurati di evitare le variabili globali.

Vedi questo articolo: Il codice dell'etilometro Buggy riflette l'importanza della revisione della fonte

Ci sono stati alcuni problemi con lo stile del codice identificati da entrambi gli studi. Una delle questioni stilistiche che riguardavano i revisori era l'uso estensivo di variabili globali non protette . Questa è considerata una forma scadente perché aumenta il rischio che lo stato del programma diventi incoerente o che i valori vengano inavvertitamente modificati o sovrascritti. I ricercatori hanno anche espresso preoccupazione per il fatto che la precisione decimale non viene mantenuta in modo coerente in tutto il codice.

Scommetto che quegli sviluppatori sperano di non aver usato variabili globali!


6
È stata la risata migliore che ho avuto da un po '. Un vero esempio del perché lo sviluppo di fonti chiuse a scopo di lucro è negativo e un buon esempio di variegati globali è andato storto!
Evil Spork,

Ciò che è stabilito qui è che le variabili globali sono viste con disprezzo. Non c'è nulla qui che dimostri che le variabili globali siano state un vero problema nel codice. SysTest ha affermato che, sebbene il codice "non sia stato scritto in modo coerente con le consuete migliori pratiche di progettazione del software", avrebbe comunque "prodotto in modo affidabile risultati di test coerenti". Quindi nessun danno da parte dei globali è stato effettivamente documentato. A mio modo di vedere, hanno appena stabilito che "Beh, questi sviluppatori non praticano la stessa religione codificante del resto del mondo tradizionale".
LionKimbro,

19

Le variabili globali sono cattive quanto le crei, non meno.

Se stai creando un programma completamente incapsulato, puoi usare i globi. È un "peccato" usare i globuli, ma i peccati di programmazione sono pessimi filosofici.

Se dai un'occhiata a L.in.oleum , vedrai una lingua le cui variabili sono esclusivamente globali. Non è scalabile perché tutte le librerie non hanno altra scelta che usare i globi.

Detto questo, se hai delle scelte e puoi ignorare la filosofia del programmatore, i globi non sono poi così male.

Né sono Goto, se li usi nel modo giusto.

Il grosso "cattivo" problema è che, se li usi in modo sbagliato, le persone urlano, il lander di Marte si schianta e il mondo esplode ... o qualcosa del genere.


17
Minimizzare i problemi legati all'uso dei globi a uno studente confuso non è una buona idea dell'IMO.
GEOCHET,

3
La filosofia del design non è oggettiva. Niente affatto. Solo perché alla maggior parte dei programmatori non piace qualcosa, non significa che non si dovrebbe mai esaminare quel qualcosa. È facile fare un uso generale dei globi senza la fine del mondo. Lascialo fare, lottare (sapendo che lo farebbe) e imparare come.
user54650,

7
Rich ha ragione. Questa risposta non dice nulla di ciò che è / non è male (o di come i globi possano essere usati in modo sicuro), solo che "non sono così male come tutto ciò. In quanto tale, minimizza solo i problemi.
jalf

4
Non sono d'accordo sul fatto che le variabili globali siano solo "cattive come le crei". Penso che uno dei problemi principali, specialmente in questo mondo multi-sviluppatore e interconnesso in cui la maggior parte di noi vive, lavora e programma, è che le variabili globali danno a qualcuno ELSE l'opportunità di rendere il codice errato.
Gariepy,

@gariepy fino a quando non saprò, anche se il discorso riguarda la statica: D ok, questo è quello ... e la mia app ha solo una o due variabili globali, quella viene fornita con Visual Studio, DEBUG e TRACE che normalmente non usiamo: D
DeadManN,

17

Risponderei a questa domanda con un'altra domanda: usi i singelton / I singelton sono cattivi?

Perché (quasi tutti) l'utilizzo di singelton è una variabile globale glorificata.


11
Stavo per pubblicare un commento intelligente che diceva "Sono cattivi solo se li chiami globali invece di singoli", ma mi hai battuto.
Smo

Sto ancora cercando di capire cosa diavolo sono i LOL.
GeoffreyF67,

1
@Geoffrey: ecco alcune buone descrizioni SO - stackoverflow.com/questions/11831/… e per alcuni buoni collegamenti: stackoverflow.com/questions/11831/…
Gavin Miller,

10
Per la cronaca, un singleton è una variabile globale con un glorificato Design Patterns (tm) (lol) per renderlo legittimo. È ugualmente male per tutti gli stessi motivi.
R .. GitHub smette di aiutare ICE il

@GavinMiller Stai dicendo che va bene se usi il simpleton ... ooops, eufemismo singleton?
Juan Mendes,

14

Il problema è meno che sono cattivi e più che sono pericolosi . Hanno il loro insieme di pro e contro e ci sono situazioni in cui sono il modo più efficiente o unico per raggiungere un determinato compito. Tuttavia, sono molto facili da usare in modo improprio, anche se si prendono provvedimenti per usarli sempre correttamente.

Alcuni professionisti:

  • È possibile accedere da qualsiasi funzione.
  • È possibile accedere da più thread.
  • Non uscirà mai dal campo di applicazione fino alla fine del programma.

Alcuni svantaggi:

  • È possibile accedervi da qualsiasi funzione, senza la necessità di essere esplicitamente trascinati come parametro e / o documentati.
  • Non thread-safe.
  • Inquina lo spazio dei nomi globale e potenzialmente causa collisioni di nomi, a meno che non vengano prese misure per impedirlo.

Nota, se vuoi, che i primi due pro e i primi due contro che ho elencato sono esattamente la stessa cosa, solo con una diversa formulazione. Questo perché le caratteristiche di una variabile globale possono davvero essere utili, ma le stesse caratteristiche che le rendono utili sono la fonte di tutti i loro problemi.

Alcune potenziali soluzioni ad alcuni dei problemi:

  • Valuta se sono effettivamente la soluzione migliore o più efficiente per il problema. Se ci sono eventuali soluzioni migliori, che invece utilizzare.
  • Inseriscili in uno spazio dei nomi [C ++] o singleton struct [C, C ++] con un nome univoco (un buon esempio sarebbe Globalso GlobalVars) oppure usa una convenzione di denominazione standardizzata per le variabili globali (come global_[name]o g_module_varNameStyle(come indicato da underscore_d nei commenti )). Ciò documenterà entrambi il loro utilizzo (è possibile trovare il codice che utilizza le variabili globali cercando lo spazio dei nomi / nome struttura) e minimizzare l'impatto sullo spazio dei nomi globale.
  • Per qualsiasi funzione che accede alle variabili globali, documenta esplicitamente quali variabili legge e quali scrive. Ciò faciliterà la risoluzione dei problemi.
  • Inseriscili nel loro file sorgente e dichiarali externnell'intestazione associata, in modo che il loro uso possa essere limitato alle unità di compilazione che devono accedervi. Se il tuo codice si basa su molte variabili globali, ma ogni unità di compilazione necessita solo dell'accesso a una manciata di esse, potresti prendere in considerazione l'ordinamento in più file di origine, quindi è più semplice limitare l'accesso di ciascun file alle variabili globali.
  • Imposta un meccanismo per bloccarli e sbloccarli e / o progettare il codice in modo che il minor numero di funzioni possibile debba effettivamente modificare le variabili globali. Leggerli è molto più sicuro che scriverli, anche se le gare di thread possono ancora causare problemi nei programmi multithread.
  • Fondamentalmente, minimizza l'accesso ad essi e massimizza l'unicità del nome. Volete evitare le collisioni di nomi e avere il minor numero possibile di funzioni che possono potenzialmente modificare una determinata variabile.

Che siano buoni o cattivi dipende da come li usi. La maggior parte tende a usarli male, quindi la diffidenza generale nei loro confronti. Se usati correttamente, possono essere un grande vantaggio; se usato male, tuttavia, possono e potranno tornare a mordere voi quando e come meno te lo aspetti.

Un buon modo per vederlo è che essi stessi non sono cattivi, ma consentono un cattivo design e possono moltiplicare gli effetti del cattivo design in modo esponenziale.


Anche se non hai intenzione di usarli, è meglio sapere come usarli in sicurezza e scegliere di non farlo, piuttosto che non usarli perché non sai come usarli in sicurezza. Se ti trovi mai in una situazione in cui devi mantenere un codice preesistente che si basa su variabili globali, potresti avere difficoltà se non sai come usarle correttamente.


1
+1 per il pragmatismo. Un singleton spesso aggiunge solo il boilerplate per trasformare l'istanza e il refactor in membri e si finisce con ... variabili globali, che si mascherano solo con un nome diverso. Perché preoccuparsi, se non quello di evitare il peccato di globali su un semplice tecnicismo? Gli spazi dei nomi sono belli come una barriera, ma trovo un semplice g_module_varNameStyleperfettamente leggibile. Per essere chiari, non sto usando i globali se posso evitarlo facilmente - parola chiave facilmente , perché da quando ho smesso di credere che debbano essere evitati - o piuttosto offuscati - a tutti i costi, mi sto divertendo molto di più, e il mio il codice è (shock!) molto più ordinato
underscore_d

@underscore_d È principalmente solo un modo per distinguere più facilmente tra variabili globali e variabili locali e anche per facilitare l'individuazione delle variabili globali durante la ricerca del codice, con l'intenzione di prevenire la confusione sul fatto che una variabile sia globale o locale / un parametro / un membro / ecc. Anche una convenzione di denominazione standard come la tua funziona, purché coerente. Modifica la mia risposta con l'idea della convenzione di denominazione standard, grazie.
Justin Time - Ripristina Monica il

1
"Per qualsiasi funzione ... documenta esplicitamente quali variabili" - ricorda che questa è una relazione transitiva. Se la funzione A chiama le funzioni B e C, allora legge e scrive le variabili scritte da entrambi (più quelle direttamente nel suo corpo)
Caleth,

11

Come qualcuno ha detto (sto parafrasando) in un altro thread "Regole come questa non dovrebbero essere infrante, fino a quando non capirai appieno le conseguenze di farlo."

Ci sono momenti in cui sono necessarie variabili globali, o almeno molto utili (Lavorare con richiamate definite dal sistema, ad esempio). D'altra parte, sono anche molto pericolosi per tutti i motivi che ti è stato detto.

Ci sono molti aspetti della programmazione che probabilmente dovrebbero essere lasciati agli esperti. A volte hai BISOGNO di un coltello molto affilato. Ma non puoi usarne uno finché non sei pronto ...


1
Sono d'accordo, se capisci le conseguenze, va bene infrangere le regole, ma se ti sorprendi a farlo spesso, stai facendo qualcosa di sbagliato
Juan Mendes,

9

Le variabili globali sono generalmente sbagliate, specialmente se altre persone lavorano sullo stesso codice e non vogliono spendere 20 minuti alla ricerca di tutti i luoghi a cui fa riferimento la variabile. E l'aggiunta di thread che modificano le variabili porta un nuovo livello di mal di testa.

Le costanti globali in uno spazio dei nomi anonimo utilizzato in una singola unità di traduzione sono eccellenti e onnipresenti nelle app e nelle librerie professionali. Ma se i dati sono mutabili e / o devono essere condivisi tra più TU, è possibile incapsularli, se non per motivi di progettazione, quindi per chiunque esegua il debug o lavori con il proprio codice.


9

L'uso di variabili globali è un po 'come spazzare lo sporco sotto un tappeto. È una soluzione rapida e molto più facile a breve termine rispetto a una padella per la polvere o un aspirapolvere per pulirla. Tuttavia, se finisci per spostare il tappeto più tardi, avrai un grande pasticcio a sorpresa sotto.


metafora pigra priva di contesto! = risposta
underscore_d

1
@underscore_d: Non sono d'accordo. Questa è una domanda di discussione, anche se non è etichettata come tale (probabilmente a causa della sua età), e quindi le risposte come questa sono perfettamente valide, e fa un punto che affronta la questione dei PO.
Gariepy,

7

Le variabili globali sono dannose, se ti consentono di manipolare aspetti di un programma che dovrebbero essere modificati solo localmente. In OOP i globi spesso sono in conflitto con l'idea di incapsulamento.


7

Penso che il tuo professore stia cercando di fermare una cattiva abitudine prima ancora che inizi.

Le variabili globali hanno il loro posto e come molte persone hanno detto sapere dove e quando usarle può essere complicato. Quindi penso piuttosto che entrare nel nocciolo del perché, come, quando e dove delle variabili globali il tuo professore ha deciso di vietare. Chissà, potrebbe annullarli in futuro.


7

Assolutamente no. Usandoli male però ... questo è male.

Rimuoverli senza ragione per il gusto di farlo è semplicemente ... insensato. A meno che tu non conosca i vantaggi e gli svantaggi, è meglio essere chiari e fare come ti è stato insegnato / appreso, ma non c'è nulla di implicitamente sbagliato nelle variabili globali. Quando capisci i pro e i contro, meglio prendere la tua decisione.


3
-1 Esistono numerose ragioni per mettere in guardia contro le variabili globali: la più grande per me è che dipendenze nascoste e globali rendono estremamente difficile testare il codice in qualsiasi modo prevedibile. A meno che non valuti la capacità di testare il tuo codice in modo automatizzato, suggerirei che le variabili globali non ti causeranno altro che dolore. E inoltre, in un programma ben strutturato ci sono sempre alternative.
jkp,

1
quello che stai dicendo è un'enorme generalizzazione eccessiva, un uso attento dello stato globale non impedisce i test automatizzati - in realtà quasi tutte le app hanno uno stato globale, sia che siano avvolte come istanze allocate dinamicamente di oggetti ben incapsulati o dati statici che sono totalmente esposte concettualmente non fa alcuna differenza, ci sono ancora dipendenze - si tratta solo di come sono codificate.
jheriko,

1
Esattamente. Non sono tanto "cattivi" quanto "facilmente fragili", in pratica. Se sai come usarli senza rompere nulla e quando usarli invece di un'alternativa, possono essere utili. Altrimenti ... non così tanto.
Justin Time - Ripristina Monica

4

Le variabili globali vanno bene nei piccoli programmi, ma orribili se usate allo stesso modo in quelli grandi.

Ciò significa che puoi facilmente prendere l'abitudine di usarli mentre impari. Questo è ciò che il tuo professore sta cercando di proteggerti.

Quando avrai più esperienza, sarà più facile imparare quando stanno bene.


4

No, non sono affatto male. È necessario esaminare il codice (macchina) prodotto dal compilatore per prendere questa decisione, a volte è molto peggio usare un locale piuttosto che un globale. Nota anche che mettere "statico" su una variabile locale sta praticamente diventando un globale (e crea altri brutti problemi che un vero globale risolverebbe). i "globi locali" sono particolarmente cattivi.

I globali ti danno anche un controllo pulito sull'utilizzo della memoria, qualcosa di molto più difficile da fare con la gente del posto. In questi giorni è importante solo in ambienti embedded in cui la memoria è piuttosto limitata. Qualcosa da sapere prima di supporre che embedded sia uguale agli altri ambienti e supporre che le regole di programmazione siano le stesse su tutta la linea.

È bene che tu metta in dubbio le regole che ti vengono insegnate, la maggior parte di esse non è per i motivi per cui ti viene detto. La lezione più importante però non è che questa è una regola da portare con te per sempre, ma questa è una regola richiesta per onorare per passare questa classe e andare avanti. Nella vita scoprirai che per la società XYZ avrai altre regole di programmazione che alla fine dovrai rispettare per ottenere uno stipendio. In entrambe le situazioni puoi discutere la regola, ma penso che avrai una fortuna molto migliore in un lavoro che a scuola. Sei solo un altro di molti studenti, il tuo posto verrà presto sostituito, i professori non lo faranno, in un posto di lavoro sei uno di una piccola squadra di giocatori che deve vedere questo prodotto fino alla fine e in quell'ambiente le regole sviluppate sono per il beneficio dei membri del team nonché del prodotto e dell'azienda, quindi se a tutti piacciono o se per quel particolare prodotto ci sono buone ragioni ingegneristiche per violare qualcosa che hai imparato al college o qualche libro sulla programmazione generica, allora vendi la tua idea al team e scrivila come un metodo valido se non preferito . Tutto è un gioco leale nel mondo reale.

Se segui tutte le regole di programmazione che ti sono state insegnate a scuola o nei libri, la tua carriera di programmatore sarà estremamente limitata. Probabilmente puoi sopravvivere e avere una carriera fruttuosa, ma l'ampiezza e la larghezza degli ambienti a tua disposizione saranno estremamente limitate. Se sai come e perché esiste la regola e puoi difenderla, va bene, se la tua sola ragione è "perché il mio insegnante ha detto così", beh, non è così buono.

Nota che argomenti come questo sono spesso discussi sul posto di lavoro e continueranno ad esserlo, man mano che i compilatori e i processori (e le lingue) si evolvono, così fanno questo tipo di regole e senza difendere la tua posizione e possibilmente ti viene insegnata una lezione da qualcuno con un'altra opinione che non vorrai andare avanti.

Nel frattempo, fai semplicemente quello che dice il più forte o porta il bastone più grande (fino a quando non sei tu quello che grida più forte e porta il bastone più grande).


4
È solo un altro modo di dire "nessuno è mai stato licenziato per aver acquistato IBM"?
Gordon Potter,

1
Un buon punto che per alcune applicazioni l'uso di variabili globali può effettivamente rendere il lavoro più semplice. In generale l'uso delle variabili globali è una fonte di problemi con percorsi nascosti di accoppiamento tra sezioni della fonte. Tuttavia, avere un'area di memoria condivisa a cui viene fatto riferimento come globale viene utilizzata per implementazioni numeriche come interfacce di dispositivi o forse una tabella di parametri globale contenente costanti di vario tipo o una tabella di salto.
Richard Chambers,

4

Vorrei discutere contro il punto sollevato in questa discussione che rende il multi-threading più difficile o impossibile di per sé. Le variabili globali sono stati condivisi, ma anche le alternative ai globi (ad esempio il passaggio di puntatori) potrebbero condividere lo stato. Il problema con il multi-threading è come utilizzare correttamente lo stato condiviso, non se tale stato è condiviso attraverso una variabile globale o qualcos'altro.

Il più delle volte quando fai multi-threading devi condividere qualcosa. In un modello produttore-consumatore, ad esempio, è possibile condividere alcune code thread-safe che contengono le unità di lavoro. E sei autorizzato a condividerlo perché quella struttura di dati è thread-safe. Il fatto che quella coda sia globale o meno è del tutto irrilevante quando si tratta di sicurezza dei thread.

La speranza implicita espressa in questo thread che trasformare un programma da single-thread a multi-thread sarà più facile quando non si usano i globi è ingenuo. Sì, i globi rendono più facile spararti al piede, ma ci sono molti modi per spararti.

Non sto sostenendo i globali, poiché gli altri punti sono ancora validi, il mio punto è semplicemente che il numero di thread in un programma non ha nulla a che fare con l'ambito variabile.


3

Sì, perché se lasci che vengano utilizzati da programmatori incompetenti (leggi il 90%, in particolare gli scienziati), finisci con oltre 600 variabili globali distribuite su oltre 20 file e un progetto di 12.000 linee in cui l'80% delle funzioni prende il vuoto, restituisce il vuoto e opera interamente sullo stato globale.

Diventa rapidamente impossibile capire cosa sta succedendo in qualsiasi momento a meno che tu non conosca l'intero progetto.


2

L'uso delle variabili globali dipende effettivamente dai requisiti. Il suo vantaggio è che, riduce il sovraccarico di passare ripetutamente i valori.

Ma il tuo professore ha ragione perché solleva problemi di sicurezza, quindi l'uso delle variabili globali dovrebbe essere evitato il più possibile. Le variabili globali creano anche problemi che a volte sono difficili da eseguire il debug .

Per esempio:-

Situazioni in cui i valori delle variabili vengono modificati in fase di esecuzione . In quel momento è difficile identificare quale parte del codice lo sta modificando e su quali condizioni.


2

Global è buono quando si tratta di configurazione . Quando vogliamo che la nostra configurazione / modifiche di avere un impatto globale sul tutto il progetto .

Quindi possiamo cambiare una configurazione e le modifiche sono dirette all'intero progetto . Ma devo avvertire che dovresti essere molto intelligente per usare i globi.


1

Prima o poi dovrai cambiare il modo in cui è impostata quella variabile o cosa succede quando si accede, oppure devi solo cercare dove è stata modificata.

È praticamente sempre meglio non avere variabili globali. Basta scrivere la diga get e impostare i metodi, ed essere ghiandola quando ne hai bisogno un giorno, settimana o mese dopo.


1

Di solito uso i globuli per valori che raramente vengono cambiati come singoli o puntatori a funzioni in una libreria caricata dinamicamente. L'uso di globuli mutabili in applicazioni multithread tende a causare bug difficili da rintracciare, quindi cerco di evitarlo come regola generale.

L'uso di un argomento globale invece di passare un argomento è spesso più veloce ma se stai scrivendo un'applicazione multithread, cosa che fai spesso al giorno d'oggi, in genere non funziona molto bene (puoi usare thread-statics ma il guadagno in termini di prestazioni è discutibile) .


1

Nelle applicazioni Web all'interno di un enterprize può essere utilizzato per conservare dati specifici di sessione / finestra / thread / utente sul server per motivi di ottimizzazione e per evitare la perdita di lavoro in cui la connessione è instabile. Come accennato, le condizioni di gara devono essere gestite. Usiamo una singola istanza di una classe per queste informazioni ed è gestita con cura.


1

Alla fine della giornata, il tuo programma o app può ancora funzionare ma è una questione di essere ordinato e avere una completa comprensione di ciò che sta succedendo. Se condividi un valore variabile tra tutte le funzioni, potrebbe essere difficile tracciare quale funzione sta modificando il valore (se la funzione lo fa) e rende più difficile il debug un milione di volte


0

la sicurezza è meno significa che chiunque può manipolare le variabili se sono dichiarate globali, per questo spiegherai questo esempio se hai un saldo come variabile globale nel tuo programma bancario, la funzione utente può manipolarla e anche un funzionario bancario può manipolare questo quindi c'è un problema. solo all'utente dovrebbe essere data la sola lettura e la funzione di prelievo, ma l'impiegato della banca può aggiungere l'importo quando l'utente dà personalmente i contanti al banco.questo è il modo in cui funziona


-1

In un'applicazione multi-thread, utilizzare le variabili locali al posto delle variabili globali per evitare una condizione di competizione.

Una condizione di competizione si verifica quando più thread accedono a una risorsa condivisa, con almeno un thread con accesso in scrittura ai dati. Quindi, il risultato del programma non è prevedibile e dipende dall'ordine degli accessi ai dati da parte di thread diversi.

Maggiori informazioni qui, https://software.intel.com/en-us/articles/use-intel-parallel-inspector-to-find-race-conditions-in-openmp-based-multithreaded-code


Per i posteri: questo è in parte corretto nella migliore delle ipotesi. Le "variabili locali" in questa risposta si riferiscono a filo variabili -Local, piuttosto che le variabili di ambito locale più comuni che il PO si riferisce. Gli effetti collaterali della modifica delle variabili globali in modo non sicuro sono molto diversi da quelli del cambiamento dello stato globale in modo non simultaneo.
Jules,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.