I globali sono inevitabili.
È una vecchia discussione, ma vorrei comunque aggiungere alcuni pensieri perché mi mancano nelle risposte sopra menzionate. Quelle risposte semplificano ciò che un globale è troppo e presentano soluzioni che non sono affatto soluzioni al problema. Il problema è: qual è il modo corretto di trattare una variabile globale e l'uso della parola chiave global? Per questo dobbiamo prima esaminare e descrivere cos'è un globale.
Dai un'occhiata a questo codice di Zend e tieni presente che non suggerisco che Zend sia scritto male:
class DecoratorPluginManager extends AbstractPluginManager
{
/**
* Default set of decorators
*
* @var array
*/
protected $invokableClasses = array(
'htmlcloud' => 'Zend\Tag\Cloud\Decorator\HtmlCloud',
'htmltag' => 'Zend\Tag\Cloud\Decorator\HtmlTag',
'tag' => 'Zend\Tag\Cloud\Decorator\HtmlTag',
);
Ci sono molte dipendenze invisibili qui. Quelle costanti sono in realtà classi. Puoi anche vedere require_once in alcune pagine di questo framework. Require_once è una dipendenza globale, quindi crea dipendenze esterne. Ciò è inevitabile per un framework. Come puoi creare una classe come DecoratorPluginManager senza molto codice esterno da cui dipende? Non può funzionare senza molti extra. Usando il framework Zend, hai mai cambiato l'implementazione di un'interfaccia? Un'interfaccia è infatti globale.
Un'altra applicazione utilizzata a livello globale è Drupal. Sono molto preoccupati per la corretta progettazione, ma proprio come ogni grande framework, hanno molte dipendenze esterne. Dai un'occhiata alle globali in questa pagina:
/**
* @file
* Initiates a browser-based installation of Drupal.
*/
/**
* Root directory of Drupal installation.
*/
define('DRUPAL_ROOT', getcwd());
/**
* Global flag to indicate that site is in installation mode.
*/
define('MAINTENANCE_MODE', 'install');
// Exit early if running an incompatible PHP version to avoid fatal errors.
if (version_compare(PHP_VERSION, '5.2.4') < 0) {
print 'Your PHP installation is too old. Drupal requires at least PHP 5.2.4. See the <a href="http://drupal.org/requirements">system requirements</a> page for more information.';
exit;
}
// Start the installer.
require_once DRUPAL_ROOT . '/includes/install.core.inc';
install_drupal();
Hai mai scritto un reindirizzamento alla pagina di accesso? Questo sta cambiando un valore globale. (E poi non stai dicendo "WTF", che considero una buona reazione alla cattiva documentazione della tua applicazione.) Il problema con le globali non è che sono globali, ti servono per avere un'applicazione significativa. Il problema è la complessità dell'applicazione complessiva che può renderla un incubo da gestire. Le sessioni sono globali, $ _POST è globale, DRUPAL_ROOT è globale, include / install.core.inc 'è un globale non modificabile. C'è un grande mondo al di fuori di qualsiasi funzione richiesta per consentire a quella funzione di svolgere il suo lavoro.
La risposta di Gordon non è corretta, perché sopravvaluta l'indipendenza di una funzione e chiamare bugiardo una funzione semplifica eccessivamente la situazione. Le funzioni non mentono e quando dai un'occhiata al suo esempio la funzione è progettata in modo improprio - il suo esempio è un bug. (A proposito, sono d'accordo con questa conclusione che si dovrebbe disaccoppiare il codice.) La risposta di inganno non è davvero una definizione corretta della situazione. Le funzioni funzionano sempre in un ambito più ampio e il suo esempio è troppo semplicistico. Saremo tutti d'accordo con lui sul fatto che quella funzione è completamente inutile, perché restituisce una costante. Quella funzione è comunque un cattivo design. Se vuoi dimostrare che la pratica è cattiva, fornisci un esempio pertinente. Rinominare le variabili in un'applicazione non è un grosso problema avere un buon IDE (o uno strumento). La domanda riguarda l'ambito della variabile, non la differenza di ambito con la funzione. C'è un momento opportuno affinché una funzione svolga il suo ruolo nel processo (ecco perché viene creata in primo luogo) e in quel momento opportuno può influenzare il funzionamento dell'applicazione nel suo insieme, quindi lavorare anche su variabili globali . La risposta di xzyfer è un'affermazione senza argomentazioni. I globali sono altrettanto presenti in un'applicazione se si dispone di funzioni procedurali o progettazione OOP. I prossimi due modi per modificare il valore di un globale sono essenzialmente gli stessi: quindi lavorando anche su variabili globali. La risposta di xzyfer è un'affermazione senza argomentazioni. I globali sono altrettanto presenti in un'applicazione se si dispone di funzioni procedurali o progettazione OOP. I prossimi due modi per modificare il valore di un globale sono essenzialmente gli stessi: quindi lavorando anche su variabili globali. La risposta di xzyfer è un'affermazione senza argomentazioni. I globali sono altrettanto presenti in un'applicazione se si dispone di funzioni procedurali o progettazione OOP. I prossimi due modi per modificare il valore di un globale sono essenzialmente gli stessi:
function xzy($var){
global $z;
$z = $var;
}
function setZ($var){
$this->z = $var;
}
In entrambi i casi il valore di $ z viene modificato all'interno di una funzione specifica. In entrambi i modi di programmazione puoi apportare queste modifiche in un mucchio di altri punti del codice. Potresti dire che usando global potresti chiamare $ z ovunque e cambiare lì. Si, puoi. Ma lo farai? E se fatto in luoghi inadeguati, non dovrebbe quindi essere chiamato un bug?
Bob Fanger commenta xzyfer.
Qualcuno dovrebbe quindi usare qualcosa e in particolare la parola chiave "globale"? No, ma proprio come qualsiasi tipo di design, prova ad analizzare da cosa dipende e cosa dipende da esso. Prova a scoprire quando cambia e come cambia. La modifica dei valori globali dovrebbe avvenire solo con quelle variabili che possono cambiare ad ogni richiesta / risposta. Cioè, solo a quelle variabili che appartengono al flusso funzionale di un processo, non alla sua implementazione tecnica. Il reindirizzamento di un URL alla pagina di login appartiene al flusso funzionale di un processo, la classe di implementazione utilizzata per un'interfaccia all'implementazione tecnica. Puoi cambiare quest'ultimo durante le diverse versioni dell'applicazione, ma non dovresti cambiarli ad ogni richiesta / risposta.
Per capire meglio quando è un problema lavorare con le globali e la parola chiave globale e quando no, introdurrò la frase successiva, che viene da Wim de Bie quando scrive sui blog: "Personale sì, privato no". Quando una funzione sta cambiando il valore di una variabile globale per il proprio funzionamento, chiamerò quell'uso privato di una variabile globale e un bug. Ma quando la modifica della variabile globale viene effettuata per la corretta elaborazione dell'applicazione nel suo insieme, come il reindirizzamento dell'utente alla pagina di login, allora è che a mio parere è possibile un buon design, non per definizione cattivo e certamente non un anti-modello.
In retrospettiva alle risposte di Gordon, ingannare e xzyfer: hanno tutti "sì privato" (e bug) come esempi. Questo è il motivo per cui sono contrari all'uso di globali. Lo farei anch'io. Tuttavia, non vengono forniti con esempi di "sì personale, no privato" come ho fatto più volte in questa risposta.