As variáveis ​​globais são ruins? [fechadas]

247

Em C / C ++, as variáveis ​​globais são tão ruins quanto meu professor pensa que são?

GEOCHET
fonte
17
Vou morder, caso ele esteja tentando contar uma piada ... "quão ruins são elas"?
Zach Scrivena
13
Eu acho que essa pergunta foi bem interessante! O desenvolvimento de software ainda enfrenta as mesmas armadilhas antigas desde o início e os programadores muitas vezes ainda não sabem que o uso de variáveis ​​globais, gotos, variável de nome curto NÃO é o problema. Código incorreto é escrito todos os dias sem usá-lo. 1
Sylvain Rodrigue
69
Como podemos responder? Ele não nos disse o quão ruim seu professor pensa que é. :)
Steve Fallows
9
@ Juan Mendes Eu concordo 100% com você! O problema de que eu estava falando é que muitos desenvolvedores sabem que não devem usar variáveis ​​globais, mas simplesmente NÃO sabem o porquê! E assim eu vi muitos softwares grandes, onde todas as funções receberam a mesma mega-estrutura contendo +100 campos - Olha mãe, sem variáveis ​​globais! O mesmo problema que as chamadas "boas práticas": são boas práticas em ALGUNS contextos, não em todo o contexto. Utilizá-los PODE criar código insustentável. Felicidades.
Sylvain Rodrigue
3
Existem muito poucos usos bons para variáveis ​​globais. Um uso possível, mas discutível, seria um objeto de "configuração" global, que lê um arquivo de configuração uma vez na inicialização.
Siler

Respostas:

256

O problema com variáveis ​​globais é que, como todas as funções têm acesso a elas, fica cada vez mais difícil descobrir quais funções realmente lêem e escrevem essas variáveis.

Para entender como o aplicativo funciona, é preciso levar em consideração todas as funções que modificam o estado global. Isso pode ser feito, mas à medida que o aplicativo cresce, fica mais difícil a ponto de ser praticamente impossível (ou pelo menos uma completa perda de tempo).

Se você não confiar em variáveis ​​globais, poderá passar o estado entre diferentes funções, conforme necessário. Dessa forma, você tem uma chance muito maior de entender o que cada função faz, pois não precisa levar em consideração o estado global.

Brian Rasmussen
fonte
9
Esta resposta é realmente boa. Combine isso com o 'minimizar o escopo de variáveis' resposta stackoverflow.com/questions/357187/...
bobobobo
17
Substitua 'class' por 'application' e 'object state' por 'global state' e você cria exatamente o mesmo argumento para não usar variáveis ​​de membro (também conhecidas como campos) nas classes. A resposta real é usá-los quando apropriado.
Ian Goldby
2
Algumas perguntas (talvez tolas): 1) Se você deseja saber quais funções lêem e escrevem essas variáveis, você não pode simplesmente usar a função "find" em um editor para identificar os casos em que os valores nessas variáveis ​​são modificados? 2) "Isso pode ser feito ... uma completa perda de tempo)." Você pode dar um exemplo? 3) "Se você não depende de variáveis ​​globais, ... você não precisa levar em consideração o estado global." Não entendo como isso é uma vantagem. Talvez um exemplo disso funcione para mim.
21313 Andrei
2
@bobobobo link quebrado, podemos obter uma captura de tela de você, um usuário com mais de 10k?
noɥʇʎԀʎzɐɹƆ
3
@ noɥʇʎԀʎzɐɹƆ Aqui você vai! i.imgur.com/RwRgJLZ.jpg
Mateen Ulhaq
85

O importante é lembrar o objetivo geral: clareza

A regra "sem variáveis ​​globais" existe porque, na maioria das vezes, as variáveis ​​globais tornam o significado do código menos claro.

No entanto, como muitas regras, as pessoas lembram-se da regra, e não o que a regra deveria fazer.

Eu já vi programas que parecem dobrar o tamanho do código, passando um enorme número de parâmetros simplesmente para evitar o mal das variáveis ​​globais. No final, o uso de globais tornaria o programa mais claro para quem o lê. Ao aderir irremediavelmente à palavra da regra, o programador original falhou na intenção da regra.

Então, sim, os globais são geralmente ruins. Mas se você achar que, no final, a intenção do programador é esclarecida pelo uso de variáveis ​​globais, vá em frente. No entanto, lembre-se da queda na clareza que ocorre automaticamente quando você força alguém a acessar um segundo trecho de código (os globais) para entender como o primeiro trecho funciona.

