Talvez vocês já tenham ouvido uma conversa assim:
- Ei, temos que saber se um produto está disponível para ser vendido
- Colocamos um contador e quando ele chegar a zero ele não pode mais ser vendido.
- Não, o produto pode ter o contador em qualquer número, e em algum momento pode ser inativado para impedir que possa ser vendido.
- Ah! Vamos colocar uma flag “sim”/“não” para ver se o produto esta disponível.
- Boa!
Diálogos semelhantes acontecem todos os dias em todas as rodas de conversas em busca da solução ideal para este e problemas semelhantes.
Mas qual é o problema em si?
Se abstrairmos o quão simples é adicionar um campo numa tabela que já existe e pensar nos efeitos a longo prazo desta adição, podemos enumerar uma série de recomendações, boas práticas, inconformidades, etc, que estamos “ferindo”:
bancos relacionais têm “relacional” no nome porque servem para isso, para que suas estruturas de dados representem relações e portanto deve-se sempre avaliar as suas responsabilidades. No caso do exemplo, determinar que um produto está disponível ou não para ser vendido, deve ser de uma nova estrutura;
não existe problema algum em se fazer
JOIN
para poder chegar ao valor de um campo, bancos relacionais são feito para isso, o problema está querer fazer uma otimização precoce, as formas normais existem como um primeiro conjunto de regras a se seguir para antecipar problemas nos relacionamentos;sem muito conhecimento do processo de negócio, não é possível saber antecipadamente como será a distribuição dos valores
sim/não
portanto não podemos antecipar se um índice será efetivo ou não; de qualquer forma um índice é uma estrutura de dados à parte, uma tabela com uma chave primaria poderia trazer efeitos melhores e diversas situações, não só tecnicamente, mas também para analisar esses dados no futuro;se a maturidade da entidade Produto é alta, adicionar qualquer lógica, qualquer campo, vai reduzir a maturidade dela, porque você pode estar quebrando interfaces bem definidas, vejam que não foi informado a obrigatoriedade do campo e isto pode mudar completamente o comportamento de processos de negócio que alteram esta entidade;
um campo contendo
sim/não
pode não ser suficiente para expressar o ciclo de vida da informação. A informação pode ter um ciclo de vida muito mais longo para ser expressado em simples “sim” e “não”, este ciclo pode fazer a informação por mais estados do que apenas ativo ou não, por exemplo vocês podem querer manter um histórico para medir por quanto tempo um produto ficou disponível;ferimos o princípio Open/Closed, entre outras palavras, “Produto” deveria ser estendível, na prática, criar uma nova tabela para esta ser responsável por manter os possíveis estados dos produtos;
adicionar um campo em uma tabela existente em uma base com grande volume de transações gerará bloqueios na tabela causando espera nas transações que a consultam e o downtime disto pode ser inaceitável, a adição de uma entidade não teria esta sintoma;
é de responsabilidade de “Produto” responder se ele pode ser vendido ou não? Não parece ser coerente ao se pensar que os relacionamentos também devem representar processos de negócio. E se for responsabilidade de um módulo especifico do sistema que representa um processo de negócio e usar as informações do Produto, precisaria este modulo estar fortemente acoplado ao produto? Não poderia este módulo estar inclusive executando separadamente?
Não considerei acima questões relacionadas a denormalização por motivos de desempenho, mas quando isto ocorre é porque existe um monitoramento, ou existiu alguma análise pontual em um ambiente de produção, e o resultado dela considerou adicionar uma redundância, mas é uma análise baseada em fatos.
Não gostaria de chamar isto acima de “regras”, tão pouco estou dizendo que é “errado” adicionar campos em entidades que já existem, mas sim que no mínimo estes itens devem fazer parte de um checklist a ser considerado sempre que se for efetuar alguma mudança em suas estruturas de dados. Este checklist não precisa ser formal, documentado e não é escrito em pedra. Ele precisa ser derivado, pensando, aperfeiçoado e adaptado às suas realidades.
Estes são meus R$ 0,02, por já ter sofrido com isto incontáveis vezes por não poder ter agido enquanto era tempo. É um problema do passado repetido hoje e que com certeza continuará se repetindo no futuro enquanto as conversas não forem abertas e não envolverem pessoas suficientes para que as habilidades envolvidas possam pensar realmente na solução.