Eu tenho uma coluna no meu banco de dados que é obrigatória APENAS se um outro field tiver um valor específico. Hoje essa validação é feita a nível de aplicação mas eu adicionei um check constraint para garantir a integridade de dados a nível de banco também.
Minha check constraint é a seguinte: (minha coluna type é um enum)
Check constraints:
"code_filled_when_type_is_sent" CHECK (type <> 'sent'::type OR code IS NOT NULL) NOT VALID
essa check constraint faz a inserção falhar quando insiro um registro com type SENT e que o code não está inserido:
ERROR: new row for relation "companies" violates check constraint "code_filled_when_type_is_sent" (PG::CheckViolation)
o que vocês acham dessa abordagem para colocar mais uma garantia na integridade de dados?
Fala Cadu,
eu acho válido o ponto de realmente deixar o banco consistente.
Mas tenho um certo receio quanto a isso.
No caso você acabou inferindo uma regra de negócio no seu banco de dados.
Dependendo de como isso é documentado na sua empresa/contexto, pode gerar mais problemas do que benefícios.
Ex: Amanhã você sai da empresa, essa regra do ‘type’ <> ‘sent’ muda, talvez o próximo desenvolvedor que der manutenção nessa feature tenha dificuldade de achar o ponto de alteração no banco. Claro que esse exemplo é pequeno.
Se você está gerando essa constraint pelo codebase os problemas de rastreio ficam minimizados, então vai da cultura da empresa e de como estão documentando as coisas ai.
Se tornar isso uma prática comum e fácil, acho que consegue unir o melhor dos dois mundos.
Agora se for algo que você fez pontualmente então eu preferiria nem fazer e deixar só na APP mesmo.
Here are the guidelines I find most useful:
Any stable requirement should be implemented as a check constraint.
Any critical requirement should be implemented as a check constraint.
Unstable requirements on tables expected to grow might be better implemented in code, so you can change them frequently, but it still might be better to use a check constraint and wait for the table to actually get large enough to be a problem.
E acho que faz sentido sim. O quão crítico é essa regra pra mim? Se for crítica, aí sim faz sentido talvez colocarmos a regra em mais uma camada.
Acho que o ponto é a criticidade, se é imprescindível que jamais essa regra seja comprometida, talvez valha o “double check” no banco.
Como vc já tem essa regra no código e possivelmente um teste pra ela, para cair na validação do banco precisaria que alguém removesse a validação e o teste. Caso aconteça isso, o banco é uma tentativa a mais de barrar isso, mas não impede a pessoa de remover do banco também da mesma forma que fez na aplicação, então é só um obstáculo a mais, pra talvez fazer a pessoa pensar “é, TAAALVEEEZ eu não devesse estar fazendo isso”.
Dai tenho duas dúvidas:
Esse ajuste no banco, fica versionado junto com o código da aplicação? Assim ele é mais visível do que sei lá, só algo que um DBA vai lá e roda o script direto na base e fica longe do código.
Vc consegue testar essa validação a nível de banco de forma automatizada? Pergunto pq um teste específico assim ajuda na documentação e deixa mais claro que tem essa regra a nível de banco implementada.