Tom West
fonte
8
Sugerindo usando um global em vez de variáveis que passam é uma receita para fazer seu código não reutilizável e inseguro para multi-threading
Juan Mendes
16
Sugerir globais nas circunstâncias certas é uma receita para um código mais claro e com melhor desempenho. "Passar" requer alocação constante de memória dinâmica da pilha, e isso seria bobagem para algo que deveria ser global, como um buffer global para dados de soquete de entrada. Por exemplo, se você possui uma função que lê Winsock recv (), por que criar e desalocar constantemente esse buffer em todas as chamadas? Torne o buffer um global. Múltiplos threads não serão lidos de qualquer maneira.
James
Apenas curioso, qual programa duplica o tamanho do código passando parâmetros para evitar variáveis ​​globais? Na minha experiência, o uso de variáveis ​​globais pode resolver problemas de exposição de dados, mas geralmente há uma lógica complexa adicional que você precisa adicionar para garantir que essas variáveis ​​mágicas se comportem corretamente.
user2167582
3
Se alguém está passando cerca de 100 variáveis, não aprendeu o que é um objeto. Usar a referência a esse objeto é, na pior das hipóteses, passando por um ponteiro. Eu diria que a regra não é apenas clareza, mas também testabilidade - e usar um método não global tende a tornar as coisas muito mais fáceis de testar.
UKMonkey
2
"Se alguém está passando cerca de 100 variáveis, não aprendeu o que é um objeto." Concordou, mas nem todo o mundo é orientado a objetos. Meu exemplo pessoal de duplicar o tamanho do código foi um grande programa de Fortran, por volta de 1986. Como recém-empregado da universidade, eu o "aprimorei", adicionando cerca de 30 parâmetros a cada chamada, eliminando todos os globais. Então desfiz minha melhoria quando percebi o que havia feito.
Tom Oeste
64

Meu professor costumava dizer algo como: usar variáveis ​​globais é bom se você usá-las corretamente. Acho que nunca fui bom em usá-los corretamente, então raramente os usava.

barneytron
fonte
25
Tão verdade. Eles são como gotos, se você não sabe quando usá-los, nunca o faça.
21119 David Holm
5
Na minha empresa atual, eles usam staticmuito variáveis ​​globais, a linguagem é C. Estando confinados a unidades de conversão relativamente pequenas, eles começam a se parecer com variáveis ​​de classe de objetos C ++.
Vorac
1
As variáveis ​​estáticas do @Vorac não são variáveis ​​globais, são variáveis ​​locais. Uma variável global é uma variável disponível em qualquer lugar do programa (daí "global", duh). Não deve ser confundido com variáveis ​​de escopo de arquivo , que são variáveis ​​declaradas fora de qualquer função. Uma variável estática do escopo do arquivo não é uma variável global.
Lundin
1
Para me corrigir program lifetime, file scope variables,. E eles tornaram-se bastante mundial uma vez que você passar um ponteiro para a variável para o mundo exterior (o que é impossível com variáveis automáticas) ..
Vorac
@Lundin Concordo, staticas variáveis ​​globais têm escopo limitado à mesma unidade de tradução. Mas eles têm vida útil até o final do programa como qualquer variável global.
precisa
38

Variáveis ​​globais só devem ser usadas quando você não tem alternativa. E sim, isso inclui Singletons. 90% do tempo, variáveis ​​globais são introduzidas para economizar o custo de passar um parâmetro. E então acontece a codificação multithreading / teste de unidade / manutenção, e você tem um problema.

Então, sim, em 90% das situações as variáveis ​​globais são ruins. As exceções provavelmente não serão vistas por você em seus anos de faculdade. Uma exceção que posso pensar em detalhes é lidar com objetos inerentemente globais, como tabelas de interrupção. Coisas como a conexão com o banco de dados parecem ser globais, mas não são.


fonte
2
A única exceção que eu vi em meus anos de faculdade era funções gráficos call-back. No XWindows, os retornos de chamada do mouse não tinham argumentos de dados nulos * que permitiam repassar pedaços arbitrários do estado do programa ... (não que isso acabe sendo MUITO melhor do que um global de qualquer maneira ...)
Brian Postow
10
+1 em "Coisas como a conexão com o banco de dados parecem ser globais, mas não são".
R .. GitHub Pare de ajudar o gelo
1
As tabelas de interrupção não são globais, há uma por processador - mas também há uma instância do seu programa por processador para que "cancele".
user253751
1
Alguém pode me esclarecer por que as conexões com o banco de dados não são globais (e qual seria uma boa alternativa)? Eu sempre pensei nas conexões como um dos raros casos em que os globais eram aceitáveis.
Floella
33

O problema que as variáveis ​​globais criam para o programador é que ele expande a superfície de acoplamento entre componentes entre os vários componentes que estão usando as variáveis ​​globais. O que isso significa é que, à medida que o número de componentes usando uma variável global aumenta, a complexidade das interações também pode aumentar. Esse aumento no acoplamento geralmente facilita a injeção de defeitos no sistema ao fazer alterações e também dificulta o diagnóstico e a correção dos defeitos. Esse aumento de acoplamento também pode reduzir o número de opções disponíveis ao fazer alterações e pode aumentar o esforço necessário para as alterações, pois é necessário rastrear os vários módulos que também estão usando a variável global para determinar as conseqüências das alterações.

