Como os globals são diferentes de um banco de dados?

247

Eu simplesmente deparei com esta velha pergunta perguntando o que é tão maligno sobre o estado global, e a resposta mais votada e aceita 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 seu 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 é diferente de trabalhar com dados armazenados? em um banco de dados?

Quando o seu programa está trabalhando com dados de um banco de dados, você não se importa se outro código em seu sistema está alterando-o, ou mesmo se um programa totalmente diferente está alterando-o, para esse assunto. Você não se importa com os dados; esse é o ponto inteiro. Tudo o que importa é que o código lida corretamente com os dados que encontra. (Obviamente estou encobrindo a questão espinhosa do cache aqui, mas vamos ignorar isso no momento.)

Mas se os dados com os quais você está trabalhando forem provenientes de uma fonte externa sobre a qual o seu código não tem controle, como um banco de dados (ou entrada do usuário, um soquete de rede ou um arquivo etc.) e não há nada de errado com isso, então como os dados globais dentro do próprio código - sobre o qual seu programa tem um controle muito maior - de alguma forma, uma coisa ruim quando é obviamente menos ruim do que coisas perfeitamente normais que ninguém vê como problema?

    
por Mason Wheeler 24.05.2016 / 21:42
fonte

22 respostas

117
Primeiro, eu diria que a resposta que você liga para exagerar esse problema em particular e que o principal mal do estado global é que ele introduz o acoplamento de maneiras imprevisíveis que podem dificultar a mudança do comportamento do seu sistema no futuro.

Mas, aprofundando essa questão, há diferenças entre o estado global em um aplicativo típico orientado a objeto 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, e não apenas dados .

  • O estado global em um aplicativo normalmente não fornece as garantias consistentes de consistência que um banco de dados faz - não há transações durante as quais você vê um estado consistente para ele, sem atualizações atômicas, 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. Assim, mesmo que os problemas com um banco de dados fossem tão ruins, ainda podemos eliminar alguns dos possíveis problemas e uma solução parcial é melhor do que nenhuma solução.

    
por 24.05.2016 / 22:05
fonte
75

Primeiro, quais são os problemas com as variáveis globais, com base na resposta aceita para a pergunta que você vinculou?

Very briefly, it makes program state unpredictable.

Bancos de dados são, na maior parte do tempo, compatíveis com ACID. O ACID aborda especificamente os problemas subjacentes que tornariam um armazenamento de dados imprevisível ou não confiável.

Further, global state hurts the readability of your code.

Isso ocorre porque as variáveis globais existem em um escopo longe de seu uso, talvez até mesmo em um arquivo diferente. Ao usar um banco de dados, você está usando um conjunto de registros ou um objeto ORM que é local para o código que você está lendo (ou deveria ser).

Os drivers de banco de dados normalmente fornecem uma interface consistente e compreensível para acessar dados que são os mesmos, independentemente do domínio do problema. Quando você obtém dados de um banco de dados, seu programa possui uma cópia dos dados. Atualizações são atômicas. Contraste com variáveis globais, em que vários segmentos ou métodos podem estar operando na mesma parte de dados, sem nenhuma atomicidade, a menos que você mesmo adicione a sincronização. Atualizações nos dados são imprevisíveis e difíceis de rastrear. As atualizações podem ser intercaladas, causando exemplos de livros didáticos padrão burl de corrupção de dados multithread (por exemplo, incrementos intercalados).

Basicamente, os bancos de dados modelam dados diferentes das variáveis globais, mas deixando isso de lado por um momento, os bancos de dados são projetados do zero para serem um armazenamento de dados compatível com ACID que mitiga muitas das preocupações com variáveis globais. / p>     
por 24.05.2016 / 22:11
fonte
44

Eu ofereço algumas observações:

Sim, um banco de dados é um estado global.

Na verdade, é um estado super global, como você apontou. É universal! Seu escopo envolve qualquer coisa ou qualquer pessoa que se conecte ao banco de dados. E eu suspeito que muitas pessoas com anos de experiência podem contar histórias de horror sobre como "coisas estranhas" nos dados levaram a um "comportamento inesperado" em um ou mais dos aplicativos relevantes ...

Uma das conseqüências potenciais 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 opera extrinsecamente de alguma forma, ele não faz nada.

