Globals sind unvermeidlich.
Es ist eine alte Diskussion, aber ich möchte noch einige Gedanken hinzufügen, weil ich sie in den oben genannten Antworten vermisse. Diese Antworten vereinfachen, was eine globale zu viel ist, und präsentieren Lösungen, die überhaupt keine Lösungen für das Problem sind. Das Problem ist: Was ist der richtige Umgang mit einer globalen Variablen und die Verwendung des Schlüsselworts global? Dazu müssen wir zunächst untersuchen und beschreiben, was ein Global ist.
Schauen Sie sich diesen Code von Zend an - und verstehen Sie bitte, dass ich nicht behaupte, dass Zend schlecht geschrieben ist:
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',
);
Hier gibt es viele unsichtbare Abhängigkeiten. Diese Konstanten sind eigentlich Klassen. Sie können require_once auch auf einigen Seiten dieses Frameworks sehen. Require_once ist eine globale Abhängigkeit, wodurch externe Abhängigkeiten erstellt werden. Das ist für einen Rahmen unvermeidlich. Wie können Sie eine Klasse wie DecoratorPluginManager ohne viel externen Code erstellen, von dem sie abhängt? Es kann nicht ohne viele Extras funktionieren. Haben Sie mit dem Zend-Framework jemals die Implementierung einer Schnittstelle geändert? Eine Schnittstelle ist in der Tat eine globale.
Eine weitere weltweit verwendete Anwendung ist Drupal. Sie sind sehr besorgt über das richtige Design, aber genau wie jedes große Framework haben sie viele externe Abhängigkeiten. Schauen Sie sich die Globals auf dieser Seite an:
/**
* @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();
Haben Sie jemals eine Weiterleitung zur Anmeldeseite geschrieben? Das verändert einen globalen Wert. (Und dann sagen Sie nicht 'WTF', was ich als gute Reaktion auf eine schlechte Dokumentation Ihrer Anwendung betrachte.) Das Problem bei Globals ist nicht, dass es sich um Globals handelt, Sie benötigen sie, um eine aussagekräftige Anwendung zu haben. Das Problem ist die Komplexität der gesamten Anwendung, die es zu einem Albtraum machen kann. Sitzungen sind global, $ _POST ist global, DRUPAL_ROOT ist global, include / install.core.inc 'ist nicht modifizierbar global. Es gibt eine große Welt außerhalb jeder Funktion, die erforderlich ist, damit diese Funktion ihre Arbeit erledigt.
Die Antwort von Gordon ist falsch, weil er die Unabhängigkeit einer Funktion überschätzt und eine Funktion als Lügner bezeichnet, was die Situation zu stark vereinfacht. Funktionen lügen nicht und wenn Sie sich sein Beispiel ansehen, ist die Funktion nicht richtig gestaltet - sein Beispiel ist ein Fehler. (Übrigens stimme ich dieser Schlussfolgerung zu, dass man Code entkoppeln sollte.) Die Antwort der Täuschung ist nicht wirklich eine richtige Definition der Situation. Funktionen funktionieren immer in einem größeren Rahmen und sein Beispiel ist viel zu einfach. Wir werden ihm alle zustimmen, dass diese Funktion völlig nutzlos ist, weil sie eine Konstante zurückgibt. Diese Funktion ist sowieso schlechtes Design. Wenn Sie zeigen möchten, dass die Praxis schlecht ist, geben Sie bitte ein relevantes Beispiel. Das Umbenennen von Variablen in einer Anwendung ist mit einer guten IDE (oder einem Tool) keine große Sache. Die Frage bezieht sich auf den Umfang der Variablen, nicht auf den Unterschied im Umfang mit der Funktion. Es gibt einen geeigneten Zeitpunkt für eine Funktion, um ihre Rolle im Prozess zu erfüllen (deshalb wird sie in erster Linie erstellt), und zu diesem richtigen Zeitpunkt kann sie die Funktionsweise der gesamten Anwendung beeinflussen und somit auch an globalen Variablen arbeiten . Die Antwort von xzyfer ist eine Aussage ohne Argumentation. Globals sind in einer Anwendung genauso vorhanden, wenn Sie über prozedurale Funktionen oder ein OOP-Design verfügen. Die nächsten beiden Möglichkeiten, den Wert eines globalen Werts zu ändern, sind im Wesentlichen dieselben: daher auch an globalen Variablen arbeiten. Die Antwort von xzyfer ist eine Aussage ohne Argumentation. Globals sind in einer Anwendung genauso vorhanden, wenn Sie über prozedurale Funktionen oder ein OOP-Design verfügen. Die nächsten beiden Möglichkeiten, den Wert eines globalen Werts zu ändern, sind im Wesentlichen dieselben: daher auch an globalen Variablen arbeiten. Die Antwort von xzyfer ist eine Aussage ohne Argumentation. Globals sind in einer Anwendung genauso vorhanden, wenn Sie über prozedurale Funktionen oder ein OOP-Design verfügen. Die nächsten beiden Möglichkeiten, den Wert eines globalen Werts zu ändern, sind im Wesentlichen dieselben:
function xzy($var){
global $z;
$z = $var;
}
function setZ($var){
$this->z = $var;
}
In beiden Fällen wird der Wert von $ z innerhalb einer bestimmten Funktion geändert. Auf beide Arten der Programmierung können Sie diese Änderungen an einer Reihe anderer Stellen im Code vornehmen. Man könnte sagen, dass man mit global überall $ z aufrufen und dort ändern kann. Ja, du kannst. Aber wirst du? Und wenn es an ungeeigneten Orten gemacht wird, sollte es dann nicht als Fehler bezeichnet werden?
Bob Fanger kommentiert xzyfer.
Sollte jemand dann einfach irgendetwas verwenden und vor allem das Schlüsselwort 'global'? Nein, aber versuchen Sie wie bei jeder Art von Design zu analysieren, worauf es ankommt und was davon abhängt. Versuchen Sie herauszufinden, wann es sich ändert und wie es sich ändert. Das Ändern globaler Werte sollte nur bei Variablen erfolgen, die sich bei jeder Anforderung / Antwort ändern können. Das heißt, nur zu den Variablen, die zum Funktionsablauf eines Prozesses gehören, nicht zu seiner technischen Implementierung. Die Umleitung einer URL zur Anmeldeseite gehört zum Funktionsablauf eines Prozesses, der Implementierungsklasse, die für eine Schnittstelle zur technischen Implementierung verwendet wird. Sie können Letzteres während der verschiedenen Versionen der Anwendung ändern, sollten diese jedoch nicht bei jeder Anforderung / Antwort ändern.
Um besser zu verstehen, wann es ein Problem ist, mit Globals und dem Schlüsselwort global zu arbeiten, und wann nicht, werde ich den nächsten Satz einführen, der von Wim de Bie beim Schreiben über Blogs stammt: "Persönliches Ja, privates Nein". Wenn eine Funktion den Wert einer globalen Variablen aufgrund ihrer eigenen Funktionsweise ändert, werde ich diese private Verwendung einer globalen Variablen und eines Fehlers nennen. Aber wenn die Änderung der globalen Variablen für die ordnungsgemäße Verarbeitung der gesamten Anwendung vorgenommen wird, wie die Weiterleitung des Benutzers auf die Anmeldeseite, dann ist das meiner Meinung nach möglicherweise gutes Design, nicht per Definition schlecht und schon gar nicht schlecht Anti-Muster.
Rückblickend auf die Antworten von Gordon, Deceze und Xzyfer: Alle haben als Beispiele 'privates Ja' (und Bugs). Deshalb sind sie gegen die Verwendung von Globalen. Ich würde es auch tun. Sie enthalten jedoch keine "persönlichen Ja, privaten Nein" -Beispiele, wie ich sie in dieser Antwort mehrmals gemacht habe.