O cenário é simples: você precisa compartilhar algum tipo de informação entre várias partes do seu código. A solução mirabolante: usar uma variável global. Afinal as variáveis globais estão acessíveis de todos os lugares e facilmente você introduz referências à ela em diversas partes do seu código.
Isso é uma péssima ideia. O uso de uma variável global denota péssimo design. Trata-se de um radical livre dentro do seu código que pode levá-lo a comportamentos erráticos, principalmente se a sua aplicação utilizar mais de uma linha simultânea de execução. A lista de problemas que podem ser causados por variáveis globais é tão grande que é melhor evitar o seu uso a todo custo.
Desenhe e redesenhe!
Ficou difícil compartilhar informações no seu código? Isso é sinal de que a modularização está ruim e precisa de um redesenho. Não tenha medo de mudar as coisas de lugar. É preferível redesenhar toda a sua estrutura de código do que deixar pontos de falha potenciais como uma variável global. Siga a Lei de Murphy: o que puder ser montado ao contrário, será montado ao contrário (este é o enunciado original).
Um bom desenho da estrutura do seu código poderá livrá-lo de várias dores-de-cabeça. A variável global é uma delas.
Por que a variável global é ruim?
O seu programa é, na verdade, uma máquina de estados. O estado do seu programa, como um todo, é dado pela soma dos estados de cada objeto individual que existe no seu programa. Apesar de usar o termo objeto, estou me referindo a qualquer coisa que possa mudar o comportamento do seu software, ou seja, variáveis e não, necessariamente, objetos como em Programação Orientada ao Objeto.
O estado do seu programa independe da linguagem de programação. E a manutenção deste estado depende de como os objetos em memória são tratados e controlados. Sempre é uma boa ideia manter todo o controle de estado centralizado. Assim você consegue controlar o ciclo de vida de cada objeto durante o processamento dos dados. Porém, as variáveis globais tem o controle do seu estado compartilhado por áreas do seu código que nem sempre são evidentes, dificultando a manutenção.
Isso quer dizer que não fica evidente no seu código qual módulo ou função altera o estado de uma variável global, tornando a manutenção uma caça de agulhas em palheiros. A situação fica ainda pior quando há várias threads utilizando um estado compartilhado globalmente, o que pode levar a mudanças assíncronas de estado completamente sem controle pois a execução das threads dependem da quantidade de time sharing que lhes foi reservada e que pode ser de tamanho completamente arbitrário.
Assim, o controle do estado de uma variável global torna-se distribuído no seu código sendo difícil mantê-lo ao longo do tempo. E é certeza que todos os piores defeitos do seu código ocorrerão nas rotinas que alteram o estado de uma variável global.