O objetivo do encapsulamento , que é basicamente o oposto do uso de variáveis ​​globais, é diminuir o acoplamento para facilitar o entendimento e a alteração da fonte, a segurança e o teste mais fácil. É muito mais fácil usar o teste de unidade quando as variáveis ​​globais não são usadas.

Por exemplo, se você tem uma variável inteira global simples que está sendo usada como um indicador enumerado que vários componentes usam como uma máquina de estado e você faz uma alteração adicionando um novo estado a um novo componente, você deve rastrear todas as outras componentes para garantir que a alteração não os afete. Um exemplo de um possível problema seria se uma switchinstrução para testar o valor da variável global de enumeração com caseinstruções para cada um dos valores atuais estivesse sendo usada em vários locais e acontece que algumas das switchinstruções não têm um defaultcaso para tratar um valor inesperado para o global, de repente, você tem um comportamento indefinido no que diz respeito ao aplicativo.

Por outro lado, o uso de uma área de dados compartilhados pode ser usado para conter um conjunto de parâmetros globais que são referenciados em todo o aplicativo. Essa abordagem geralmente é usada em aplicativos incorporados com pequenas dimensões de memória.

Ao usar variáveis ​​globais nesse tipo de aplicativo, normalmente a responsabilidade de gravar na área de dados é alocada para um único componente e todos os outros componentes veem a área como conste lida nela, nunca gravando nela. A adoção dessa abordagem limita os problemas que podem se desenvolver.

Alguns problemas de variáveis ​​globais que precisam ser contornados

Quando a origem de uma variável global, como uma struct, é modificada, tudo o que é usado deve ser recompilado para que tudo o que for usado na variável conheça seu verdadeiro tamanho e modelo de memória.

Se mais de um componente puder modificar a variável global, você poderá encontrar problemas com dados inconsistentes na variável global. Com um aplicativo multiencadeamento, você provavelmente precisará adicionar algum tipo de região crítica ou de bloqueio para fornecer uma maneira de que apenas um encadeamento de cada vez possa modificar a variável global e quando um encadeamento estiver modificando a variável, todas as alterações serão concluídas. e confirmado antes que outros threads possam consultar a variável ou modificá-la.

Depurar um aplicativo multithread que usa uma variável global pode ser mais difícil. Você pode encontrar condições de corrida que podem criar defeitos difíceis de replicar. Com vários componentes se comunicando por meio de uma variável global, especialmente em um aplicativo multithread, é muito difícil entender qual componente está alterando a variável quando e como ela está alterando a variável.

Conflito de nomes pode ser um problema com o uso de variáveis ​​globais. Uma variável local que tem o mesmo nome que uma variável global pode ocultar a variável global. Você também enfrenta o problema da convenção de nomenclatura ao usar a linguagem de programação C. Uma solução alternativa é dividir o sistema em subsistemas com as variáveis ​​globais de um subsistema específico, todas começando com as mesmas três primeiras letras (consulte isso sobre como resolver colisões de espaços de nomes no objetivo C ). O C ++ fornece espaços de nomes e, com o C, você pode contornar isso criando uma estrutura visível globalmente, cujos membros são vários itens de dados e ponteiros para dados e funções que são fornecidas em um arquivo como estático, portanto, apenas com visibilidade do arquivo, para que possam ser referenciadas apenas através a estrutura globalmente visível.

Em alguns casos, a intenção original do aplicativo é alterada para que as variáveis ​​globais que forneceram o estado de um único encadeamento sejam modificadas para permitir a execução de vários encadeamentos duplicados. Um exemplo seria um aplicativo simples projetado para um único usuário usando variáveis ​​globais para estado e, em seguida, um pedido é enviado pelo gerenciamento para adicionar uma interface REST para permitir que aplicativos remotos atuem como usuários virtuais. Portanto, agora é necessário duplicar as variáveis ​​globais e suas informações de estado para que o usuário único e cada um dos usuários virtuais de aplicativos remotos tenham seu próprio conjunto exclusivo de variáveis ​​globais.

Usando C ++ namespacee a structtécnica para C

Para a linguagem de programação C ++, a namespacediretiva é uma grande ajuda para reduzir as chances de um conflito de nomes. namespacejuntamente com classe as várias palavras-chave de acesso ( private, protected, e public) fornecem a maior parte das ferramentas necessárias para variáveis Encapsular. No entanto, a linguagem de programação C não fornece essa diretiva. Esta postagem de stackoverflow, Namespaces em C , fornece algumas técnicas para C.

Uma técnica útil é ter uma única área de dados residentes na memória, definida como uma structque tenha visibilidade global e, dentro disso, structsejam ponteiros para as várias variáveis ​​e funções globais que estão sendo expostas. As definições reais das variáveis ​​globais recebem escopo de arquivo usando a staticpalavra - chave Se você usar a constpalavra-chave para indicar quais são somente leitura, o compilador poderá ajudá-lo a impor o acesso somente leitura.

