Por que as variáveis ​​globais são más? [fechadas]

120

Estou tentando descobrir por que o uso de globalé considerado uma má prática em python (e na programação em geral). Alguém pode explicar? Links com mais informações também seriam apreciados.

LarsVegas
fonte
Votando para reabrir - editei a pergunta para mudar o foco para as explicações e para longe dos recursos externos. (Suponho que é por isso que foi fechada, mas apenas no caso de algo a ver com ser uma pergunta sobre a má prática, comparar estes outras perguntas sobre má prática ainda em aberto: eval, import *, concatenação , variávelid , sombras atributo )
wjandrea

Respostas:

156

Isso não tem nada a ver com Python; variáveis ​​globais são ruins em qualquer linguagem de programação.

No entanto, constantes globais não são conceitualmente iguais às variáveis ​​globais ; constantes globais são perfeitamente inofensivas. Em Python, a distinção entre os dois é puramente por convenção: CONSTANTS_ARE_CAPITALIZEDe globals_are_not.

A razão pela qual as variáveis ​​globais são ruins é que elas permitem que funções tenham efeitos colaterais ocultos (não óbvios, surpreendentes, difíceis de detectar, difíceis de diagnosticar), levando a um aumento na complexidade, potencialmente levando ao código Spaghetti .

No entanto, o uso racional do estado global é aceitável (assim como o estado local e a mutabilidade), mesmo em programação funcional, seja para otimização de algoritmo, complexidade reduzida, armazenamento em cache e memoização, ou a praticidade de portar estruturas originadas em uma base de código predominantemente imperativa.

Resumindo, sua pergunta pode ser respondida de várias maneiras, então sua melhor aposta é apenas pesquisar no Google "por que as variáveis ​​globais são ruins". Alguns exemplos:

Se você quiser se aprofundar e descobrir por que os efeitos colaterais estão relacionados e muitas outras coisas esclarecedoras, você deve aprender Programação Funcional:

Erik Kaplun
fonte
35

Sim, em teoria , os globais (e o "estado" em geral) são maus. Na prática, se você olhar para o diretório de pacotes do python, você descobrirá que a maioria dos módulos lá começa com um monte de declarações globais. Obviamente, as pessoas não têm problemas com eles.

Especificamente para python, a visibilidade global é limitada a um módulo, portanto, não existem globais "verdadeiros" que afetam todo o programa - o que os torna menos prejudiciais. Outro ponto: não há const, então quando você precisa de uma constante, você tem que usar uma global.

Na minha prática, se acontecer de eu modificar um global em uma função, sempre declaro isso com global, mesmo que tecnicamente não haja necessidade disso, como em:

cache = {}

def foo(args):
    global cache

    cache[args] = ...

Isso torna as manipulações globais mais fáceis de rastrear.

georg
fonte
3
de muitas maneiras, um módulo em python é semelhante a uma classe singleton e os globais do módulo são semelhantes às propriedades da classe.
Corley Brigman
9
@CorleyBrigman: classes singleton, na verdade, muitas vezes sofrem dos mesmos problemas normalmente atribuídos a globais :)
Erik Kaplun,
4
a visibilidade dos módulos python não se limita a um módulo. Eles estão disponíveis em todo o intérprete e (aqui está o importante) alterações afetam todo o intérprete. Não é como uma string que você cria instâncias ... é como modificar todas as instâncias de string. Cheiro de remendo de macaco.
graffic de
2
A maioria dos módulos não começa com a definição de globais, exceto constantes. Globais são ruins, significam variáveis / estado global não constantes.
BlackJack
2
Usar globais é uma ideia horrível, um dos motivos pode ser a incapacidade de testar corretamente as funções que atualizam algum dicionário arbitrário que existe "em algum lugar". Uma base de código com globais não pode ser realmente comprovada como funcional.
Tomasz Sosiński
10

Uma opinião pessoal sobre o assunto é que ter variáveis ​​globais sendo usadas em uma lógica de função significa que algum outro código pode alterar a lógica e a saída esperada dessa função, o que tornará a depuração muito difícil (especialmente em grandes projetos) e tornará os testes mais difíceis também.