Um módulo útil pode ser dado ou pode encontrá-lo . E, pode retornar dados ou pode modificar estado. Mas, se não interagir de alguma forma com o mundo externo, pode muito bem 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 podem ser escritos com total desrespeito pelo que o mundo exterior está fazendo. Mas, em última análise, alguma coisa precisa encontrar os dados e modificar esse estado global externo.

Além disso, em aplicativos do mundo real, os dados existem para que possam ser lidos e atualizados por diversas operações. Alguns problemas são impedidos por bloqueios e transações. Mas, impedir que essas operações entrem em conflito umas com as outras em princípio , no final do dia, simplesmente envolve pensamento cuidadoso. (E cometer erros ...)

Mas também não estamos trabalhando diretamente com o estado global.

A menos que o aplicativo esteja na camada de dados (em SQL ou qualquer outro), 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 impacto para o estado atual, compartilhado.

E, nos casos em que precisamos mudar esse estado global, sob a suposição de que os dados que nos foram fornecidos não foram alterados, geralmente podemos realizar o mesmo tipo de bloqueio que faríamos em nossos globais globais. / p>

E, finalmente, costumamos fazer coisas diferentes com bancos de dados do que podemos com pessoas malcriadas.

Um global malcriado e fragmentado se parece com isso:

Int32 counter = 0;

public someMethod() {
  for (counter = 0; counter < whatever; counter++) {
    // do other stuff.
  }
}

public otherMethod() {
  for (counter = 100; counter < whatever; counter--) {
    // do other stuff.
  }
}

Nós simplesmente não usamos bancos de dados para coisas em processo / operacionais como essas. E pode ser a natureza lenta do banco de dados e a relativa conveniência de uma variável simples que nos impede: nossa interação lenta e desajeitada com bancos de dados simplesmente os torna candidatos ruins para muitos dos erros que historicamente temos feita com variáveis .

    
por 25.05.2016 / 00:57
fonte
21

Eu não concordo com a afirmação fundamental de que:

When your program is working with data from a database, you don't care if other code in your system is changing it, or even if an entirely different program is changing it, for that matter.

Meu pensamento inicial foi "Uau. Apenas Wow". Muito tempo e esforço são gastos tentando evitar exatamente isso - e descobrir quais trocas e compromissos funcionam para cada aplicativo. Apenas ignorar é uma receita para o desastre.

Mas eu também tenho dias em um nível de arquitetura. Uma variável global não é apenas um estado global. É um estado global que é acessível 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 do que manipular em uma variável global ....)

Por exemplo, usar uma variável global pode parecer com isso

int looks_ok_but_isnt() {
  return global_int++;
}

int somewhere_else() {
  ...
  int v = looks_ok_but_isnt();
  ...
}

Mas fazer a mesma coisa com um banco de dados teria que ser mais explícito sobre o que ele está fazendo

int looks_like_its_using_a_database( MyDB * db ) {
   return db->get_and_increment("v");
}

int somewhere_else( MyBD * db ) { 
   ...
   v = looks_like_its_using_a_database(db);
   ...
}

O banco de dados está obviamente usando um banco de dados. Se você não quisesse usar um banco de dados, você pode usar o estado explícito e ele parece quase o mesmo que o caso do banco de dados.

int looks_like_it_uses_explicit_state( MyState * state ) {
   return state->v++;
}


int somewhere_else( MyState * state ) { 
   ...
   v = looks_like_it_uses_explicit_state(state);
   ...
}

Então, eu diria que usar um banco de dados é muito mais como usar estado explícito do que usar variáveis globais.

    
por 25.05.2016 / 03:10
fonte
18
O ponto em que a única razão pela qual as variáveis globais não podem ser confiáveis desde que o estado pode ser mudado em outro lugar é, por si só, razão suficiente para não usá-las, concordou (é uma ótima razão!). É provável que a resposta fosse principalmente descrever o uso onde restringir o acesso de uma variável a apenas áreas de código com as quais se preocupa faria mais sentido.

Os bancos de dados são uma questão diferente, no entanto, porque são projetados com o propósito de serem acessados "globalmente", por assim dizer.

Por exemplo:

  • Bancos de dados geralmente possuem validação de tipo e estrutura que vai além da linguagem que os acessa
  • Bancos de dados atualizam quase unanimemente as transações baseadas, o que evita estados inconsistentes, onde não há garantias de como será o estado final em um objeto global (a menos que esteja escondido atrás de um singleton)
  • A estrutura do banco de dados é, pelo menos, implicitamente documentada com base na estrutura de tabela ou de objeto, mais do que no aplicativo que a utiliza

