Globais são inevitáveis.
É uma discussão antiga, mas ainda gostaria de acrescentar algumas reflexões porque sinto falta delas nas respostas mencionadas acima. Essas respostas simplificam demais o que é um global e apresentam soluções que não são soluções para o problema. O problema é: qual a maneira adequada de lidar com uma variável global e o uso da palavra-chave global? Para isso, primeiro temos que examinar e descrever o que é um global.
Dê uma olhada neste código do Zend - e por favor, entenda que eu não sugiro que o Zend seja mal escrito:
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',
);
Existem muitas dependências invisíveis aqui. Essas constantes são, na verdade, classes. Você também pode ver require_once em algumas páginas desta estrutura. Require_once é uma dependência global, portanto, criando dependências externas. Isso é inevitável para uma estrutura. Como você pode criar uma classe como DecoratorPluginManager sem muito código externo do qual depende? Não pode funcionar sem muitos extras. Usando o framework Zend, você já mudou a implementação de uma interface? Uma interface é, na verdade, global.
Outro aplicativo usado globalmente é o Drupal. Eles estão muito preocupados com o design adequado, mas, assim como qualquer grande framework, eles têm muitas dependências externas. Dê uma olhada nos globais nesta página:
/**
* @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();
Já escreveu um redirecionamento para a página de login? Isso está mudando um valor global. (E então você não está dizendo 'WTF', que considero uma boa reação à má documentação do seu aplicativo.) O problema com os globais não é que sejam globais, você precisa deles para ter um aplicativo significativo. O problema é a complexidade do aplicativo geral, que pode torná-lo um pesadelo de lidar. As sessões são globais, $ _POST é global, DRUPAL_ROOT é global, o includes / install.core.inc 'é um global não modificável. Existe um grande mundo fora de qualquer função necessária para permitir que essa função faça seu trabalho.
A resposta de Gordon está incorreta, porque ele superestima a independência de uma função e chamar uma função de mentirosa é simplificar demais a situação. Funções não mentem e quando você dá uma olhada em seu exemplo, a função é projetada incorretamente - seu exemplo é um bug. (A propósito, concordo com a conclusão de que devemos desacoplar o código.) A resposta do deceze não é realmente uma definição adequada da situação. As funções sempre funcionam dentro de um escopo mais amplo e seu exemplo é muito simplista. Todos concordaremos com ele que essa função é totalmente inútil, porque retorna uma constante. Essa função é, de qualquer forma, um design ruim. Se você quiser mostrar que a prática é ruim, venha com um exemplo relevante. Renomear variáveis em um aplicativo não é grande coisa ter um bom IDE (ou uma ferramenta). A questão é sobre o escopo da variável, não a diferença de escopo com a função. Existe um momento adequado para uma função desempenhar seu papel no processo (é por isso que ela é criada em primeiro lugar) e nesse momento adequado pode influenciar o funcionamento da aplicação como um todo, portanto, também trabalhando em variáveis globais . A resposta de xzyfer é uma declaração sem argumentação. Os globais estão presentes em um aplicativo se você tiver funções procedurais ou design OOP. As próximas duas maneiras de alterar o valor de um global são essencialmente as mesmas: portanto, também trabalhando em variáveis globais. A resposta de xzyfer é uma declaração sem argumentação. Os globais estão presentes em um aplicativo se você tiver funções procedurais ou design OOP. As próximas duas maneiras de alterar o valor de um global são essencialmente as mesmas: portanto, também trabalhando em variáveis globais. A resposta de xzyfer é uma declaração sem argumentação. Os globais estão presentes em um aplicativo se você tiver funções procedurais ou design OOP. As próximas duas maneiras de alterar o valor de um global são essencialmente as mesmas:
function xzy($var){
global $z;
$z = $var;
}
function setZ($var){
$this->z = $var;
}
Em ambos os casos, o valor de $ z é alterado em uma função específica. Em ambas as formas de programação, você pode fazer essas alterações em vários outros locais do código. Você poderia dizer que usando global você poderia chamar $ z em qualquer lugar e mudar lá. Sim você pode. Mas você vai? E quando feito em locais inadequados, não deveria ser chamado de bug?
Bob Fanger comenta sobre xzyfer.
Alguém deveria usar qualquer coisa, especialmente a palavra-chave 'global'? Não, mas como qualquer tipo de projeto, tente analisar o que depende e o que depende disso. Tente descobrir quando ele muda e como ele muda. A alteração dos valores globais só deve acontecer com as variáveis que podem ser alteradas a cada solicitação / resposta. Ou seja, apenas para aquelas variáveis que pertencem ao fluxo funcional de um processo, não à sua implementação técnica. O redirecionamento de uma URL para a página de login pertence ao fluxo funcional de um processo, a classe de implementação usada para uma interface para a implementação técnica. Você pode alterar o último durante as diferentes versões do aplicativo, mas não deve alterá-los a cada solicitação / resposta.
Para entender melhor quando é um problema trabalhar com globais e a palavra-chave global e quando não, vou apresentar a próxima frase, que vem de Wim de Bie ao escrever sobre blogs: 'Pessoal sim, privado não'. Quando uma função está mudando o valor de uma variável global para seu próprio funcionamento, chamarei esse uso privado de uma variável global e um bug. Mas quando a alteração da variável global é feita para o processamento adequado da aplicação como um todo, como o redirecionamento do usuário para a página de login, então isso na minha opinião é possivelmente um bom design, não por definição ruim e certamente não um anti-padrão.
Em retrospecto, as respostas de Gordon, deceze e xzyfer: todos eles têm 'sim privado' (e bugs) como exemplos. É por isso que eles se opõem ao uso de globais. Eu faria também Eles, no entanto, não vêm com exemplos de 'sim pessoal, não particular' como fiz nesta resposta várias vezes.