O uso da structtécnica também pode encapsular o global, para que ele se torne um tipo de pacote ou componente que passa a ser global. Por ter um componente desse tipo, fica mais fácil gerenciar alterações que afetam o global e a funcionalidade usando o global.

No entanto, enquanto namespaceou a structtécnica puder ajudar a gerenciar conflitos de nomes, ainda existem os problemas subjacentes ao acoplamento entre componentes que o uso de globais introduz especialmente em um aplicativo multithread moderno.

Richard Chambers
fonte
Esta é a melhor explicação, explica tudo o que existe. Parabéns!
Johndoevodka
Seu idioma deve ter uma regra de código para impedir que você use muito acoplamento de classe.
Melbourne Developer
20

Variáveis ​​globais são tão ruins quanto você as cria, nada menos.

Se você estiver criando um programa totalmente encapsulado, poderá usar globais. É um "pecado" usar globais, mas os pecados de programação são amplamente filosóficos.

Se você verificar L.in.oleum , verá um idioma cujas variáveis ​​são exclusivamente globais. Não é escalável, porque todas as bibliotecas não têm escolha a não ser usar globais.

Dito isto, se você tem opções e pode ignorar a filosofia do programador, os globais não são tão ruins assim.

Nem Gotos, se você usá-los corretamente.

O grande problema "ruim" é que, se você usá-los erradamente, as pessoas gritam, o Mars Lander cai e o mundo explode .... ou algo assim.

user54650
fonte
16
Subestimar os problemas do uso de globais a um aluno confuso não é uma boa idéia da IMO.
GEOCHET 27/01/09
3
A filosofia do design não é objetiva. Nem um pouco. Só porque a maioria dos programadores não gosta de algo, não significa que nunca se deva investigar isso. É fácil fazer uso geral de globais sem que o mundo acabe. Deixe-o fazer isso, lutar (sabendo que ele faria) e aprender como.
user54650
7
Rich está certo. Esta resposta não diz nada sobre o que é / não é ruim (ou como os globais podem ser usados ​​com segurança), apenas que "eles não são tão ruins quanto tudo isso. Como tal, apenas minimiza os problemas."
jalf
4
Não concordo que as variáveis ​​globais sejam tão "ruins quanto você as cria". Eu acho que um dos principais problemas, especialmente neste mundo interconectado e com vários desenvolvedores, onde a maioria de nós vive, trabalha e programa, é que variáveis ​​globais dão a alguém a oportunidade de tornar seu código ruim.
Gariepy
@gariepy até saber que embora a conversa seja sobre estática: D ok, é isso ... e meu aplicativo tem apenas uma ou duas variáveis ​​globais, essa é uma que vem com o Visual Studio, DEBUG e TRACE, que normalmente não usamos: D
deadManN
19

Sim, mas você não incorre no custo de variáveis ​​globais até parar de trabalhar no código que usa variáveis ​​globais e começar a escrever outra coisa que use o código que usa variáveis ​​globais. Mas o custo ainda está lá.

Em outras palavras, é um custo indireto de longo prazo e, como tal, a maioria das pessoas pensa que não é ruim.

MSN
fonte
19

Se for possível que seu código acabe sendo analisado intensivamente durante um julgamento na Suprema Corte , você deve evitar variáveis ​​globais.

Veja este artigo: O código do bafômetro reflete a importância da revisão da fonte

Houve alguns problemas com o estilo do código que foram identificados pelos dois estudos. Uma das questões estilísticas que preocuparam os revisores foi o uso extensivo de variáveis ​​globais desprotegidas . Isso é considerado ruim porque aumenta o risco de o estado do programa se tornar inconsistente ou de que valores sejam modificados ou substituídos inadvertidamente. Os pesquisadores também expressaram alguma preocupação com o fato de que a precisão decimal não é mantida de forma consistente em todo o código.

Cara, aposto que esses desenvolvedores desejam que não usem variáveis ​​globais!

Casey
fonte
6
Essa foi a melhor risada que já tive em um tempo. Um verdadeiro exemplo de por que o desenvolvimento de código fechado para fins lucrativos é ruim e um bom exemplo de vars globais deu errado!
Mal Spork
O que é estabelecido aqui é que variáveis ​​globais são vistas com desprezo. Não há nada aqui que mostre que variáveis ​​globais eram um problema genuíno no código. O SysTest disse que, embora o código "não tenha sido escrito de maneira consistente com as práticas recomendadas de design de software", ele ainda "produziria resultados consistentes de testes". Portanto, nenhum dano dos globais foi realmente documentado. A meu ver, eles acabaram de estabelecer que "Bem, esses desenvolvedores não praticam a mesma religião de codificação que o resto do mundo".
LionKimbro 11/11/19
17

Eu responderia a essa pergunta com outra pergunta: Você usa singeltons / singeltons são ruins?

Porque (quase todo) o uso de singelton é uma variável global glorificada.

