Digamos que você escreva um aplicativo que possa ser configurado pelo usuário. Para armazenar esses "dados de configuração" em um banco de dados, dois padrões são comumente usados.
A tabela de linha única
CompanyName | StartFullScreen | RefreshSeconds | ... ---------------+-------------------+------------------+-------- ACME Inc. | true | 20 | ...
A tabela nome-valor-par
ConfigOption | Value -----------------+------------- CompanyName | ACME Inc. StartFullScreen | true (or 1, or Y, ...) RefreshSeconds | 20 ... | ...
Eu já vi as duas opções na natureza e ambas têm vantagens e desvantagens óbvias, por exemplo:
- As tabelas de linha única limitam o número de opções de configuração que você pode ter (já que o número de colunas em uma linha geralmente é limitado). Cada opção de configuração adicional requer uma alteração no esquema do banco de dados.
- Em uma tabela nome-valor-par, tudo é "tipicamente digitado" (você precisa codificar / decodificar seus parâmetros Booleanos / Data / etc.).
- (muito mais)
Existe algum consenso na comunidade de desenvolvimento sobre qual opção é preferível?
Respostas:
Pessoalmente, prefiro as tabelas de linha única para a maioria das coisas. Embora seja verdade que é menos flexível, a menos que você esteja esperando um comportamento dinâmico, é perfeitamente aceitável adicionar colunas extras mais tarde, se necessário. De certa forma, é o equivalente a usar um dicionário / mapa para armazenar pares nome-valor versus ter membros de classe durante a programação. É verdade que não é uma metáfora perfeita, mas muitas das vantagens e desvantagens são paralelas quando você pensa sobre isso.
Então você usaria um dicionário / mapa sobre os alunos? Provavelmente não, a menos que você tenha motivos para pensar que a quantidade de dados a ser representada é totalmente adaptável, assim como ter uma tabela de pares nome-valor.
fonte
Geralmente eu usaria a opção 2, mas teria várias colunas para aplicar o tipo de dados
A opção 1 possui o benefício adicional de que você pode facilmente "trocar" configurações inteiras adicionando uma
Active
coluna.fonte
activatedOn
carimbo de data e hora, para saber quando foi ativado. E se você optar pela opção 2 ... o que acontece se o resultado final for armazenar valores em várias colunas (ou é oracle, onde (aparentemente) nulo e uma string vazia são equivalentes)?Para mim, se você usa uma única linha ou EAV, depende de como você deseja consumi-los.
O poder do EAV é que novos dados possam ser adicionados sem alterações na estrutura. Isso significa que, se você deseja um novo valor de configuração, basta adicioná-lo à tabela e retirá-lo onde deseja no código, e não precisa adicionar um novo campo ao domínio, esquema, mapeamento, consultas DAL etc.
Sua falha é que ele possui apenas a estrutura mais simples, exigindo que você lide com os dados de maneira pessimista. Todo uso de qualquer valor de configuração deve esperar que o valor não esteja presente ou não esteja no formato adequado e se comporte de acordo quando não estiver. Um valor de configuração pode não ser analisável para um double, int, ou char. Pode ser nulo. pode não haver linha para o valor. As maneiras de contornar isso geralmente exigem que exista um único valor "padrão" válido para todos os valores de configuração de um tipo de código em particular ( extremamente raro; mais frequentemente, o valor padrão é tão problemático para consumir código quanto nenhum), ou mantenha um dicionário codificado de valores padrão (que deve mudar toda vez que uma nova coluna é adicionada, tornando a principal vantagem do armazenamento EAV bastante discutível).
Uma única linha larga é praticamente o oposto. Você o mapeia para uma única instância de um objeto Configuration com um campo / propriedade para cada valor de configuração existente. Você sabe exatamente que tipo esses valores devem ser no momento da compilação e "falha rapidamente" no DAL se uma coluna de configuração não existir ou não tiver um valor do tipo adequado, oferecendo um lugar para capturar exceções com base em problemas de recuperação / hidratação da configuração.
A principal desvantagem é que uma mudança estrutural é necessária para cada novo valor; nova coluna de banco de dados, nova coluna no DAL (o mapeamento ou as consultas SQL / SPs), nova coluna de domínio, tudo necessário para testar adequadamente o uso.
A situação adequada para usar qualquer um desses é a situação na qual as desvantagens são mitigadas. Para mim, a maioria das situações de codificação de configuração exigiu uma implementação de linha única. Isso ocorre principalmente porque se você está introduzindo um valor de configuração totalmente novo que governa o comportamento de alguma parte do seu programa, você já precisa alterar o código para usar o novo valor de configuração; por que não aparecer no objeto de configuração e adicionar o valor a ser usado?
Em resumo, um esquema EAV para armazenar configuração realmente não resolve o problema que pretende resolver, e a maioria das soluções alternativas para os problemas apresentados viola o DRY.
fonte
Especificamente para valores de configuração, eu diria - vá com a única linha. A menos que você esteja passando pelo desenvolvimento, com que frequência essas colunas serão alteradas?
Provavelmente, é melhor proteger o tipo de dados dos valores , em vez de codificar a extensibilidade que você provavelmente não terá no tempo de inatividade entre liberações grandes. Além disso, adicionar ou remover uma única coluna é a migração mais fácil que existe. Não prevejo dor de cabeça ao criar uma nova opção de configuração.
Além disso, você disse que "usuários" podem configurar essas opções sem dar um limite. São configurações por usuário? Nesse caso, argumentarei ainda mais fortemente que as opções de configuração devem estar nas colunas - uma única linha por usuário. Isso poupará muitas dores de cabeça de manutenção posteriormente.
fonte
Se seus clientes puderem processar fragmentos JSON (que não são apenas matrizes e dicionários, mas também cadeias simples, números, booleanos, valores nulos), será possível ter uma tabela de várias linhas com o nome da opção e um valor de cadeia contendo JSON. Isso permite que você também armazene valores estruturados, e o código para processá-los já deve estar lá.
Se seus clientes não puderem processar fragmentos JSON, obtenha novos clientes.
fonte
Única linha Prós: bem definido. Contras: Alterar a configuração pode ser uma dor. Migrações de banco de dados etc.
Profissionais de valor da entidade: Super flexível, suporta a evolução da sua configuração. Contras: Integridade referencial? Mais verificações em seu código para verificar se a propriedade existe antes que você possa fazer alguma coisa.
Eu usaria a abordagem 2 apoiada por um banco de dados não relacional como o Mongo. Se há algo que você pode ter certeza, sua mudança.
fonte
Use ambos!
Classifique quais opções podem ter várias instâncias e quais são genéricas.
A tabela de linha única (configurações)
A tabela nome-valor-par (opções)
Eu acho que isso é mais flexível.
fonte