Mais importante ainda, os bancos de dados têm um propósito diferente de uma variável global. Bancos de dados são para armazenar e pesquisar grandes quantidades de dados organizados, onde variáveis globais servem a nichos específicos (quando justificáveis).

    
por 24.05.2016 / 22:03
fonte
10

But when I look at that, I can't help but think that that's a really weak explanation, because how is that any different from working with data stored in a database?

Ou diferente de trabalhar com um dispositivo interativo, com um arquivo, com memória compartilhada, etc. Um programa que faz exatamente a mesma coisa toda vez que é executado é um programa muito chato e inútil. Então sim, é um argumento fraco.

Para mim, a diferença que faz 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. Eu tenho que 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 esta função lê a partir do teclado, que a função acessa um arquivo, alguma outra função acessa a memória compartilhada (e é melhor que haja proteções em torno disso), e alguma outra função acessa um banco de dados. p>

Com as variáveis globais, por outro lado, não é nada óbvio. A API diz para chamar foo(this_argument, that_argument) . Não há nada na sequência de chamada que diga que a variável global g_DangerWillRobinson deve ser definida para algum valor, mas antes de chamar foo (ou examinada depois de chamar foo ).

O Google proibiu o uso de argumentos de referência não-const em C ++ principalmente porque não é óbvio para o leitor do código que foo(x) mudará x porque foo usa uma referência não constante como argumento . (Compare with C #, que determina que tanto a definição de função quanto o site de chamada devem qualificar um parâmetro de referência com a palavra-chave ref .) Embora eu não concorde com o padrão do Google sobre isso, eu entendo o ponto deles.

O código é escrito uma vez e modificado algumas vezes, mas, se estiver bom, é lido muitas vezes. Linhas ocultas de comunicação são muito ruins. A referência não-const de C ++ representa uma pequena linha oculta de comunicação. Uma boa API ou um bom IDE mostrará que "Oh! Isso é chamado por referência". As variáveis globais são uma enorme linha oculta de comunicação.

    
por 25.05.2016 / 01:24
fonte
8

Acho que a explicação citada simplifica a questão ao ponto em que o raciocínio se torna ridículo. Naturalmente, o estado de um banco de dados externo contribui para o estado global. A questão importante é como seu programa depende do estado global (mutável). Se uma função de biblioteca para dividir strings no espaço em branco dependeria de resultados intermediários armazenados em um banco de dados, eu objetaria a esse design pelo menos tanto quanto eu objetaria a um array de caracteres global usado para o mesmo propósito. 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 que uma estrutura global de valor-chave na memória funcionará, isso não é necessariamente um sinal de design inadequado. O importante é que - independentemente da solução escolhida para armazenar seus dados - essa escolha é isolada em uma parte muito pequena do sistema, de modo que a maioria dos componentes pode ser independente da solução escolhida para implementação e testada em unidade de forma isolada. solução pode ser alterada mais tarde com pouco esforço.

    
por 24.05.2016 / 22:19
fonte
8

Como engenheiro de software que trabalha predominantemente com firmware incorporado, estou quase sempre usando variáveis globais para qualquer coisa entre os módulos. Na verdade, é uma prática recomendada para o embedded. Eles são atribuídos estaticamente, portanto, não há risco de explodir o heap / pilha e não há tempo extra para a alocação / limpeza da pilha na entrada / saída da função.

A desvantagem disso é que nós fazemos temos que considerar como essas variáveis são usadas, e muito disso se resume ao mesmo tipo de pensamento que entra na disputa de banco de dados. Qualquer leitura / escrita assíncrona das variáveis DEVE ser atômica. Se mais de um lugar puder escrever uma variável, algum pensamento deve ser feito para garantir que eles sempre escrevam dados válidos, para que a escrita 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 tomada no início para que o processamento seja feito usando um valor consistente, mesmo se esse valor se torna obsoleto durante o processamento.

(Para esse último, no meu primeiro dia de um contrato trabalhando em um sistema de contramedidas de aeronaves, tão altamente relacionado à segurança, a equipe de software estava olhando para um relatório de bug que eles estavam tentando descobrir por uma semana Eu tinha tido tempo suficiente para baixar as ferramentas de desenvolvimento e uma cópia do código. Eu perguntei "não poderia essa variável ser atualizada entre as leituras e causar isso?", mas realmente não recebi uma resposta. O que o novo cara sabe, afinal? Então, enquanto eles ainda estavam discutindo, eu adicionei código de proteção para ler a variável atomicamente, fiz uma compilação local, e basicamente disse: "Ei, tente isso". 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 cuidadosamente.

    
por 25.05.2016 / 16:39
fonte
7

Dependendo do aspecto que você está julgando, as variáveis globais e o acesso ao banco de dados podem estar em mundos separados, mas, desde que os julguemos como dependências, eles são os mesmos.

Vamos considerar a definição da programação funcional de uma função pura, que deve depender apenas dos parâmetros que ela toma 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, ela pode produzir saídas diferentes porque 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 uma parte da interface da função tanto quanto seus outros argumentos, então não é o problema. O problema é apenas que isso está oculto até o momento em que estamos surpreendidos por comportamento inesperado de funções aparentemente óbvias, em seguida, leia suas implementações para descobrir as dependências ocultas .

Esta parte, o momento em que uma variável global se torna uma dependência oculta é o que é considerado mau por nós programadores. Isso torna o código mais difícil de raciocinar, é difícil prever como ele se comportará, será difícil reutilizá-lo, será difícil testá-lo e, especialmente, aumentará o tempo de depuração e correção quando ocorrer um problema.

O mesmo acontece quando escondemos a dependência do banco de dados. Podemos ter funções ou objetos fazendo chamadas diretas para consultas e comandos de banco de dados, ocultando essas dependências e causando o mesmo problema que as variáveis globais causam; ou podemos torná-los explícitos, o que, como se vê, é considerado uma prática recomendada que atende por muitos nomes, como padrão de repositório, data-store, gateway, etc.

P.S .: Há outros aspectos que são importantes para essa comparação, como se a concorrência está envolvida, mas esse ponto é coberto por outras respostas aqui.

    
por 25.05.2016 / 04:20
fonte
6

Ok, vamos começar do ponto histórico.

Estamos em um aplicativo antigo, escrito em sua combinação típica de assembly e C. Não há funções, apenas procedimentos . Quando você deseja passar um argumento ou retornar um valor de um procedimento, use uma variável global. Desnecessário dizer que isso é muito difícil de acompanhar e, em geral, cada procedimento pode fazer o que quiser com cada variável global. Como era de se esperar, as pessoas se voltaram para passar argumentos e retornar valores de uma maneira diferente assim que possível (a menos que fosse essencial para o desempenho não fazer isso - por exemplo, veja o código fonte do Build Engine (Duke 3D)). O ódio de variáveis globais nasceu aqui - você tinha muito pouca ideia de qual parte do estado global cada procedimento iria ler e alterar, e você não poderia realmente aninhar as chamadas de procedimento com segurança.

Isso significa que o ódio variável global é uma coisa do passado? Não é bem assim.

Primeiro, eu tenho que mencionar que eu vi a mesma abordagem para passar argumentos no projeto no qual estou trabalhando agora. Para passar duas instâncias de 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 assim, e provavelmente nasceu de qualquer cultivo de carga ou de um completo equívoco sobre como o C # funciona.

O ponto principal é que, ao adicionar variáveis globais, você está expandindo o escopo de cada pedaço de 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ê tiver 600 variáveis globais (novamente, exemplo do mundo real: /), todos os seus escopos de método serão implicitamente expandidos por essas 600 variáveis globais, e não há uma maneira simples de rastrear quem tem acesso a quê.

Se feito de maneira errada (da maneira usual :)), as variáveis globais podem ter acoplamentos entre si. Mas você não tem ideia de como eles estão acoplados e não há mecanismos para garantir que o estado global seja sempre consistente. Mesmo se você introduzir seções críticas para tentar manter as coisas consistentes, você descobrirá que elas se comparam mal a um banco de dados ACID adequado:

  • Não há como reverter uma atualização parcial, a menos que você preserve os valores antigos antes da "transação". Escusado será dizer que, neste ponto, passar um valor como argumento já é uma vitória:)
  • Todos que acessam o mesmo estado devem aderir ao mesmo processo de sincronização. Mas não há como impor isso - se você esquecer de configurar a seção crítica, você está ferrado.
  • Mesmo que você sincronize corretamente todo o acesso, pode haver chamadas aninhadas que acessam o estado parcialmente modificado. Isso significa que você pode travar (se as seções críticas não forem repetitivas) ou lidar com dados inconsistentes (se eles forem novos).