Gavin Miller
fonte
11
Eu estava prestes a postar um comentário inteligente dizendo: "Eles só são ruins se você os chama de globais em vez de singletons", mas você me venceu.
smo
Ainda estou tentando descobrir o que diabos são os singletons.
GeoffreyF67
1
@Geoffrey: aqui estão algumas boas descrições SO - stackoverflow.com/questions/11831/... e para alguns bons links: stackoverflow.com/questions/11831/...
Gavin Miller
10
Para o registro, um singleton é uma variável global com um nome glorificado de Design Patterns (tm) (lol) para torná-lo legítimo. É igualmente ruim pelas mesmas razões.
R .. GitHub Pare de ajudar o gelo
@GavinMiller Está dizendo que está tudo bem se você usar o simplório ... ooops, eufemismo singleton?
Juan Mendes
14

O problema é menos ruim e mais perigoso . Eles têm seu próprio conjunto de prós e contras, e há situações em que são a maneira mais eficiente ou a única maneira de realizar uma tarefa específica. No entanto, eles são muito fáceis de usar incorretamente, mesmo que você tome medidas para sempre usá-las corretamente.

Alguns profissionais:

  • Pode ser acessado de qualquer função.
  • Pode ser acessado de vários threads.
  • Nunca ficará fora do escopo até o término do programa.

Alguns contras:

  • Pode ser acessado de qualquer função, sem precisar ser explicitamente arrastado como parâmetro e / ou documentado.
  • Não é seguro para threads.
  • Polui o espaço para nome global e potencialmente causa colisões de nomes, a menos que sejam tomadas medidas para evitar isso.

Observe, se você preferir, que os dois primeiros profissionais e os dois primeiros contras listados são exatamente a mesma coisa, apenas com palavras diferentes. Isso ocorre porque os recursos de uma variável global podem realmente ser úteis, mas os próprios recursos que os tornam úteis são a fonte de todos os seus problemas.

Algumas soluções possíveis para alguns dos problemas:

  • Considere se eles são realmente a melhor ou mais eficiente solução para o problema. Se houver quaisquer soluções melhores, use que em vez.
  • Coloque-os em um espaço de nome [C ++] ou struct singleton [C, C ++] com um nome exclusivo (um bom exemplo seria Globalsou GlobalVars) ou use uma convenção de nomenclatura padronizada para variáveis ​​globais (como global_[name]ou g_module_varNameStyle(como mencionado por underscore_d nos comentários) )). Isso documentará seu uso (você pode encontrar o código que usa variáveis ​​globais pesquisando o espaço para nome / nome da estrutura) e minimizar o impacto no espaço para nome global.
  • Para qualquer função que acesse variáveis ​​globais, documente explicitamente quais variáveis ​​ele lê e quais escreve. Isso facilitará a solução de problemas.
  • Coloque-os em seu próprio arquivo de origem e declare-os externno cabeçalho associado, para que seu uso possa ser limitado às unidades de compilação que precisam acessá-los. Se o seu código depende de muitas variáveis ​​globais, mas cada unidade de compilação precisa apenas acessar algumas delas, você pode classificá-las em vários arquivos de origem, para que seja mais fácil limitar o acesso de cada arquivo às variáveis ​​globais.
  • Configure um mecanismo para bloqueá-lo e desbloqueá-lo e / ou crie seu código para que o menor número possível de funções precise modificar variáveis ​​globais. Lê-los é muito mais seguro do que escrevê-los, embora as corridas de threads ainda possam causar problemas em programas multithread.
  • Basicamente, minimize o acesso a eles e maximize a exclusividade do nome. Você deseja evitar colisões de nomes e ter o menor número possível de funções que possam modificar potencialmente qualquer variável.

Se eles são bons ou ruins, depende de como você os usa. A maioria tende a usá-los mal, daí a cautela geral em relação a eles. Se usados ​​corretamente, eles podem ser um grande benefício; se usado mal, no entanto, eles podem e vai voltar a morder-lhe quando e como você menos espera.

Uma boa maneira de ver isso é que eles próprios não são ruins, mas habilitam o design incorreto e podem multiplicar os efeitos do design incorreto exponencialmente.


Mesmo que você não pretenda usá-los, é melhor saber usá-los com segurança e optar por não usá-los, do que não usá-los, porque você não sabe usá-los com segurança. Se você se encontrar em uma situação em que precisa manter um código preexistente que depende de variáveis ​​globais, poderá ter dificuldades se não souber usá-las adequadamente.

