Les globaux sont inévitables.
C'est une vieille discussion, mais je voudrais quand même ajouter quelques réflexions car elles me manquent dans les réponses mentionnées ci-dessus. Ces réponses simplifient ce qu'est trop un global et présentent des solutions qui ne sont pas du tout des solutions au problème. Le problème est: quelle est la bonne façon de traiter une variable globale et l'utilisation du mot-clé global? Pour cela, nous devons d'abord examiner et décrire ce qu'est un global.
Jetez un œil à ce code de Zend - et comprenez bien que je ne suggère pas que Zend soit mal écrit:
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',
);
Il y a beaucoup de dépendances invisibles ici. Ces constantes sont en fait des classes. Vous pouvez également voir require_once dans certaines pages de ce framework. Require_once est une dépendance globale, créant ainsi des dépendances externes. C'est inévitable pour un cadre. Comment pouvez-vous créer une classe comme DecoratorPluginManager sans beaucoup de code externe dont cela dépend? Il ne peut pas fonctionner sans beaucoup d'extras. En utilisant le framework Zend, avez-vous déjà changé l'implémentation d'une interface? Une interface est en fait un global.
Une autre application utilisée dans le monde est Drupal. Ils sont très préoccupés par une conception appropriée, mais comme tout grand framework, ils ont beaucoup de dépendances externes. Jetez un œil aux globaux sur cette page:
/**
* @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();
Avez-vous déjà écrit une redirection vers la page de connexion? Cela change une valeur globale. (Et puis ne dites-vous pas «WTF», que je considère comme une bonne réaction à une mauvaise documentation de votre application.) Le problème avec les globaux n'est pas qu'ils soient globaux, vous en avez besoin pour avoir une application significative. Le problème est la complexité de l'application globale qui peut en faire un cauchemar à gérer. Les sessions sont globales, $ _POST est un global, DRUPAL_ROOT est un global, le includes / install.core.inc 'est un global non modifiable. Il y a un grand monde en dehors de toute fonction nécessaire pour que cette fonction fasse son travail.
La réponse de Gordon est incorrecte, car il surestime l'indépendance d'une fonction et appeler une fonction un menteur simplifie à l'extrême la situation. Les fonctions ne mentent pas et lorsque vous regardez son exemple, la fonction est mal conçue - son exemple est un bogue. (En passant, je suis d'accord avec cette conclusion qu'il faut découpler le code.) La réponse de deceze n'est pas vraiment une définition correcte de la situation. Les fonctions fonctionnent toujours dans un cadre plus large et son exemple est bien trop simpliste. Nous conviendrons tous avec lui que cette fonction est totalement inutile, car elle renvoie une constante. Cette fonction est de toute façon une mauvaise conception. Si vous voulez montrer que la pratique est mauvaise, veuillez fournir un exemple pertinent. Renommer les variables dans une application n'est pas un problème avec un bon IDE (ou un outil). La question concerne la portée de la variable, pas la différence de portée avec la fonction. Il y a un moment propice pour qu'une fonction joue son rôle dans le processus (c'est pourquoi elle est créée en premier lieu) et à ce moment-là, elle peut influencer le fonctionnement de l'application dans son ensemble, donc également travailler sur des variables globales . La réponse de xzyfer est une déclaration sans argumentation. Les globaux sont tout aussi présents dans une application si vous avez des fonctions procédurales ou une conception POO. Les deux façons suivantes de modifier la valeur d'un global sont essentiellement les mêmes: donc aussi travailler sur des variables globales. La réponse de xzyfer est une déclaration sans argumentation. Les globaux sont tout aussi présents dans une application si vous avez des fonctions procédurales ou une conception POO. Les deux façons suivantes de modifier la valeur d'un global sont essentiellement les mêmes: donc aussi travailler sur des variables globales. La réponse de xzyfer est une déclaration sans argumentation. Les globaux sont tout aussi présents dans une application si vous avez des fonctions procédurales ou une conception POO. Les deux façons suivantes de modifier la valeur d'un global sont essentiellement les mêmes:
function xzy($var){
global $z;
$z = $var;
}
function setZ($var){
$this->z = $var;
}
Dans les deux cas, la valeur de $ z est modifiée dans une fonction spécifique. Dans les deux modes de programmation, vous pouvez apporter ces modifications à un tas d'autres endroits du code. Vous pourriez dire qu'en utilisant global, vous pouvez appeler $ z n'importe où et y changer. Oui, vous pouvez. Mais allez-vous? Et quand cela est fait dans des endroits inadaptés, ne devrait-il pas être appelé un bogue?
Bob Fanger commente xzyfer.
Quelqu'un devrait-il alors utiliser n'importe quoi et en particulier le mot clé «global»? Non, mais comme tout type de design, essayez d'analyser ce dont cela dépend et ce qui en dépend. Essayez de savoir quand cela change et comment cela change. La modification des valeurs globales ne devrait se produire qu'avec les variables qui peuvent changer à chaque demande / réponse. Autrement dit, uniquement aux variables qui appartiennent au flux fonctionnel d'un processus, pas à sa mise en œuvre technique. La redirection d'une URL vers la page de connexion appartient au flux fonctionnel d'un processus, la classe d'implémentation utilisée pour une interface vers l'implémentation technique. Vous pouvez modifier ces dernières au cours des différentes versions de l'application, mais ne devez pas les modifier à chaque demande / réponse.
Pour mieux comprendre quand c'est un problème de travailler avec des globals et le mot-clé global et quand je ne vais pas vous présenter la phrase suivante, qui vient de Wim de Bie lors de l'écriture sur les blogs: «Personal yes, private no». Lorsqu'une fonction change la valeur d'une variable globale pour son propre fonctionnement, j'appellerai cette utilisation privée d'une variable globale et d'un bogue. Mais lorsque le changement de la variable globale est fait pour le bon traitement de l'application dans son ensemble, comme la redirection de l'utilisateur vers la page de connexion, alors est-ce à mon avis peut-être un bon design, pas par définition mauvais et certainement pas un anti-motif.
Rétrospectivement aux réponses de Gordon, deceze et xzyfer: ils ont tous des «oui privés» (et des bugs) comme exemples. C'est pourquoi ils s'opposent à l'utilisation de globaux. Je ferais aussi. Cependant, ils ne sont pas accompagnés d'exemples de «oui personnel, non privé», comme je l'ai fait plusieurs fois dans cette réponse.