É possível resolver esses problemas? Na verdade não. Você precisa de encapsulamento para lidar com isso, ou disciplina realmente rigorosa. É difícil fazer as coisas direito e geralmente não é uma receita muito boa para o sucesso no desenvolvimento de software:)

O escopo menor tende a tornar o código mais fácil de raciocinar. Variáveis globais fazem com que mesmo os pedaços de código mais simples incluam grandes extensões de escopo.

Naturalmente, isso não significa que o escopo global seja ruim. Não deve ser a primeira solução que você escolhe - é um exemplo típico de "simples de implementar, difícil de manter".

    
por 25.05.2016 / 10:02
fonte
6

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 o pôster original observa, a diferença não é tão grande assim.

Estudantes inexperientes geralmente acham que os erros são algo que acontece com outras pessoas. Os professores usam "Variáveis globais são más" como uma razão simplificada para penalizar o mau design. Os estudantes geralmente não entendem que só porque o seu programa de 100-line é livre de bugs não significa que os mesmos métodos podem 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 mais detalhes sobre diretrizes, como ACID e formulários normais e assim por diante.

Se as pessoas usassem a abordagem ACID para variáveis globais, elas não seriam tão ruins.

Por outro lado, se você criar bancos de dados mal, eles podem ser pesadelos.

    
por 25.05.2016 / 12:33
fonte
5