Justin Time - Restabelecer Monica
fonte
1
+1 para pragmatismo. Um singleton geralmente apenas adiciona clichê para transformar a instância e refatorar em membros, e você acaba com ... variáveis ​​globais, mascaradas com um nome diferente. Por que se preocupar, além de evitar o pecado de Globals por mero tecnicismo? Os namespaces são bons como barreira, mas acho um simples g_module_varNameStyleperfeitamente legível. Para ser claro, não estou usando globais se puder evitá-la facilmente - palavra-chave facilmente , porque desde que parei de acreditar que elas devem ser evitadas - ou melhor, ofuscadas - a todo custo, estou tendo um tempo muito melhor, e meu código é (choque!) muito mais organizado
underscore_d
@underscore_d É principalmente apenas uma maneira de diferenciar variáveis ​​globais e locais com mais facilidade, além de facilitar a localização de variáveis ​​globais ao pesquisar seu código, com a intenção de evitar confusão sobre se uma variável é global ou local / um parâmetro / um membro / etc. Uma convenção de nomenclatura padrão como a sua também funciona, desde que seja consistente. Editando minha resposta com a ideia da convenção de nomenclatura padrão, obrigado.
Justin Time - Restabelece Monica
1
"Para qualquer função ... documente explicitamente quais variáveis" - lembre-se de que esta é uma relação transitiva. Se chamadas de função A função B e C, em seguida, ele lê e escreve as variáveis escritas por ambos (mais aqueles diretamente nele do corpo)
Caleth
11

Como alguém disse (estou parafraseando) em outro tópico "Regras como essa não devem ser violadas, até que você entenda completamente as conseqüências disso".

Há momentos em que variáveis ​​globais são necessárias ou pelo menos muito úteis (por exemplo, trabalhando com retornos de chamada definidos pelo sistema). Por outro lado, eles também são muito perigosos por todos os motivos pelos quais você foi informado.

Existem muitos aspectos da programação que provavelmente devem ser deixados para os especialistas. Às vezes você precisa de uma faca muito afiada. Mas você não pode usar um até estar pronto ...

Brian Postow
fonte
1
Concordo, se você compreende as consequências, é OK a quebrar as regras, mas se você se pegar fazendo isso muitas vezes, você está fazendo algo errado
Juan Mendes
9

As variáveis ​​globais geralmente são ruins, especialmente se outras pessoas estiverem trabalhando no mesmo código e não quiserem gastar 20 minutos pesquisando todos os locais em que a variável é referenciada. E adicionar threads que modificam as variáveis ​​traz um novo nível de dores de cabeça.

As constantes globais em um espaço de nome anônimo usado em uma única unidade de tradução são excelentes e onipresentes em aplicativos e bibliotecas profissionais. Mas se os dados forem mutáveis ​​e / ou tiverem que ser compartilhados entre várias TUs, convém encapsulá-los - se não for por motivos de design, por qualquer pessoa que depure ou trabalhe com seu código.

Michel
fonte
9

Usar variáveis ​​globais é como varrer a sujeira sob um tapete. É uma solução rápida e muito mais fácil a curto prazo do que usar um recipiente de pó ou aspirador para limpá-lo. No entanto, se você acabar movendo o tapete mais tarde, terá uma grande bagunça surpresa por baixo.

gnovice
fonte
metáfora preguiçosa desprovida de contexto! = resposta
underscore_d
1
@underscore_d: Eu discordo. Esta é uma pergunta de discussão, mesmo que não esteja marcada como tal (provavelmente devido à sua idade) e, portanto, respostas como essa são perfeitamente válidas e faz questão de abordar a questão dos OPs.
Gariepy
7

As variáveis ​​globais são ruins, se permitirem que você manipule aspectos de um programa que deve ser modificado apenas localmente. No POO, os globais geralmente entram em conflito com a idéia de encapsulamento.

Leonidas
fonte
7

Acho que seu professor está tentando parar um mau hábito antes mesmo de começar.

As variáveis ​​globais têm seu lugar e, como muitas pessoas disseram, saber onde e quando usá-las pode ser complicado. Então, acho que, em vez de entrar no âmago da questão do porquê, como, quando e onde das variáveis ​​globais seu professor decidiu banir. Quem sabe, ele pode proibi-los no futuro.

bong
fonte
7

Absolutamente não. Mas usá-los mal ... isso é ruim.

Removê-los sem pensar é apenas isso ... sem sentido. A menos que você conheça as vantagens e desvantagens, é melhor ficar claro e fazer o que foi ensinado / aprendido, mas não há nada implicitamente errado com as variáveis ​​globais. Quando você entender os prós e contras, tome melhor sua própria decisão.

jheriko
fonte
3
-1 Existem inúmeras razões para advertir contra variáveis ​​globais: a maior delas para mim é que dependências ocultas e globais tornam o código de teste de qualquer maneira previsível extremamente difícil. A menos que você não valorize a capacidade de testar seu código de maneira automatizada, sugiro que variáveis ​​globais não causem nada além de dor. Além disso, em um programa bem estruturado, sempre existem alternativas.
jkp
1
o que você está dizendo é uma generalização massiva, o uso cuidadoso do estado global não impede o teste automatizado - na verdade, quase todos os aplicativos têm estado global, seja ele envolvido como instâncias alocadas dinamicamente de objetos bem encapsulados ou dados estáticos que são totalmente expostos a ele não faz diferença conceitualmente, ainda existem dependências - é exatamente como elas são codificadas.
jheriko
1
Exatamente. Eles não são tão "ruins" quanto "facilmente quebráveis", basicamente. Se você souber usá-los sem quebrar nada, e quando usá-los em vez de uma alternativa, eles podem ser úteis. Caso contrário ... nem tanto.
Justin Time - Restabelece Monica
4

