2012-08-14 20 views
5

So che le variabili globali sono negative e dovrebbero essere evitate il più possibile. Tuttavia, quando si scrivono programmi paralleli con MPI, ad esempio, alcune variabili vengono inizializzate solo una volta e mai modificate (numero di questa attività, numero totale di attività, ecc.). È ancora considerato una cattiva pratica avere queste variabili come globali? Dal momento che hai praticamente bisogno di accedere a queste variabili tutto il tempo, sembra sciocco creare una classe per loro in main e passare un puntatore ad esso al 99% di tutte le funzioni del programma. Il mio approccio finora è stato quello di nasconderli in uno spazio dei nomi mpi_glob (per il caso del C++, suppongo che non mi preoccuperei di inserirli in una struttura in C per emulare uno spazio dei nomi). Suppongo che la domanda valga anche per altre variabili set-only-once come un sistema di unità, ecc.Variabili globali e MPI

risposta

5

Il motivo per cui le variabili globali "sono errate" è che introducono l'accoppiamento tra file di origine separati che possono essere difficili da identificare e tracciare. In particolare, se una variabile globale ha uno stato imprevisto in qualche punto del programma, può essere difficile capire dove è stata modificata.

Sostituire le variabili globali con le variabili locali che vengono passate facendo riferimento a ogni funzione del programma non elimina il problema. In termini di progettazione, si tratta di "dati tramp", cioè di dati che vagano anche dove non è necessario.

Ora, il punto qui è che, come suggerite, i dati inizializzati una volta e mai modificati non hanno i problemi che rendono le variabili globali "cattive". Poiché il problema non esiste, la soluzione non è necessaria.

0

Nessuna regola dovrebbe essere seguita su un precipizio e le specifiche dipendono interamente dal tipo di programma che si sta scrivendo.

Se il tuo programma è relativamente piccolo (o sei l'unico a scrivere/mantenerlo), allora probabilmente è meglio lasciare le variabili "globali" in uno spazio dei nomi speciale. Almeno in questo modo non è probabile che vi si sovrappongano o si calpestano accidentalmente in un ambito locale da qualche parte. Che sta assumendo che non stai facendo qualcosa di simile a questo, però:

using namespace mpi_glob; 

che è poco diverso da solo che hanno le variabili globali in un file da qualche parte e non protegge molto.

Se rende il programma più chiaro e facile da capire utilizzando le variabili globali, quindi utilizzale. Se è possibile tenerli locali, tenerli locali, perché di solito rende la manutenzione più semplice a lungo termine.

0

Suppongo che Singleton dovrebbe aiutarti a gestirlo meglio, quindi non devi passare il puntatore. In pratica, lo mpi_glob fa lo stesso, Singleton è solo un modo più abituale.

In alternativa, è ancora possibile ricorrere a variabili globali: non sono male in quanto tali. Se si vuole sottolineare l'assegnazione di una volta è possibile dichiarare loro const e metterli via inizializzatore statico come questo:

const int number_of_tasks = get_preconfigured_number_of_tasks(); 

Se le variabili globali sono utilizzati per tenere la compilazione costanti di tempo, allora è perfettamente bene di sostituirli con i membri enum o il preprocessore definisce. In questo modo si semplificherà il compilatore, poiché può utilizzare il valore immediato sul posto senza accesso alla memoria.


Il credito va a Pete Becker per aver segnalato problemi Singleton nel suo commento. Se anche questi problemi ti infastidiscono, è possibile adottare un approccio totalmente diverso.

Ricordare come vengono implementati i programmi Java? C'è una classe principale con il metodo principale e tutto il lavoro del programma parte da quel metodo principale. Main è ancora una funzione membro, cioè può accedere esclusivamente ad alcuni campi privati ​​della classe principale (devono essere statici in caso di Java, ma questo non è il punto principale qui).

Possiamo estendere ulteriormente il concetto all'implementazione di tipo Command -like. La differenza con Java convenzionale è che l'equivalente del metodo principale non è statico e le variabili globali con valori specifici del programma contenuto sono variabili membro non statiche. Tutte le funzioni che devono accedere ai dati di stato globali devono essere convertite in funzioni membro. Questo è possibile, perché il metodo principale è anche la funzione membro.

In questo modo, penso, è possibile ottenere una migliore incapsulamento e sicurezza dei dati.

+1

Un singleton è eccessivo per le costanti e fornisce solo un'illusione di sicurezza per i dati globali. Il problema con i dati globali è che può essere modificato da qualsiasi file sorgente, quindi è difficile vedere dove è stata apportata una particolare modifica. Rendendolo un singleton non lo cambia. L'unico vantaggio di cui sono a conoscenza dall'uso di un singleton è che riduce l'ordine dei problemi di inizializzazione. Ma l'ordine dei problemi di inizializzazione deriva dall'uso eccessivo dei globals; la riduzione dell'uso di globals riduce anche questi problemi, oltre a ridurre i problemi di debug che presentano i globals. –

+0

@PeteBecker Sono d'accordo con te per quanto riguarda il controllo dei dati, specialmente se singleton è solo un oggetto stupido senza getter/setter. In questo caso Singleton non ha lo scopo di portare vantaggi OP non chiesto. L'ho disegnato solo per rappresentare un modo più ordinario, che i programmatori comuni come me si aspetterebbero. È sicuramente un eccesso di costanti, ecco perché ci sono altre alternative. –

+0

non importa se l'oggetto che si ottiene da un singleton ha getter e setter. Sono ancora dati globali. I getter ei setter non sono più utili e non meno utili di quanto non sarebbero con semplici dati globali. –