Ci sono molte ragioni per cui i globi sono cattivi in OOP.
Se il numero o la dimensione degli oggetti che richiedono la condivisione è troppo grande per essere passati in modo efficiente nei parametri di funzione, di solito tutti raccomandano l' iniezione di dipendenza anziché un oggetto globale.
Tuttavia, nel caso in cui quasi tutti debbano conoscere una determinata struttura di dati, perché Dependency Injection è meglio di un oggetto globale?
Esempio (uno semplificato, per mostrare il punto in generale, senza approfondire troppo in una specifica applicazione)
Esiste un numero di veicoli virtuali che hanno un numero enorme di proprietà e stati, da tipo, nome, colore, velocità, posizione, ecc. Un numero di utenti può controllarli a distanza e un numero enorme di eventi (entrambi gli utenti- avviato e automatico) possono cambiare molti dei loro stati o proprietà.
La soluzione ingenua sarebbe quella di crearne un contenitore globale, come
vector<Vehicle> vehicles;
a cui è possibile accedere da qualsiasi luogo.
La soluzione più intuitiva di OOP sarebbe quella di avere il contenitore membro della classe che gestisce il ciclo di eventi principale e di essere istanziato nel suo costruttore. Ogni classe che ne ha bisogno ed è membro del thread principale, avrà accesso al contenitore tramite un puntatore nel proprio costruttore. Ad esempio, se un messaggio esterno arriva tramite una connessione di rete, subentra una classe (una per ogni connessione) che gestisce l'analisi e il parser avrà accesso al contenitore tramite un puntatore o un riferimento. Ora, se il messaggio analizzato provoca una modifica in un elemento del contenitore o richiede alcuni dati al di fuori di esso per eseguire un'azione, può essere gestito senza la necessità di lanciare migliaia di variabili attraverso segnali e slot (o peggio, memorizzandoli nel parser per essere successivamente recuperati da chi ha chiamato il parser). Naturalmente, tutte le classi che ricevono l'accesso al contenitore tramite iniezione di dipendenza, fanno parte dello stesso thread. Diversi thread non accederanno direttamente ad esso, ma faranno il loro lavoro e quindi invieranno segnali al thread principale, e gli slot nel thread principale aggiorneranno il contenitore.
Tuttavia, se la maggior parte delle classi avrà accesso al contenitore, cosa lo rende davvero diverso da un globale? Se così tante classi hanno bisogno dei dati nel contenitore, il "modo di iniezione di dipendenza" non è solo un globale mascherato?
Una risposta sarebbe la sicurezza del thread: anche se mi preoccupo di non abusare del container globale, forse un altro sviluppatore in futuro, sotto la pressione di una scadenza ravvicinata, utilizzerà comunque il container globale in un thread diverso, senza occuparmi di tutto i casi di collisione. Tuttavia, anche in caso di iniezione di dipendenza, si potrebbe dare un puntatore a qualcuno che gira in un altro thread, portando agli stessi problemi.