Variáveis ​​globais são boas em programas pequenos, mas horríveis se usadas da mesma maneira em programas grandes.

Isso significa que você pode facilmente adquirir o hábito de usá-los enquanto aprende. É disso que seu professor está tentando protegê-lo.

Quando você é mais experiente, será mais fácil aprender quando eles estiverem bem.

Darron
fonte
4

Não, eles não são ruins. Você precisa observar o código (de máquina) produzido pelo compilador para fazer essa determinação; às vezes é muito pior usar um local do que um global. Observe também que colocar "estático" em uma variável local está basicamente tornando-o global (e cria outros problemas feios que um global real resolveria). "globais locais" são particularmente ruins.

Os Globals também oferecem controle limpo sobre o uso da memória, algo muito mais difícil de fazer com os habitantes locais. Hoje em dia isso só importa em ambientes incorporados, onde a memória é bastante limitada. Algo a saber antes de você assumir que incorporado é o mesmo que outros ambientes e assumir que as regras de programação são as mesmas em todos os aspectos.

É bom que você questione as regras que estão sendo ensinadas, a maioria delas não é pelas razões pelas quais você está sendo informado. A lição mais importante, porém, não é que essa seja uma regra a ser levada para sempre, mas essa é uma regra que deve ser respeitada para passar nesta classe e seguir em frente. Na vida, você descobrirá que, para a empresa XYZ, você terá outras regras de programação que, no final, terá que respeitar para continuar recebendo um salário. Nas duas situações, você pode argumentar sobre a regra, mas acho que você terá muito mais sorte no trabalho do que na escola. Você é apenas mais um dos muitos estudantes, seu lugar será substituído em breve, os professores não. Em um trabalho, você faz parte de uma pequena equipe de jogadores que precisam ver esse produto até o fim e nesse ambiente as regras desenvolvidas são para benefício dos membros da equipe, bem como do produto e da empresa, portanto, se todos tiverem a mesma opinião ou se, para o produto em particular, houver boas razões de engenharia para violar algo que você aprendeu na faculdade ou algum livro sobre programação genérica, venda sua ideia para a equipe e escreva-a como um método válido, se não o preferido. . Tudo é um jogo justo no mundo real.

Se você seguir todas as regras de programação ensinadas na escola ou nos livros, sua carreira em programação será extremamente limitada. É provável que você possa sobreviver e ter uma carreira frutífera, mas a amplitude e a largura dos ambientes disponíveis serão extremamente limitadas. Se você sabe como e por que a regra existe e pode defendê-la, isso é bom, se você apenas raciocinar é "porque meu professor disse isso", isso não é tão bom.

Observe que tópicos como esse são frequentemente discutidos no local de trabalho e continuarão sendo, à medida que os compiladores e processadores (e idiomas) evoluem, o mesmo ocorre com esses tipos de regras e sem defender sua posição e possivelmente receber uma lição de alguém com outra opinião que você não terá. Siga em frente.

Nesse meio tempo, basta fazer o que diz o que fala mais alto ou carrega o maior bastão (até que você seja o que mais grita e o maior).

old_timer
fonte
4
Essa é apenas outra maneira de dizer "ninguém nunca foi demitido por comprar a IBM"?
Gordon Potter
1
É bom ressaltar que, para alguns aplicativos que usam variáveis ​​globais, podem realmente facilitar o trabalho. Em geral, o uso de variáveis ​​globais é uma fonte de problemas com caminhos ocultos de acoplamento entre seções da fonte. No entanto, ter uma área de memória compartilhada referenciada como global é usada para várias implementações, como interfaces de dispositivo ou talvez uma tabela de parâmetros global contendo constantes de vários tipos ou uma tabela de salto.
Richard Chambers
4

Eu gostaria de argumentar contra o argumento de que este multi-threading torna mais difícil ou impossível por si só. Variáveis ​​globais são estado compartilhado, mas as alternativas aos globais (por exemplo, passando indicadores) também podem compartilhar estado. O problema com o multiencadeamento é como usar corretamente o estado compartilhado, não se esse estado é compartilhado por meio de uma variável global ou outra coisa.

Na maioria das vezes, quando você faz multi-threading, precisa compartilhar algo. Em um padrão produtor-consumidor, por exemplo, você pode compartilhar alguma fila de thread-safe que contenha as unidades de trabalho. E você pode compartilhá-lo porque essa estrutura de dados é segura para threads. Se essa fila é global ou não, é completamente irrelevante quando se trata de segurança de threads.

