Acabei de me deparar com essa pergunta antiga, perguntando o que há de tão ruim no estado global, e a resposta aceita mais votada afirma que você não pode confiar em nenhum código que funcione com variáveis globais, porque algum outro código em outro lugar pode aparecer e modificar sua valor e então você não sabe qual será o comportamento do seu código, porque os dados são diferentes! Mas quando olho para isso, não posso deixar de pensar que essa é uma explicação realmente fraca, porque é que isso é diferente de trabalhar com dados armazenados em um banco de dados?
Quando seu programa está trabalhando com dados de um banco de dados, você não se importa se outro código do seu sistema está alterando-o ou mesmo se um programa completamente diferente está alterando-o. Você não se importa com o que são os dados; esse é o ponto inteiro. Tudo o que importa é que seu código lide corretamente com os dados encontrados. (Obviamente, estou discutindo a questão muitas vezes espinhosa do armazenamento em cache aqui, mas vamos ignorá-lo por enquanto.)
Mas se os dados com os quais você está trabalhando são provenientes de uma fonte externa sobre a qual seu código não tem controle, como um banco de dados (ou entrada do usuário ou soquete de rede ou arquivo etc.) e não há nada errado com isso, então como os dados globais dentro do próprio código - sobre os quais seu programa tem um controle muito maior - de alguma forma são ruins quando obviamente são bem menos ruins do que coisas perfeitamente normais que ninguém vê como um problema?
Respostas:
Primeiro, eu diria que a resposta que você vincula para exagerar essa questão em particular e que o principal mal do estado global é que ele introduz acoplamentos de maneiras imprevisíveis que podem dificultar a alteração do comportamento do seu sistema no futuro.
Mas, aprofundando-se nessa questão, existem diferenças entre o estado global em um aplicativo orientado a objetos típico e o estado mantido em um banco de dados. Resumidamente, os mais importantes são:
Os sistemas orientados a objetos permitem substituir um objeto por uma classe de objeto diferente, desde que seja um subtipo do tipo original. Isso permite que o comportamento seja alterado, não apenas dados .
O estado global em um aplicativo normalmente não fornece as garantias consistentes de um banco de dados - não há transações nas quais você vê um estado consistente, nenhuma atualização atômica etc.
Além disso, podemos ver o estado do banco de dados como um mal necessário; é impossível eliminá-lo de nossos sistemas. O estado global, no entanto, é desnecessário. Nós podemos eliminá-lo completamente. Mesmo que os problemas com um banco de dados sejam igualmente ruins, ainda podemos eliminar alguns dos problemas em potencial e uma solução parcial é melhor do que nenhuma solução.
fonte
Primeiro, quais são os problemas com variáveis globais, com base na resposta aceita à pergunta que você vinculou?
Os bancos de dados são, na grande maioria das vezes, compatíveis com ACID. O ACID aborda especificamente os problemas subjacentes que tornariam um armazenamento de dados imprevisível ou não confiável.
Isso ocorre porque as variáveis globais existem em um escopo distante de seu uso, talvez até em um arquivo diferente. Ao usar um banco de dados, você está usando um conjunto de registros ou objeto ORM local para o código que está lendo (ou deveria ser).
Os drivers de banco de dados geralmente fornecem uma interface consistente e compreensível para acessar dados iguais, independentemente do domínio do problema. Quando você obtém dados de um banco de dados, seu programa possui uma cópia dos dados. As atualizações são atômicas. Contraste para variáveis globais, em que vários threads ou métodos podem estar operando no mesmo pedaço de dados sem atomicidade, a menos que você adicione a sincronização. As atualizações dos dados são imprevisíveis e difíceis de rastrear. As atualizações podem ser intercaladas, causando exemplos de livros didáticos padrão de corrupção de dados multithread (por exemplo, incrementos intercalados).
Os bancos de dados geralmente modelam dados diferentes das variáveis globais, mas deixando de lado por um momento, os bancos de dados são projetados desde o início para serem um armazenamento de dados compatível com ACID que atenua muitas das preocupações com variáveis globais.
fonte
Eu daria algumas observações:
Sim, um banco de dados é um estado global.
De fato, é um estado super global, como você apontou. É universal! Seu escopo envolve qualquer coisa ou qualquer pessoa que se conecte ao banco de dados. E suspeito que muitas pessoas com anos de experiência possam contar histórias de horror sobre como "coisas estranhas" nos dados levaram a "comportamento inesperado" em um ou mais aplicativos relevantes ...
Uma das possíveis conseqüências do uso de uma variável global é que dois "módulos" distintos usarão essa variável para seus próprios propósitos distintos. E nessa medida, uma tabela de banco de dados não é diferente. Pode ser vítima do mesmo problema.
Hmm ... Aqui está a coisa:
Se um módulo não operar extrinsecamente de alguma forma, não fará nada.
Um módulo útil pode receber dados ou pode encontrá- los. E, pode retornar dados ou pode modificar o estado. Mas, se não interagir de alguma maneira com o mundo externo, poderá não fazer nada.
Agora, nossa preferência é receber dados e retornar dados. A maioria dos módulos é simplesmente mais fácil de escrever se eles puderem ser escritos com total desconsideração pelo que o mundo exterior está fazendo. Mas, finalmente, algo precisa encontrar os dados e modificar esse estado externo global.
Além disso, em aplicativos do mundo real, os dados existem para que possam ser lidos e atualizados por várias operações. Alguns problemas são evitados por bloqueios e transações. Porém, impedir que essas operações entrem em conflito umas com as outras em princípio , no final do dia, envolve simplesmente um pensamento cuidadoso. (E cometer erros ...)
Mas também, geralmente não estamos trabalhando diretamente com o estado global.
A menos que o aplicativo esteja na camada de dados (no SQL ou o que for), os objetos com os quais nossos módulos trabalham são na verdade cópias do estado global compartilhado. Podemos fazer o que quisermos, sem qualquer impacto no estado compartilhado real.
E, nos casos em que precisamos alterar esse estado global, sob a suposição de que os dados que recebemos não foram alterados, geralmente podemos executar o mesmo tipo de bloqueio que faríamos em nossos globais locais.
E, finalmente, que costumamos fazer coisas diferentes com bases de dados do que pode com globals impertinentes.
Um global impertinente e quebrado se parece com isso:
Simplesmente não usamos bancos de dados para coisas em processo / operacionais como essa. E pode ser a natureza lenta do banco de dados e a relativa conveniência de uma variável simples que nos detém: nossa interação lenta e desajeitada com os bancos de dados simplesmente os torna maus candidatos a muitos dos erros que cometemos historicamente com variáveis.
fonte
Não concordo com a afirmação fundamental de que:
Meu pensamento inicial foi "Uau. Apenas Uau". Despende muito tempo e esforço tentando evitar exatamente isso - e calculando quais compensações e compromissos funcionam para cada aplicativo. Ignorar é uma receita para o desastre.
Mas eu também tenho diplomas em nível arquitetural. Uma variável global não é apenas um estado global. É um estado global que pode ser acessado de qualquer lugar de forma transparente. Ao contrário de usar um banco de dados, você precisa ter um identificador para ele - (a menos que você armazene um identificador em uma variável global ...)
Por exemplo, o uso de uma variável global pode se parecer com isso
Mas fazer o mesmo com um banco de dados teria que ser mais explícito sobre o que está fazendo
O banco de dados obviamente está mexendo com um banco de dados. Se você não quiser usar um banco de dados, poderá usar um estado explícito e parecer quase o mesmo que o caso do banco de dados.
Então, eu diria que usar um banco de dados é muito mais como usar estado explícito do que usar variáveis globais.
fonte
MakeNewThing
dependeMakeNewThingInDb
e minha classe de controlador usaMakeNewThing
, não está claro no código no meu controlador que estou modificando o banco de dados. Então, e se eu usar outra classe que realmente confirme minha transação atual no banco de dados? O DI torna muito difícil controlar o escopo de um objeto.O ponto em que a única razão pela qual as variáveis globais não podem ser confiáveis, uma vez que o estado pode ser alterado em outro lugar, não é, por si só, razão suficiente para não usá-las, concordou (é uma boa razão!). É provável que a resposta tenha sido principalmente descrever o uso em que restringir o acesso de uma variável apenas às áreas de código com as quais faria sentido faria mais sentido.
Os bancos de dados são uma questão diferente, no entanto, porque são projetados com o objetivo de serem acessados "globalmente", por assim dizer.
Por exemplo:
Mais importante ainda, os bancos de dados têm um propósito diferente de uma variável global. Os bancos de dados são para armazenar e pesquisar grandes quantidades de dados organizados, onde variáveis globais atendem a nichos específicos (quando justificáveis).
fonte
Ou diferente de trabalhar com um dispositivo interativo, com um arquivo, com memória compartilhada etc. Um programa que faz exatamente a mesma coisa sempre que é executado é um programa muito chato e bastante inútil. Então, sim, é um argumento fraco.
Para mim, a diferença que faz a diferença em relação às variáveis globais é que elas formam linhas de comunicação ocultas e desprotegidas. Ler de um teclado é muito óbvio e protegido. Preciso fazer uma determinada chamada de função e não consigo acessar o driver do teclado. O mesmo se aplica ao acesso a arquivos, memória compartilhada e seu exemplo, bancos de dados. É óbvio para o leitor do código que essa função lê no teclado, que acessa um arquivo, alguma outra função acessa a memória compartilhada (e é melhor haver proteções a esse respeito), e ainda outra função acessa um banco de dados.
Com variáveis globais, por outro lado, não é nada óbvio. A API diz para ligar
foo(this_argument, that_argument)
. Não há nada na sequência de chamada que diga que a variável globalg_DangerWillRobinson
deve ser definida com algum valor, mas antes da chamadafoo
(ou examinada após a chamadafoo
).O Google proibiu o uso de argumentos de referência não constantes no C ++, principalmente porque não é óbvio para o leitor o código que
foo(x)
será alterado,x
porque issofoo
exige uma referência não constante como argumento. (Compare com o C #, que determina que tanto a definição da função quanto o site de chamada devem qualificar um parâmetro de referência com aref
palavra - chave.) Embora eu não concorde com o padrão do Google sobre isso, entendo seu ponto de vista.O código é escrito uma vez e modificado algumas vezes, mas se for bom, é lido muitas e muitas vezes. Linhas ocultas de comunicação são um karma muito ruim. A referência não-const do C ++ representa uma pequena linha oculta de comunicação. Uma boa API ou um bom IDE me mostrará que "Oh! Isso é chamado por referência". Variáveis globais são uma enorme linha oculta de comunicação.
fonte
Penso que a explicação citada simplifica demais a questão até o ponto em que o raciocínio se torna ridículo. Obviamente, o estado de um banco de dados externo contribui para o estado global. A questão importante é comoseu programa depende do estado global (mutável). Se uma função de biblioteca para dividir seqüências de caracteres no espaço em branco dependeria dos resultados intermediários armazenados em um banco de dados, eu objetaria a esse design pelo menos tanto quanto objetaria uma matriz global de caracteres usada para o mesmo objetivo. Por outro lado, se você decidir que seu aplicativo não precisa de um DBMS completo para armazenar dados de negócios neste momento e uma estrutura global de valores-chave na memória funcionará, isso não é necessariamente um sinal de design inadequado. O que é importante é que - independentemente da solução escolhida para armazenar seus dados - essa opção é isolada em uma porção muito pequena do sistema, para que a maioria dos componentes possa ser independente da solução escolhida para implantação e testada por unidade isoladamente e implantada. solução pode ser alterada posteriormente com pouco esforço.
fonte
Como engenheiro de software que trabalha predominantemente com firmware incorporado, quase sempre estou usando variáveis globais para qualquer coisa entre os módulos. Na verdade, é uma prática recomendada para incorporado. Eles são atribuídos estaticamente, portanto não há risco de explodir a pilha / pilha e não há tempo extra para alocação / limpeza de pilha na entrada / saída da função.
A desvantagem desta situação é que nós não temos que considerar como essas variáveis são usadas, e um monte de que vem para baixo para o mesmo tipo de pensamento que vai para banco de dados disputas. Qualquer leitura / gravação assíncrona de variáveis DEVE ser atômica. Se mais de um local puder gravar uma variável, é necessário pensar em garantir que eles sempre gravem dados válidos, para que a gravação anterior não seja arbitrariamente substituída (ou que a substituição arbitrária seja uma coisa segura a ser feita). Se a mesma variável for lida mais de uma vez, deve-se considerar o que acontece se a variável alterar o valor entre as leituras ou uma cópia da variável deve ser tirada no início para que o processamento seja feito usando um valor consistente, mesmo se esse valor se torna obsoleto durante o processamento.
(No último dia, no meu primeiro dia de contrato trabalhando em um sistema de contramedidas de aeronaves, tão altamente relacionado à segurança, a equipe de software estava analisando um relatório de bug que tentava descobrir há uma semana. Eu tinha tido tempo suficiente para baixar as ferramentas de desenvolvimento e uma cópia do código. Perguntei "essa variável não pode ser atualizada entre leituras e causá-la?", Mas realmente não recebi uma resposta. Ei, o que o afinal, enquanto eles ainda estavam discutindo, eu adicionei um código de proteção para ler a variável atomicamente, fiz uma compilação local e basicamente disse "ei pessoal, tente isso". Maneira de provar que valho minha taxa de contratação . :)
Portanto, as variáveis globais não são uma coisa inequivocamente ruim, mas deixam você aberto a uma ampla gama de questões, se você não pensar nelas com cuidado.
fonte
Dependendo do aspecto que você está julgando, as variáveis globais e o acesso ao banco de dados podem ser diferentes, mas enquanto os julgamos como dependências, eles são os mesmos.
Vamos considerar a definição de uma função pura pela programação funcional que deve depender apenas dos parâmetros que ela recebe como entradas, produzindo uma saída determinística. Ou seja, dado o mesmo conjunto de argumentos duas vezes, ele deve produzir o mesmo resultado.
Quando uma função depende de uma variável global, ela não pode mais ser considerada pura, pois, para o mesmo conjunto ou argumentos, pode produzir resultados diferentes, pois o valor da variável global pode ter sido alterado entre as chamadas.
No entanto, a função ainda pode ser vista como determinística se considerarmos a variável global como parte da interface da função e seus outros argumentos, portanto não é o problema. O problema é apenas que isso fica oculto até o momento em que somos surpreendidos por um comportamento inesperado de funções aparentemente óbvias; em seguida, leia suas implementações para descobrir as dependências ocultas .
Nesta parte, o momento em que uma variável global se torna uma dependência oculta é o que é considerado mau por nós, programadores. Torna o código mais difícil de raciocinar, difícil de prever como ele se comportará, difícil de reutilizar, difícil de testar e, principalmente, aumenta o tempo de depuração e correção quando ocorre um problema.
O mesmo acontece quando ocultamos a dependência no banco de dados. Podemos ter funções ou objetos fazendo chamadas diretas para consultas e comandos do banco de dados, ocultando essas dependências e causando-nos exatamente o mesmo problema que as variáveis globais causam; ou podemos explicitá-los, o que, como se vê, é considerado uma prática recomendada com muitos nomes, como padrão de repositório, armazenamento de dados, gateway etc.
PS: Existem outros aspectos importantes para essa comparação, como se a concorrência está envolvida, mas esse ponto é abordado por outras respostas aqui.
fonte
Ok, vamos começar do ponto histórico.
Estamos em um aplicativo antigo, escrito em sua combinação típica de montagem e C. Não há funções, apenas procedimentos . Quando você deseja passar um argumento ou retornar valor de um procedimento, você usa uma variável global. Escusado será dizer que é muito difícil acompanhar e, em geral, todo procedimento pode fazer o que quiser com cada variável global. Sem surpresa, as pessoas passaram a passar argumentos e retornar valores de uma maneira diferente assim que possível (a menos que fosse crítico para o desempenho não fazê-lo - por exemplo, consulte o código-fonte do Build Engine (Duke 3D)). O ódio das variáveis globais nasceu aqui - você tinha muito pouca ideia de qual parte do estado global cada procedimento leria e mudaria e não era possível aninhar chamadas de procedimentos com segurança.
Isso significa que o ódio à variável global é coisa do passado? Nem tanto.
Primeiro, devo mencionar que vi exatamente a mesma abordagem para transmitir argumentos no projeto em que estou trabalhando agora. Para passar duas instâncias do tipo de referência em C #, em um projeto com cerca de 10 anos de idade. Não há literalmente uma boa razão para fazer isso dessa maneira, e provavelmente nasceu do cultivo de carga ou de um completo mal-entendido de como o C # funciona.
O ponto mais importante é que, ao adicionar variáveis globais, você está expandindo o escopo de cada parte do código que tem acesso a essa variável global. Lembre-se de todas as recomendações como "mantenha seus métodos curtos"? Se você possui 600 variáveis globais (novamente, exemplo do mundo real: /), todos os seus escopos de método são implicitamente expandidos por essas 600 variáveis globais e não há uma maneira simples de acompanhar quem tem acesso a quê.
Se feito errado (da maneira usual :)), variáveis globais podem ter acoplamento entre si. Mas você não tem idéia de como eles são acoplados, e não há mecanismo para garantir que o estado global seja sempre consistente. Mesmo se você introduzir seções críticas para tentar manter as coisas consistentes, verá que ele se compara mal a um banco de dados ACID adequado:
É possível resolver esses problemas? Na verdade não. Você precisa de um encapsulamento para lidar com isso, ou uma disciplina realmente estrita. É difícil fazer as coisas direito, e isso geralmente não é uma receita muito boa para o sucesso no desenvolvimento de software :)
Escopos menores tendem a facilitar o raciocínio do código. As variáveis globais fazem com que até mesmo as partes mais simples do código incluam enormes faixas de escopo.
Obviamente, isso não significa que o escopo global seja ruim. Apenas não deve ser a primeira solução que você procura - é um exemplo típico de "simples de implementar, difícil de manter".
fonte
Uma variável global é uma ferramenta, pode ser usada para o bem e para o mal.
Um banco de dados é uma ferramenta, pode ser usado para o bem e para o mal.
Como observa o pôster original, a diferença não é tão grande assim.
Os estudantes inexperientes costumam pensar que erros são algo que acontece com outras pessoas. Os professores usam "As variáveis globais são más" como uma razão simplificada para penalizar o mau design. Os alunos geralmente não entendem que, apenas porque seu programa de 100 linhas é livre de bugs, não significa que os mesmos métodos possam ser usados para programas de 10000 linhas.
Quando você trabalha com bancos de dados, não pode simplesmente banir o estado global, pois é disso que trata o programa. Em vez disso, você obtém diretrizes mais detalhadas, como ACID e Formulários normais, etc.
Se as pessoas usassem a abordagem ACID para variáveis globais, elas não seriam tão ruins.
Por outro lado, se você criar mal bancos de dados, eles podem ser pesadelos.
fonte
Para mim, o principal mal é que os Globals não têm proteção contra problemas de concorrência. Você pode adicionar mecanismos para lidar com esses problemas com o Globals, mas descobrirá que quanto mais problemas de simultaneidade resolver, mais o Globals começará a imitar um banco de dados. O mal secundário não é um contrato de uso.
fonte
errno
em C.Algumas das outras respostas tentam explicar por que usar um banco de dados é bom. Eles estão errados! Um banco de dados é um estado global e, como tal, é tão ruim quanto um singleton ou uma variável global. É errado usar um banco de dados quando você pode facilmente usar um mapa ou uma matriz local!
Variáveis globais permitem acesso global, o que acarreta risco de abuso. Variáveis globais também têm vantagens. Dizem que as variáveis globais são algo que você deve evitar, e não algo que você nunca deve usar. Se você pode evitá-los facilmente, deve evitá-los. Mas se os benefícios superam os inconvenientes, é claro que você deve usá-los! *
A mesma coisa ** se aplica aos bancos de dados, que são estados globais - assim como as variáveis globais. Se você pode se contentar sem acessar um banco de dados, e a lógica resultante faz tudo o que você precisa e é igualmente complexo, o uso de um banco de dados aumenta o risco do seu projeto, sem nenhum benefício correspondente.
Na vida real, muitos aplicativos exigem estado global por design, às vezes até estado global persistente - é por isso que temos arquivos, bancos de dados etc.
* A exceção aqui são os alunos. Faz sentido proibir os alunos de usar variáveis globais para que eles tenham que aprender quais são as alternativas.
** Algumas respostas afirmam incorretamente que os bancos de dados estão de alguma forma melhor protegidos do que outras formas de estado global (a pergunta é explicitamente sobre estado global , não apenas variáveis globais). Isso é besteira. A proteção primária oferecida no cenário do banco de dados é por convenção, que é exatamente a mesma para qualquer outro estado global. A maioria dos idiomas também permite muita proteção adicional para o estado global, na forma de
const
classes que simplesmente não permitem alterar seu estado após a configuração no construtor, ou getters e setters que podem levar em consideração as informações do encadeamento ou o estado do programa.fonte
Em certo sentido, a distinção entre variáveis globais e um banco de dados é semelhante à distinção entre membros públicos e privados de um objeto (supondo que alguém ainda use campos públicos). Se você pensa em todo o programa como um objeto, as globais são as variáveis privadas e o banco de dados são os campos públicos.
A principal diferença aqui é uma das responsabilidades assumidas.
Quando você escreve um objeto, supõe-se que qualquer pessoa que mantenha os métodos de membro garantirá que os campos privados permaneçam bem comportados. Mas você já desiste de quaisquer suposições sobre o estado dos campos públicos e os trata com cuidado extra.
A mesma suposição se aplica em um nível mais amplo ao banco de dados global v / s. Além disso, a linguagem / ecossistema de programação garante restrições de acesso ao público v / s público da mesma forma que as aplica no banco de dados global (memória não compartilhada) v / s globais.
Quando o multithreading entra em cena, o conceito de banco de dados público / virtual global v / s privado v / s é meramente distinções ao longo de um espectro.
fonte
Um banco de dados pode ser um estado global, mas não precisa ser o tempo todo. Eu discordo da suposição de que você não tem controle. Uma maneira de gerenciar isso é o bloqueio e a segurança. Isso pode ser feito no registro, tabela ou banco de dados inteiro. Outra abordagem é ter algum tipo de campo de versão que impeça a alteração de um registro se os dados estiverem obsoletos.
Como uma variável global, os valores em um banco de dados podem ser alterados depois que eles são desbloqueados, mas existem várias maneiras de controlar o acesso (não dê a todos os desenvolvedores a senha da conta com permissão para alterar dados.). Se você tem uma variável que tem acesso limitado, não é muito global.
fonte
Existem várias diferenças:
Um valor do banco de dados pode ser modificado em tempo real. O valor de um global definido no código, por outro lado, não pode ser alterado, a menos que você reimplemente seu aplicativo e modifique seu código. De fato, isso é intencional. Um banco de dados é para valores que podem mudar com o tempo, mas as variáveis globais devem ser apenas para itens que nunca mudarão e quando não contiverem dados reais.
Um valor do banco de dados (linha, coluna) possui um contexto e um mapeamento relacional no banco de dados. Essa relação pode ser facilmente extraída e analisada usando ferramentas como o Jailer (por exemplo). Uma variável global, por outro lado, é um pouco diferente. Você pode encontrar todos os usos, mas seria impossível você me dizer todas as maneiras pelas quais a variável interage com o resto do seu mundo.
Variáveis globais são mais rápidas . Obter algo de um banco de dados requer que uma conexão com o banco de dados seja feita, uma seleção para mim ser executada e a conexão com o banco de dados deve ser fechada. Quaisquer conversões de tipos que você possa precisar vêm além disso. Compare isso com um global que está sendo acessado no seu código.
Estes são os únicos que consigo pensar agora, mas tenho certeza de que existem mais. Simplificando, são duas coisas diferentes e devem ser usadas para objetivos diferentes .
fonte
É claro que os globais nem sempre são inadequados. Eles existem porque têm um uso legítimo. O principal problema com os globais, e a principal fonte de advertência para evitá-los, é que o código que usa um global é anexado a esse e apenas um global.
Por exemplo, considere um servidor HTTP armazenando o nome do servidor.
Se você armazenar o nome do servidor em um global, o processo não poderá executar simultaneamente a lógica para dois nomes diferentes. Talvez o design original nunca tenha pensado em executar mais de uma instância do servidor por vez, mas se você decidir mais tarde fazer isso, simplesmente não poderá se o nome do servidor for global.
Por outro lado, se o nome do servidor estiver em um banco de dados, não há problema. Você pode simplesmente criar uma instância desse banco de dados para cada instância do servidor HTTP. Como cada instância do servidor possui sua própria instância do banco de dados, ele pode ter seu próprio nome de servidor.
Portanto, a principal objeção às globais, pode haver apenas um valor para todo o código que acessa essa global, não se aplica às entradas do banco de dados. O mesmo código pode acessar facilmente instâncias de banco de dados distintas que possuem valores diferentes para uma entrada específica.
fonte
Eu acho que essa é uma pergunta interessante, mas é um pouco difícil de responder, porque há duas questões principais que estão sendo conflitadas sob o termo 'estado global'. O primeiro é o conceito de 'acoplamento global'. A prova disso é que a alternativa dada ao estado global é a injeção de dependência. O fato é que o DI não elimina necessariamente o estado global. Ou seja, é absolutamente possível e comum injetar dependências no estado global. O que o DI faz é remover o acoplamento que acompanha as variáveis globais e o padrão Singleton comumente usado. Além de um design um pouco menos óbvio, há muito pouca desvantagem em eliminar esse tipo de acoplamento e os benefícios de eliminar o acoplamento aumentam exponencialmente com o número de dependências desses globais.
O outro aspecto disso é o estado compartilhado. Não tenho certeza se existe uma distinção clara entre estado compartilhado globalmente e estado compartilhado em geral, mas os custos e benefícios são muito mais variados. Simplificando, existem inúmeros sistemas de software que exigem que o estado compartilhado seja útil. O Bitcoin, por exemplo, é uma maneira muito inteligente de compartilhar o estado globalmente (literalmente) de uma maneira descentralizada. Compartilhar o estado mutável corretamente sem criar grandes gargalos é difícil, mas útil. Portanto, se você realmente não precisar fazer isso, poderá simplificar seu aplicativo minimizando o estado mutável compartilhado.
Portanto, a questão de como os bancos de dados diferem dos globais também é bifurcada nesses dois aspectos. Eles introduzem acoplamento? Sim, eles podem, mas isso depende muito de como o aplicativo é projetado e como o banco de dados é projetado. Existem muitos fatores para ter uma resposta única para saber se os bancos de dados apresentam acoplamento global sem detalhes do design. Quanto à introdução de compartilhamento de estado, esse é o principal ponto de um banco de dados. A questão é se eles fazem isso bem. Mais uma vez, acho que é muito complicado responder sem muitas outras informações, como as alternativas e muitas outras compensações.
fonte
Eu pensaria um pouco diferente: o "comportamento da variável global" é um preço pago pelos administradores de banco de dados (DBAs) porque é um mal necessário fazer o trabalho deles.
O problema com variáveis globais, como várias outras apontaram, não é arbitrário. O problema é que o uso deles torna o comportamento do seu programa cada vez menos previsível, porque fica mais difícil determinar quem está usando a variável e de que maneira. Esse é um grande problema para o software moderno, porque normalmente é solicitado que o software moderno faça muitas coisas flexíveis. Pode fazer bilhões ou mesmo trilhões de manipulações complexas de estado durante o decorrer de uma corrida. A capacidade de provar declarações verdadeiras sobre o que esse software fará nesses bilhões ou trilhões de operações é extremamente valiosa.
No caso de software moderno, todos os nossos idiomas fornecem ferramentas para ajudá-lo, como o encapsulamento. A escolha de não usá-lo é desnecessária, o que leva à mentalidade "global é má". Em muitas regiões do campo de desenvolvimento de software, as únicas pessoas que os utilizam são pessoas que não sabem como codificar melhor. Isso significa que eles não apenas têm problemas diretamente, mas indiretamente sugerem que o desenvolvedor não sabia o que estava fazendo. Em outras regiões, você verá que os globais são totalmente normais (o software incorporado, em particular, adora os globais, em parte porque eles funcionam bem com ISRs). No entanto, entre os muitos desenvolvedores de software existentes, eles são a voz minoritária; portanto, a única voz que você ouve é "os globais são maus".
O desenvolvimento de banco de dados é uma dessas situações de voz minoritária. As ferramentas necessárias para o trabalho do DBA são muito poderosas e sua teoria não está enraizada no encapsulamento. Para obter cada instante de desempenho de seus bancos de dados, eles precisam de acesso total e irrestrito a tudo, semelhante aos globais. Use um dos seus monstruosos bancos de dados de 100 milhões de linhas (ou mais!) E você entenderá por que eles não deixam seu mecanismo de banco de dados dar nenhum soco.
Eles pagam um preço por isso, um preço caro. Os DBAs são forçados a ser quase patológicos com sua atenção aos detalhes, porque suas ferramentas não os protegem. O melhor que eles têm em termos de proteção é o ACID ou talvez as chaves estrangeiras. Aqueles que não são patológicos encontram-se com uma bagunça total de tabelas que é completamente inutilizável, ou mesmo corrompida.
Não é incomum ter pacotes de software de 100 mil linhas. Em teoria, qualquer linha do software pode afetar qualquer global a qualquer momento. Nos DBAs, você nunca encontra 100 mil consultas diferentes que podem modificar o banco de dados. Isso não seria razoável manter com a atenção aos detalhes necessários para protegê-lo de si mesmo. Se um DBA tiver algo grande assim, ele intencionalmente encapsulará seu banco de dados usando acessadores, evitando os problemas "globais" e, em seguida, fará o máximo de trabalho possível com esse mecanismo "mais seguro". Assim, quando o push chega ao ponto, mesmo as pessoas do banco de dados evitam globais. Eles simplesmente vêm com muito perigo, e existem alternativas igualmente fortes, mas não tão perigosas.
Você prefere andar em cacos de vidro ou em calçadas bem varridas, se todas as outras coisas forem iguais? Sim, você pode andar em vidro quebrado. Sim, algumas pessoas ainda ganham a vida fazendo isso. Mas, ainda assim, deixe-os varrer a calçada e seguir em frente!
fonte
Eu acho que a premissa é falsa. Não há razão para que um banco de dados precise ser "estado global" em vez de um objeto de contexto (muito grande). Se você está vinculando o banco de dados específico que seu código está usando por meio de variáveis globais ou de parâmetros fixos de conexão com o banco de dados global, não é diferente nem menos mau do que qualquer outro estado global. Por outro lado, se você transmitir adequadamente um objeto de contexto para a conexão com o banco de dados, é apenas um estado contextual grande (e amplamente usado), não um estado global.
Medir a diferença é fácil: você poderia executar duas instâncias da lógica do seu programa, cada uma usando seu próprio banco de dados, em um único programa / processo sem fazer alterações invasivas no código? Nesse caso, seu banco de dados não é realmente "estado global".
fonte
Globais não são maus; eles são simplesmente uma ferramenta. O mau uso de globais é problemático, assim como o mau uso de qualquer outro recurso de programação.
Minha recomendação geral é que os globais sejam usados apenas em situações bem compreendidas e pensadas, nas quais outras soluções são menos ideais. Mais importante, você deseja garantir que esteja bem documentado onde esse valor global pode ser modificado e, se estiver executando multithread, que esteja garantindo que o global e quaisquer globais co-dependentes sejam acessados de maneira transacional.
fonte
Somente leitura e assuma que seus dados não estão atualizados quando você os imprime. A fila grava ou manipula conflitos de outra maneira. Bem-vindo ao diabo do inferno, você está usando db global.
fonte