Regras de Negócio X Integridade no Banco de Dados

Há muito tempo que tenho a senssação de estar fazendo a mesma coisa duas vezes.

Vejo que as mesmas validações que faço nos atributos dos meus Objetos de Domínio estão também sendo feitas para garantir a Integridade de Domínio do meu BD. E vejo também que as mesmas regras que faço para os relacionamentos entre os meus Objetos de Domínio estão também sendo feitas para garantir a Integridade de Referencial do meu BD.

Por causa disso me surgem as seguintes dúvidas:

  • Essas validações/verificações/regras de relacionamentos são mesmo regras de negócios?
  • Onde eu devo implementar essas validações/verificações/regras de relacionamentos? Nos objetos, no BD ou em ambos? Em ambos não seria um disperdício de tempo, mas implementar em um único lugar me parece deixar o modelo de BD ou de objetos inconsistente. (Me parece que no banco é o lugar mais fácil para implementar esse tipo de coisa e me parece ser o lugar ideal para implementar isso pois o banco lida com os dados e tudo isso diz a respeito aos dados)
  • Vocês podem me ajudar a ver um exemplo de regra de negócio que esta presente somente no modelo de objetos e não no banco de dados e vice-versa?

Conto com a ajuda de vocês!
Grande abraço!

Eu acho que isso depende muito. Mas acredito que você pode estar confundindo regra de negócio com validações.

Regra de negócio, PRA MIM, é algo do tipo “um operador só pode realizar uma venda com desconto se ele possuir uma senha de supervisor”. Ou ainda, “um operador só pode excluir um documento do banco de dados se ele for usuário mestre”.

Agora, as validações que você diz eu acho que se refere mais a quantidade de caracteres, por exemplo. No cadastro de um item, ele pode ter até 100 caracteres. Isso pode ter tanto no banco quanto nos seus beans de negócio quanto na sua interface. É isso?

Eu, por via das dúvidas, faço nos 3 (e vejo que muita gente faz isso também). Supondo uma arquitetura onde a minha view é JSP, os servlets chamam os SessionBeans e os SessionBeans chamam a minha API de persistência (nem sei se existe essa coisa de servlet chamando session, mas whatever. Se não existir, por favor, me avisem). Nesse caso, na JSP vai ter limite de caracteres para o item, no SessionBean, antes de inserir ou atualizar tem um método de validação (que vê caracteres, valores e falta dos mesmos) e na API de persistência vai ter try catch ou throws se tentar inserir algo que viola as restrições do modelo do banco.

Mas tudo isso é com base no EU ACHO ehhe. E eu acho que entendi errado a sua pergunta.

Geralmente, essa sensação incômoda é o primeiro alerta de que algo está errado em seu projeto.

Na minha opinião são. Uma data de nascimento que não pode ser nula ou um salário ser maior que 0. Pra mim, são regras de negócio, talvez bem simples, mas ainda assim são.

Eu dividiria, neste caso, o sistema em 3 partes: dados (BD), negócio (java) e apresentação (javascript).

Geralmente coloco no banco o máximo de validação possível no contexto da mesma tabela.
Qualquer validação de dados que possa ser feita sem usar triggers*, coloco no banco de dados.
Isso inclui períodos válidos (data final > data inicial), cpfs válidos, salários positivos.
Como você não cria tabela toda hora, não gasta tanto tempo assim.

Além do mais, trabalho com bancos que são acessados por mais de uma aplicação (nem todas escritas por minha equipe).
Com isso, garanto um pouco mais a consistência dos dados.

Nas outras duas camadas, acredito que existam frameworks pra replicar as consistências de uma para outra.
(Utilizo um feito na própria empresa, nunca procurei produtos similares).

As regras tratadas no java podem ser bem mais complexas, envolver inúmeras entidades.

No javascript replicamos as validações para comodidade do usuário.
Esperar um submit para campo numérico que deveria ser texto é um saco.
Mas como ele fica no client (de onde não se pode confiar em nada), não dá pra considerar uma verdadeira validação.

Em resumo, minha opinião é, utilize sempre todos os recursos possíveis para validar os dados e as regras em cada etapa.
Crie mecanismos (ou procure no google) para que você possa escrever as regras apenas uma vez e elas serem replicadas em todos os pontos.