Para mim, o principal mal é 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 você descobrirá que quanto mais problemas de concorrência você resolve, mais os Globals começam a imitar um banco de dados. O mal secundário não é contrato de uso.

    
por 25.05.2016 / 03:28
fonte
5

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 maligno quanto um singleton ou uma variável global. É errado usar um banco de dados quando você pode simplesmente usar um mapa local ou uma matriz!

Variáveis globais permitem acesso global, o que acarreta risco de abuso. Variáveis globais também possuem upsides. Geralmente, as variáveis globais são algo que você deve evitar, não algo que você nunca deve usar. Se você pode facilmente evitá-los, você deve evitá-los. Mas se os benefícios superam as desvantagens, é claro que você deve usá-los! *

A mesma coisa ** se aplica aos bancos de dados, que são globais - assim como as variáveis globais. Se você puder fazer sem acessar um banco de dados, e a lógica resultante fizer tudo o que você precisa e for igualmente complexa, usar um banco de dados aumenta o risco para o seu projeto, sem qualquer benefício correspondente.

Na vida real, muitos aplicativos exigem estado global por design, às vezes até mesmo estado global persistente - é por isso que temos arquivos, bancos de dados etc.

* A exceção aqui são estudantes. 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 são de alguma forma mais protegidos do que outras formas de estado global (a questão é explicitamente sobre estado global , não apenas variáveis globais). Isso é besteira. A proteção primária oferecida no cenário de 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 depois de ter sido definido no construtor ou getters e setters que podem obter informações de thread ou estado do programa em conta.

    
por 26.05.2016 / 20:47
fonte
2

Em certo sentido, a distinção entre variáveis globais e um banco de dados é semelhante à distinção entre membros privados e públicos de um objeto (supondo que alguém ainda use campos públicos). Se você pensar em todo o programa como um objeto, então os globais são as variáveis privadas e o banco de dados são os campos públicos.

A principal distinção aqui é de responsabilidade assumida.

Quando você escreve um objeto, supõe-se que qualquer um que mantenha os métodos de membro garantirá que os campos privados permaneçam bem comportados. Mas você já desiste de qualquer suposição sobre o estado dos campos públicos e os trata com cuidado extra.

A mesma hipótese se aplica em um nível mais amplo ao banco de dados global v / s. Além disso, a linguagem de programação / ecossistema garante restrições de acesso no privado v / s público no mesmo era como ele impõe-los em (não compartilhada memória) globals v / s banco de dados.

Quando o multithreading entra em cena, o conceito de banco de dados privado v / s pública v / s global v / s é meramente distinções ao longo de um espectro.

static int global; // within process memory space
static int dbvar; // mirrors/caches data outside process memory space

