Vamos dar outro exemplo que é menos cheio de concepções e expectativas. Eu tenho um enum aqui, e é o conjunto de prioridades para um bug.
Qual valor você está armazenando no banco de dados?
Então, eu poderia estar armazenando 'C'
, 'H'
, 'M'
, e 'L'
no banco de dados. Ou 'HIGH'
assim por diante. Isso tem o problema de dados digitados em sequência . Há um conjunto conhecido de valores válidos e, se você não estiver armazenando esse conjunto no banco de dados, pode ser difícil trabalhar com ele.
Por que você está armazenando os dados no código?
Você tem List<String> priorities = {'CRITICAL', 'HIGH', 'MEDIUM', 'LOW'};
ou algo nesse sentido no código. Isso significa que você tem vários mapeamentos desses dados no formato correto (você está inserindo todos os limites no banco de dados, mas está exibindo-o como Critical
). Agora, seu código também é difícil de localizar. Você vinculou a representação do banco de dados da ideia a uma sequência armazenada no código.
Em qualquer lugar que você precisar acessar essa lista, é necessário ter duplicação de código ou uma classe com várias constantes. Nenhuma das quais são boas opções. Também não se deve esquecer que existem outros aplicativos que podem usar esses dados (que podem ser gravados em outros idiomas - o aplicativo da web Java possui um sistema de relatórios Crystal Reports usado e um trabalho em lote Perl alimentando dados). O mecanismo de relatório precisaria conhecer a lista de dados válida (o que acontece se não houver nada marcado em 'LOW'
prioridade e você precisar saber que essa é uma prioridade válida para o relatório?), E o trabalho em lotes terá informações sobre qual é o valor válido valores são.
Hipoteticamente, você pode dizer "somos uma loja de idioma único - tudo está escrito em Java" e temos um único .jar que contém essas informações - mas agora isso significa que seus aplicativos estão fortemente acoplados entre si e que .jar contém os dados. Você precisará liberar a parte de relatório e a parte de atualização em lote junto com o aplicativo da Web cada vez que houver uma alteração - e espero que essa liberação ocorra sem problemas para todas as partes.
O que acontece quando seu chefe quer outra prioridade?
Seu chefe veio hoje. Há uma nova prioridade - CEO
. Agora você precisa alterar todo o código , recompilar e reimplementar.
Com uma abordagem 'enum-in-the-table', você atualiza a lista de enum para ter uma nova prioridade. Todo o código que obtém a lista extrai-o do banco de dados.
Os dados raramente ficam sozinhos
Com prioridades, os dados são inseridos em outras tabelas que podem conter informações sobre fluxos de trabalho ou sobre quem pode definir essa prioridade ou outros enfeites.
Voltando um pouco ao gênero, como mencionado na pergunta: O gênero tem um link para os pronomes em uso: he/his/him
e she/hers/her
... e você deseja evitar a codificação embutida no próprio código. E então seu chefe aparece e você precisa adicionar o 'OTHER'
gênero (para simplificar) e relacionar esse gênero com they/their/them
... e seu chefe vê o que o Facebook tem e ... bem, sim.
Ao se restringir a um bit de dados do tipo string em vez de a uma tabela enum, você agora precisa replicar essa string em várias outras tabelas para manter esse relacionamento entre os dados e seus outros bits.
E quanto a outros datastores?
Não importa onde você armazena isso, o mesmo princípio existe.
- Você pode ter um arquivo,,
priorities.prop
que tenha a lista de prioridades. Você lê esta lista em um arquivo de propriedades.
Você pode ter um banco de dados de armazenamento de documentos (como o CouchDB ) que possua uma entrada para enums
(e depois escreva uma função de validação em JavaScript ):
{
"_id": "c18b0756c3c08d8fceb5bcddd60006f4",
"_rev": "1-c89f76e36b740e9b899a4bffab44e1c2",
"priorities": [ "critical", "high", "medium", "low" ],
"severities": [ "blocker", "bad", "annoying", "cosmetic" ]
}
Você pode ter um arquivo XML com um pouco de esquema:
<xs:element name="priority" type="priorityType"/>
<xs:simpleType name="priorityType">
<xs:restriction base="xs:string">
<xs:enumeration value="critical"/>
<xs:enumeration value="high"/>
<xs:enumeration value="medium"/>
<xs:enumeration value="low"/>
</xs:restriction>
</xs:simpleType>
A idéia central é a mesma. O próprio armazenamento de dados é onde a lista de valores válidos precisa ser armazenada e aplicada. Ao colocá-lo aqui, é mais fácil argumentar sobre o código e os dados. Você não precisa se preocupar em verificar defensivamente o que possui a cada vez (em maiúsculas ou minúsculas? Por que existe um chritical
tipo nesta coluna? Etc ...) porque você sabe o que está recebendo de volta do armazenamento de dados. exatamente o que o armazenamento de dados espera que você envie de outra forma - e você pode consultar o armazenamento de dados para obter uma lista de valores válidos.
O takeaway
O conjunto de valores válidos são dados , não código. Você não precisa se esforçar para DRY código - mas a questão da duplicação é que você está duplicando os dados no código, em vez de respeitar o seu lugar como dados e armazená-lo em um banco de dados.
Isso facilita a gravação de vários aplicativos no armazenamento de dados e evita ter instâncias nas quais você precisará implantar tudo o que estiver fortemente acoplado aos dados em si - porque você não acoplado seu código aos dados.
Isso torna os aplicativos de teste mais fáceis porque você não precisa testar novamente o aplicativo inteiro quando a CEO
prioridade é adicionada - porque você não tem nenhum código que se preocupe com o valor real da prioridade.
Ser capaz de raciocinar sobre o código e os dados independentemente um do outro facilita a localização e a correção de bugs durante a manutenção.