A esperança implícita expressa ao longo deste thread de que transformar um programa de single-thread para multi-thread será mais fácil quando não usar globals for ingênuo. Sim, os globais facilitam o tiro no pé, mas há muitas maneiras de se dar um tiro.

Não estou defendendo os globais, como os outros pontos ainda permanecem, meu argumento é apenas que o número de threads em um programa não tem nada a ver com escopo variável.

Andreas Haferburg
fonte
3

Sim, porque se você permitir que programadores incompetentes os usem (leia 90%, especialmente cientistas), você terá mais de 600 variáveis ​​globais espalhadas por mais de 20 arquivos e um projeto de 12.000 linhas em que 80% das funções serão anuladas, retornadas e operadas. inteiramente no estado global.

Torna-se rapidamente impossível entender o que está acontecendo a qualquer momento, a menos que você conheça todo o projeto.

wezzman
fonte
2

O uso de variáveis ​​globais realmente depende dos requisitos. Sua vantagem é que, reduz a sobrecarga de passar os valores repetidamente.

Mas seu professor está certo porque levanta questões de segurança, portanto o uso de variáveis ​​globais deve ser evitado o máximo possível. Variáveis ​​globais também criam problemas que às vezes são difíceis de depurar .

Por exemplo:-

Situações em que os valores das variáveis ​​estão sendo modificados no tempo de execução . Nesse momento, é difícil identificar qual parte do código está modificando-o e em que condições.

Mufaddal Kagda
fonte
2

Globais são bons quando se trata de configuração . Quando queremos que nossa configuração / alterações tenham um impacto global em todo o projeto .

Assim, podemos alterar uma configuração e as alterações são direcionadas para o projeto inteiro . Mas devo advertir que você teria que ser muito inteligente para usar os globais.

Maaz Rehman
fonte
1

Mais cedo ou mais tarde, você precisará alterar como essa variável é configurada ou o que acontece quando é acessada, ou você apenas precisa procurar onde ela é alterada.

É praticamente sempre melhor não ter variáveis ​​globais. Escreva os métodos de obtenção e definição da barragem e fique à vontade quando precisar deles um dia, semana ou mês depois.

Bloodboiler
fonte
1

Eu geralmente uso globais para valores que raramente são alterados, como singletons ou ponteiros de função para funções na biblioteca carregada dinamicamente. O uso de globais mutáveis ​​em aplicativos multithread tende a levar a erros difíceis de rastrear, por isso tento evitar isso como regra geral.

Usar um global em vez de passar um argumento geralmente é mais rápido, mas se você estiver escrevendo um aplicativo multithread, o que costuma fazer hoje em dia, geralmente não funciona muito bem (você pode usar a estatística de threads, mas o ganho de desempenho é questionável) .

Erik Ohlsson
fonte
1

Em aplicativos da web dentro de uma empresa, pode ser usado para manter dados específicos da sessão / janela / encadeamento / usuário no servidor por razões de otimização e preservar contra a perda de trabalho em que a conexão é instável. Como mencionado, as condições da corrida precisam ser tratadas. Usamos uma única instância de uma classe para essas informações e elas são cuidadosamente gerenciadas.

xxyzzy
fonte
1

No final do dia, seu programa ou aplicativo ainda pode funcionar, mas é uma questão de organização e compreensão completa do que está acontecendo. Se você compartilhar um valor variável entre todas as funções, pode ser difícil rastrear qual função está alterando o valor (se a função o fizer) e dificultar a depuração um milhão de vezes

alaboudi
fonte
0

segurança é menor significa que qualquer um pode manipular as variáveis ​​se elas forem declaradas globais. Para isso, veja este exemplo, se você tiver saldo como uma variável global em seu programa bancário, a função de usuário pode manipular isso e o funcionário do banco também pode manipular isso para que haja um problema. apenas o usuário deve receber a função somente leitura e retirar, mas o funcionário do banco pode adicionar o valor quando o usuário pessoalmente der o dinheiro na mesa. é assim que funciona

Vamsi Pavan Mahesh
fonte
-1

Em um aplicativo multithread, use variáveis ​​locais no lugar de variáveis ​​globais para evitar uma condição de corrida.

Uma condição de corrida ocorre quando vários threads acessam um recurso compartilhado, com pelo menos um segmento tendo acesso de gravação aos dados. Então, o resultado do programa não é previsível e depende da ordem de acessos aos dados por diferentes threads.

Mais sobre isso aqui, https://software.intel.com/en-us/articles/use-intel-parallel-inspector-to-find-race-conditions-in-openmp-based-multithreaded-code

Kiriloff
fonte
Para a posteridade: isso é parcialmente correto, na melhor das hipóteses. As "variáveis ​​locais" nesta resposta se referem às variáveis ​​locais do encadeamento , em vez das variáveis ​​locais do escopo mais comuns às quais o OP está se referindo. Os efeitos colaterais da modificação de variáveis ​​globais de maneira insegura por encadeamento são muito diferentes daqueles da mudança de estado global de maneira não simultânea.
Jules