class Cls {
    public: static int class_public; // essentially the same as global
    private: static int class_private; // but public to all methods in class

    private: static void method() {
        static int method_private; // but public to all scopes in method
        // ...
        {
            static int scope1_private; // mutex guarded
            int the_only_truly_private_data;
        }
        // ...
        {
            static int scope2_private; // mutex guarded
        }
    }
}
    
por 30.05.2016 / 02:04
fonte
1

Um banco de dados pode ser um estado global, mas não precisa ser o tempo todo. Eu não concordo com a 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 assim que são desbloqueados, mas há muitas maneiras de controlar o acesso (não forneça a todos os desenvolvedores a senha para a conta com permissão para alterar dados . Se você tem uma variável que tem acesso limitado, ela não é muito global.

    
por 25.05.2016 / 15:25
fonte
0

Existem várias diferenças:

  • Um valor do banco de dados pode ser modificado imediatamente. 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. Na verdade, isso é intencional. Um banco de dados é para valores que podem mudar com o tempo, mas as variáveis globais devem ser apenas para coisas que nunca serão alteradas e quando não contêm dados reais.

  • Um valor de banco de dados (linha, coluna) tem 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, é ligeiramente diferente. Você pode encontrar todos os usos, mas seria impossível para você me dizer all as formas pelas quais a variável interage com o resto do mundo.

  • As variáveis globais são mais rápidas . Obter algo de um banco de dados requer uma conexão de banco de dados a ser feita, uma seleção para executar e, em seguida, a conexão com o banco de dados deve ser fechada. Qualquer tipo de conversão que você possa precisar é fornecido em cima disso. Compare isso com um global sendo acessado em seu código.

Estes são os únicos que posso pensar agora, mas tenho certeza de que há mais. Simplificando, eles são duas coisas diferentes e devem ser usados para diferentes objetivos .

    
por 25.05.2016 / 14:35
fonte
0

É claro que globals nem sempre são inapropriados. Eles existem porque eles têm um uso legítimo. O principal problema com os globals, e a principal fonte da admoestação para evitá-los, é que o código que usa um global está ligado a esse e somente 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 de servidor diferentes. Talvez o design original nunca tenha contemplado a execução de mais de uma instância de servidor de cada vez, mas se você decidir mais tarde que deseja fazer isso, simplesmente não conseguirá se o nome do servidor estiver em um 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 tem sua própria instância do banco de dados, ela pode ter seu próprio nome de servidor.

Portanto, a principal objeção a globals, pode haver apenas um valor para todo o código que acessa esse global, não se aplica a entradas de 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.

    
por 26.05.2016 / 12:20
fonte
0

Eu acho que esta é uma questão interessante, mas é um pouco difícil de responder, porque há duas questões principais que estão sendo fundidas sob o termo 'estado global'. O primeiro é o conceito de 'acoplamento global'. A prova disso é que a alternativa dada para o estado global é a injeção de dependência. O problema é que a 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 vem com 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 globals.

O outro aspecto disso é o estado compartilhado. Não tenho certeza se há uma distinção realmente clara entre o estado compartilhado globalmente e o estado compartilhado em geral, mas os custos e benefícios são muito mais sutis. 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 maneira descentralizada. Compartilhar mutáveis corretamente sem criar grandes gargalos é difícil, mas útil. Então, se você realmente não precisa fazer isso, você pode simplificar seu aplicativo minimizando o estado mutável compartilhado.

Assim, a questão de como os bancos de dados diferem dos globais também é bifurcada nesses dois aspectos. Eles introduzem o acoplamento? Sim, eles podem, mas depende muito de como o aplicativo é projetado e como o banco de dados é projetado. Há muitos fatores para se ter uma única resposta se os bancos de dados introduzem acoplamentos globais sem detalhes do design. Quanto a se eles introduzem compartilhamento de estado, bem, esse é o ponto principal de um banco de dados. A questão é se eles fazem isso bem. Novamente, acho que isso é muito complicado para responder sem muitas outras informações, como as alternativas e muitas outras compensações.

    
por 27.05.2016 / 19:24
fonte
0

Eu pensaria sobre isso de forma ligeiramente diferente: "comportamento variável global" é um preço pago pelos administradores de banco de dados (DBAs) porque é um mal necessário fazer seu trabalho.

A questão com variáveis globais, como vários outros apontaram, não é arbitrária. A questão é que seu uso torna o comportamento do seu programa cada vez menos previsível, porque se torna mais difícil determinar quem está usando a variável e de que maneira. Este é um grande problema para os softwares modernos, porque geralmente se pede a um software moderno que faça muitas coisas flexíveis. Pode fazer bilhões ou até trilhões de manipulações complexas de estado durante o curso de uma corrida. A capacidade de provar afirmações verdadeiras sobre o que esse software fará nesses bilhões ou trilhões de operações é extremamente valiosa.

No caso do software moderno, todas as nossas linguagens fornecem ferramentas para ajudar nisso, como o encapsulamento. A escolha de não usá-lo é desnecessária, o que leva à mentalidade "globals are evil". Em muitas regiões do campo de desenvolvimento de software, as únicas pessoas que as utilizam são pessoas que não sabem codificar melhor. Isso significa que eles não apenas são problemas diretamente, mas indiretamente sugerem que o desenvolvedor não sabia o que estava fazendo. Em outras regiões, você verá que globals são totalmente normais (softwares embarcados, em particular, amam globals, em parte porque funcionam bem com ISRs). No entanto, em meio a muitos desenvolvedores de software por aí, eles são a voz minoritária, então a única voz que você ouve são "globais são maus".

O desenvolvimento de banco de dados é uma dessas situações de voz minoritária. As ferramentas necessárias para fazer o trabalho de DBA são muito poderosas, e sua teoria não está enraizada no encapsulamento. Para extrair cada instante de desempenho de seus bancos de dados, eles precisam de acesso irrestrito a tudo, semelhante aos globais. Empunhe um de seus monstruosos bancos de dados de 100 milhões de linhas (ou mais!) E você apreciará porque eles não deixam seu mecanismo de DB aguentar nenhum soco.

Eles pagam um preço por isso, um preço caro. Os DBAs são forçados a serem 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 chaves estrangeiras. Aqueles que não são patológicos encontram-se com uma completa confusão de tabelas que é completamente inutilizável, ou mesmo corrompida.

Não é incomum ter pacotes de software de 100 mil linhas. Em teoria, qualquer linha no software pode afetar qualquer global em qualquer momento. Nos DBAs, você nunca encontra 100k 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 como esse, ele encapsulará seu banco de dados intencionalmente usando assessores, evitando os problemas do tipo "global" e fazendo o máximo possível de trabalho por meio desse mecanismo "mais seguro". Assim, quando o empurrão chega, até as pessoas do banco de dados evitam globals. Eles simplesmente vêm com muito perigo, e existem alternativas que são apenas tão strongs, mas não tão perigosas.

Você prefere andar por aí com cacos de vidro, ou em calçadas bem varridas, se todas as outras coisas são iguais? Sim, você pode andar de vidro quebrado. Sim, algumas pessoas até ganham a vida fazendo isso. Mas ainda assim, deixe-os varrer a calçada e seguir em frente!

    
por 28.05.2016 / 05:14
fonte
0

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ê estiver vinculado ao banco de dados específico que seu código está usando através de variáveis globais ou a parâmetros de conexão de banco de dados globais fixos, não é diferente, nem menos mal, do que qualquer outro estado global. Por outro lado, se você passar corretamente um objeto de contexto para a conexão com o banco de dados, é apenas um estado contextual grande (e amplamente utilizado), 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? Se assim for, seu banco de dados não é realmente "estado global".

    
por 30.05.2016 / 04:13
fonte
-2

Globals não são maus; eles são simplesmente uma ferramenta. O USO INDEVIDO de globals é problemático, como é o uso indevido de qualquer outra característica de programação.

Minha recomendação geral é que os globals só devem ser usados em situações que são bem entendidas e pensadas, onde outras soluções são menos ideais. Mais importante, você quer garantir que tenha documentado bem onde esse valor global pode ser modificado e, se estiver executando multithreaded, garantir que globals globais e co-dependentes sejam acessados de maneira transacional.

    
por 25.05.2016 / 20:19
fonte
-2

Padrão somente leitura e suponha que seus dados não estejam atualizados quando você imprimi-los. A fila escreve ou manipula conflitos de outra forma. Bem-vindo ao inferno diabo, você está usando global db.

    
por 31.05.2016 / 23:52
fonte

Tags