Mas você duplica essas validações na camada de negócio e na camada de apresentação(Ex: Cliente JS)? Reescrever essas regras, que ja estão escrita no BD, na camada de negócio que me incomoda…

Bom, eu acredito que deve ficar em ambos os pontos.
O modelo deve se garantir independente do banco que se usa, porém se você já estudou controle de transação verá que um dos itens obrigatórios é a Consistência dos dados, o que creio justificar essas validações a nível do banco também.
Ou seja, mesmo em caso de falha do seu modelo de negócios o nível persistente deve negar a operação equivocada, uma vez que ele se tornará inconsistente caso não o faça.

Abraços.

Acho que tudo depende de um contexto…

Validar um CPF, na view e no banco, quando este mesmo banco que é usado somente por UMA aplicação me paresse redundante. Agora… quando esse mesmo banco é usado por mais de uma aplicação, já acho que é válido, principalmente quando é o caso citado acima do banco ser usado por outra equipe.

Outro problema que vejo em colocar validações e regras em banco é: a portabiliade em relação ao banco; se você muda de banco, é um terror portar todo o código que tinha no banco anterior.

eu tb tenho a mesma sensação, ou certeza mesmo, de que a mesma regra está em mais de um ponto, as vezes chegando a três…

Aquele Bean Validation tem o propósito de resolver isso? Li por cima em uma revista tempos atrás, mas não tenho certeza se é essa a sua natureza.

[quote=xdraculax]Acho que tudo depende de um contexto…

Validar um CPF, na view e no banco, quando este mesmo banco que é usado somente por UMA aplicação me paresse redundante. Agora… quando esse mesmo banco é usado por mais de uma aplicação, já acho que é válido, principalmente quando é o caso citado acima do banco ser usado por outra equipe.

Outro problema que vejo em colocar validações e regras em banco é: a portabiliade em relação ao banco; se você muda de banco, é um terror portar todo o código que tinha no banco anterior.[/quote]

Estranho é o fato de você ter citado dois pontos da aplicação para validar o CPF exceto no que mais importa: o model.
Dentre outros detalhes, como por exemplo, ser desaconselhado dois pontos distintos de uma aplicação ou duas aplicações diferentes executarem a mesma função em um mesmo banco. Uma alternativa a isso é fornecer uma interface de acesso ao sistema 2 que somente ela seja responsável por gravar o CPF, por exemplo, dai teríamos apenas um responsável por essa persistência e validação.

Usar o mesmo banco por mais de uma aplicação é desaconselhado?

Talvez você nunca tenha ‘entrado’ neste tipo de situação, mas onde trabalho isso é perfeitamente normal, inclusive com tecnologias diferentes (aplicações Java Web, Web Services em .NET e aplicações em Delphi legadas acessam o mesmo banco pois são de orgãos e prefeituras diferentes), o que invalida a idéia que você propôs de criar uma interface comum para ser utilizada pelos 2 sistemas, pois estão falando linguas diferentes. Poderia até se pensar em um Web Service, mas pelo porte atual da aplicação isso, atualmente não é viável.

E outra, não entendi sua colocação com relação a validação no model ser ‘mais importante’.

[quote=xdraculax]Usar o mesmo banco por mais de uma aplicação é desaconselhado?

Talvez você nunca tenha ‘entrado’ neste tipo de situação, mas onde trabalho isso é perfeitamente normal, inclusive com tecnologias diferentes (aplicações Java Web, Web Services em .NET e aplicações em Delphi legadas acessam o mesmo banco pois são de orgãos e prefeituras diferentes), o que invalida a idéia que você propôs de criar uma interface comum para ser utilizada pelos 2 sistemas, pois estão falando linguas diferentes. Poderia até se pensar em um Web Service, mas pelo porte atual da aplicação isso, atualmente não é viável.

E outra, não entendi sua colocação com relação a validação no model ser ‘mais importante’. [/quote]

Sim, ja cai em situacoes dessa natureza. Na verdade todos os dias…
Isso da pano pra muita manga em discussões, mas o que questionei nao foi o mesmo banco, mas as mesmas base em si.

Quanto a validação no model, bom, ele representa o sistema com suas regras de negocio e deve ser independente de qualquer validação na view ou em outro ponto que nao seja no modelo.