Além disso, se você considerar outras pessoas lendo seu código (comunidade de código aberto, colegas, etc.), elas terão dificuldade em entender onde a variável global está sendo definida, onde foi alterada e o que esperar dessa variável global. para uma função isolada que sua funcionalidade pode ser determinada pela leitura da própria definição da função.

(Provavelmente) Violando a definição de função pura

Acredito que um código limpo e (quase) sem bugs deve ter funções tão puras quanto possível (consulte funções puras ). Uma função pura é aquela que possui as seguintes condições:

  1. A função sempre avalia o mesmo valor de resultado dado o (s) mesmo (s) valor (es) de argumento . O valor do resultado da função não pode depender de qualquer informação oculta ou estado que pode mudar enquanto a execução do programa prossegue ou entre diferentes execuções do programa, nem pode depender de qualquer entrada externa de dispositivos de E / S (geralmente — veja abaixo).
  2. A avaliação do resultado não causa nenhum efeito colateral semanticamente observável ou saída , como a mutação de objetos mutáveis ​​ou saída para dispositivos de E / S.

Ter variáveis ​​globais está violando pelo menos um dos itens acima, se não ambos, pois um código externo pode provavelmente causar resultados inesperados.

Outra definição clara de funções puras: "Função pura é uma função que recebe todas as suas entradas como argumentos explícitos e produz todas as suas saídas como resultados explícitos ." [1] . Ter variáveis ​​globais viola a ideia de funções puras, uma vez que uma entrada e talvez uma das saídas (a variável global) não está sendo explicitamente fornecida ou retornada.

(Provavelmente) Violando o princípio do PRIMEIRO teste de unidade

Mais adiante que, se você considerar teste de unidade e o primeiro princípio ( F testes AST, I testes ndependent, R epeatable, S elf-Validação e T imely) provavelmente irá violar testa princípio (o Independent o que significa que os testes não dependem um no outro).

Ter uma variável global (nem sempre), mas na maioria dos casos (pelo menos do que vi até agora) é preparar e passar os resultados para outras funções. Isso também viola esse princípio. Se a variável global foi usada dessa maneira (ou seja, a variável global usada na função X deve ser definida em uma função Y primeiro), significa que para a função de teste de unidade X você deve executar o teste / a função Y primeiro.

Globais como constantes

Por outro lado e como outras pessoas já mencionaram, se a variável global for usada como uma variável "constante" pode ser um pouco melhor, pois a linguagem não suporta constantes. No entanto, sempre prefiro trabalhar com classes e ter as "constantes" como um membro da classe e não usar uma variável global. Se você tiver um código que duas classes diferentes requerem para compartilhar uma variável global, provavelmente precisará refatorar sua solução e tornar suas classes independentes.

Não acredito que os globais não devam ser usados. Mas, se forem usados, os autores devem considerar alguns princípios (talvez os mencionados acima e outros princípios e boas práticas de engenharia de software) para um código mais limpo e quase livre de erros.

Rafael
fonte
1
Eu gosto dos "globais como constantes são um problema" ... porque se você está fazendo design OO ... realmente é. Por que alguém, exceto a classe IdCreator, precisa saber o ID_LEN?
Erik Aronesty
3

Eles são essenciais, a tela é um bom exemplo. No entanto, em um ambiente multithread ou com muitos desenvolvedores envolvidos, na prática muitas vezes surge a pergunta: quem o definiu ou apagou (erroneamente)? Dependendo da arquitetura, a análise pode ser cara e frequentemente necessária. Enquanto a leitura da var global pode ser boa, a gravação nela deve ser controlada, por exemplo, por um único thread ou classe threadsafe. Conseqüentemente, os vars globais levantam o medo de altos custos de desenvolvimento possíveis pelas consequências pelas quais são considerados maléficos. Portanto, em geral, é uma boa prática manter baixo o número de vars globais.

Horst Schlawutzke
fonte