Estou tentando me afastar do mundo procedural + relacional que estou acostumado e me aproximar mais da POO…
Normalmente eu uso e abuso de not nulls, checks, triggers e exceptions no BD para garantir a integridade dos dados, mas agora pergunto: Estas validações devem continuar a serem feitas no banco de dados? Ou devem ser tratadas em objetos na minha aplicação?
Fiz essa mesma pergunta em um forum gringo, e a resposta que tive foi que se dados inválidos conseguirem chegar até o banco de dados, é sinal de que houve uma falha na aplicação, que deveria ter validado os dados antes de persistir. Então no final das contas, o banco de dados seria um mero repositorio de dados sem qualquer inteligencia.
A principio me pareceu chocante, pois vai contra tudo que eu tinha em mente, mas pensando bem agora posso ver que faz bastante sentido. Vocês seguem esta linha tambem?
Fiz algumas pesquisas aqui mesmo, e cheguei até o livro de Domain Driven Design do Eric Evans. Já está na minha lista para ser lido. Recomendam algum material?
Sim, o único momento que eu particularmente tenho deixado qualquer tipo de inteligência no Banco de Dados, é quando preciso fazer processos em lote(exmplo: Inserir 100 mil registros por hora/dia/minuto). Que eu delego para uma Stored Procedure. Em qualquer outro cenário não vejo e não tive necessidade nenhuma de deixar qualquer inteligência no banco além de guardar dados.
Costumo colocar regras simples.
PKs, FKs e UKs, nada muito complexo não simplemente para garantir a integridade básica do banco.
Mas a maioria da inforamção é checada pela aplicação.
boa tarde… eu trabalho com validação em banco nos casos que tenho mais de uma aplicação acessando o mesmo. Dessa forma viso garantir que os dados estarao sempre coerentes independente da aplicação que esta acessando/ inserindo/ editando as informaçoes do sistema. Caso alguma dessas aplicaçoes tente fazer algo contra as normas tenho como ultima camada o banco validando. Pode nao ser a melhor tecnica, nem a mais “bonita”, mas o que me importa é a informação final.
Isso inclui not nulls, checks e foreign keys? Nem isso vc deixa no banco?
Eu estou muito acostumado com client/server, onde é apenas o sgbd no servidor e os clientes nas estações… Removendo tudo do banco, você precisará implementar um servidor de aplicações que vai receber todo o acesso das estações e validar os dados, correto? Neste caso, qual seria a melhor forma de implementar isso?
[quote]Costumo colocar regras simples.
PKs, FKs e UKs, nada muito complexo não simplemente para garantir a integridade básica do banco. [/quote]
Foi o que pensei logo de inicio, mas aí vem a questão: Como definir o que fica no banco e o que vai pra aplicação?
No final cheguei à conclusão que não tem porque dividir: Se é tudo necessário para garantir a integridade dos dados, então coloca tudo em um só lugar, ou no SGBD ou na aplicação. O que acha?
Eu acredito que o basico de validação sempre é bom ter no banco.
Mas eu prefiro muito mais validar a auto nivel, muito mais pratico de se dar manutenção tbm.
O ideal seria ter validação a todo o lado, tanto no BD quanto na aplicação, assim vc garante que seus dados serão integros.
Na maior parte dos casos eu utilizo algum framework ORM(HIbernate/TopLink) e eles já fazem isso para mim, conforme a regra que crio em minhas entidades/classes eles refletem para o banco de dados.
Quando não utilizo-os, alguma regras como not null, fk, pk eu acabo deixando em ambos os lados(aplicação e banco)
[quote=magnomp]
Eu estou muito acostumado com client/server, onde é apenas o sgbd no servidor e os clientes nas estações… Removendo tudo do banco, você precisará implementar um servidor de aplicações que vai receber todo o acesso das estações e validar os dados, correto? Neste caso, qual seria a melhor forma de implementar isso?[/quote]
Essa é a idéia, agora o teu sistema não está mais na máquina do cliente, o cliente tera na sua máquina somente o que precisa para visualizar o sistema, o sistema em si com suas regras e etc estão em um servidor intermediário.
Falando em ORM, é recomendavel que eu encapsule o hibernate (ou qualquer que seja o mecanismo de persistencia utilizado) de forma que só uma parte bem especifica da aplicação tenha acesso direto a ele? Digo isso pois imagino que qualquer um poderia utilizar o hibernate para executar uma query diretamente nele, sem verificar a validade dos dados, resultando na quebra da integridade das minhas informações.
Algo tipo:
GerenciadorDeVendas.registrarVenda(venda); { Aqui, antes de gravar a venda, verificará o status do cliente para ver se ele não está bloqueado }
FK, PK, UK e campos not null sempre deixo com o BD.
Agora a regra de negocio deixo na aplicação. Mas sempre é bom utilizar o bom senso, caso tenho um processo batch gigantes prefiro deixar numa procedure no banco de dados e iniciar pela aplicação.
Trabalhei muito tempo com oracle e na outra empresa toda regra de negocio tratavamos com triggers, procedures e function (PL/SQL). Eu acho que tem os prós e contras, trabalhando dessa forma deixamos a aplicação totalmente amarrada na aplicação. Mas como sempre dizem isso depende muito do projetos …
Eu sempre defendi que na maioria dos casos não se deve priorizar uma ou outra arquitetura pelo fato de facilitar a migração de um banco de dados porque muitas vezes essa facilidade nunca será usada.
Mas a pouco tempo atras, li um post em um blog sobre isso que me fez mudar totalmente de ideia: É importante que a aplicação seja independente de banco de dados mesmo que vc nunca precise trocar o sgbd X pelo Y, para que você possa substituir a persistencia para o sgbd X por uma persistencia “falsa”, durante testes automatizados.
Realmente esse seria o melhor do mundo não deixar aplicaçao presa ao banco de dados. Por mais que temos as ferramentas como Hibernate/JPA, eu acho dificil pensar dessa forma como deixar uma aplicação muti/banco, pois dependendo da complexidade da aplicaçao temos que usar os recursos do bancos de dados querys complexas a melhor opçao é views.
[quote=Rafael Nunes][quote=magnomp]
Eu estou muito acostumado com client/server, onde é apenas o sgbd no servidor e os clientes nas estações… Removendo tudo do banco, você precisará implementar um servidor de aplicações que vai receber todo o acesso das estações e validar os dados, correto? Neste caso, qual seria a melhor forma de implementar isso?[/quote]
Essa é a idéia, agora o teu sistema não está mais na máquina do cliente, o cliente tera na sua máquina somente o que precisa para visualizar o sistema, o sistema em si com suas regras e etc estão em um servidor intermediário.
[/quote]
Poderia me dar uma idéia de como implementar algo para gerenciar o acesso simultâneo de várias estações que podem interferir uma com a outra?
Tipo, imagine duas estações: “A” e “B”. “A” carregou um Cliente e está registrando uma venda para ele, mas nisso “B” tambem acessou o mesmo cliente e o marcou como “Bloqueado”, um status que deveria impedir a operação que “A” está fazendo.
Como a validação não estará no banco de dados, se eu não for capaz de verificar isso adequadamente na hora de gravar a venda, vou estar gerando uma inconsistencia nos dados.
Se eu fizer algo assim:
[code]public void registrarVenda(Venda venda) {
if (venda.getCliente().isBloqueado())
throw new ExceptionBlaBlaBla();
// Prossegue registrando a venda…
}[/code]
Mesmo que eu dê um “refresh” no cliente naquele momento, ainda pode ocorrer o problema.
Será que eu deveria trabalhar com locks aí?
Tipo:
[code]public void registrarVenda(Venda venda) {
synchronized(lock) {
venda.getCliente().refresh(); // Obter os dados atualizados
if (venda.getCliente().isBloqueado)
throw new ExceptionBlaBlaBla();
Eu acredito que validações devam ser colocadas em ambos os lados, até porque validações no SGBD evitam as inconsistências causadas por eventuais “marretadas”. O ponto é que existem certas coisas que acredito que fiquem melhores no banco de dados como por exemplo a auditoria. Com triggers esse trabalho é muito simplificado, além do ganho de performance (não necessita fazer IO a cada inserção), tem a questão da grande segurança dos SGBDs, etc…
Para esse caso eu não implementaria lock algum. O Cliente não pode estar em dois lugares ao mesmo tempo, e mesmo que estivesse utilizando dois caixas ao mesmo tempo, é capaz das duas vendas serem válidas.
Eu acredito que validações devam ser colocadas em ambos os lados, até porque validações no SGBD evitam as inconsistências causadas por eventuais “marretadas”. O ponto é que existem certas coisas que acredito que fiquem melhores no banco de dados como por exemplo a auditoria. Com triggers esse trabalho é muito simplificado, além do ganho de performance (não necessita fazer IO a cada inserção), tem a questão da grande segurança dos SGBDs, etc…
O que vocês acham?
Abraços[/quote]
Na minha opinião as validações devem ser colacadas nos dois lados também. Eu acho que uma coisa que pode justificar colocar as regras em procedures, funcitions etc é o fato de você dar a permissão - grant - para alguns usuários apenas
Mas acho que talvez isso também seja possível via código, alguem sabe?
[quote=Andre Fonseca]o fato de você dar a permissão - grant - para alguns usuários apenas
Mas acho que talvez isso também seja possível via código, alguem sabe?[/quote]
Hoje, apesar de implementar muita coisa no banco de dados, eu implemento usuários e controle de permissões manualmente, e verifico tudo na aplicação.
Mas não trabalho com permissões a nível de procedures e tabelas, nunca tive necessidade disso. É mais algo tipo “Permissão para baixar contas a receber”.
Concordo! A única coisa que acho que poderia acontecer (acho isso bem difícil, ao menos nunca vi) é o setor de crédito bloquear o cliente justamente alguns minutos antes do cliente chegar no caixa.
[quote=Link_pg]Eu acredito que validações devam ser colocadas em ambos os lados, até porque validações no SGBD evitam as inconsistências causadas por eventuais “marretadas”. O ponto é que existem certas coisas que acredito que fiquem melhores no banco de dados como por exemplo a auditoria. Com triggers esse trabalho é muito simplificado, além do ganho de performance (não necessita fazer IO a cada inserção), tem a questão da grande segurança dos SGBDs, etc…
[/quote]
A minha opinião sobre isto é que, colocar código no banco ou não tem a ver com estratégia. Por exemplo, uma empresa que produz e vende software colocar tudo ou boa parte do código no banco de dados poderá encontrar situações bem ruins, caso um cliente que utilize um banco de dados que não esteja previsto no sistema. Quando isto acontece, geralmente passa um monte de desenvolvedores virando noites codificando procedures / functions / triggers para o “novo” banco.
Se o sistema em questão for utilizado apenas dentro da organização acho que fica mais tranquilo, desde que vc possua uma equipe de banco / dba comprometidos com os resultados. Caso contrario, ocorre muitas brigas (“tretas”). Não é em todos os lugares que vc pode ficar “pondo as mãos” no banco de dados, tem que solicitar ao dba para ser executado. E muitas vezes eles fazem isto quando eles acharem melhor, ou seja, vc pode ficar parado esperando enquanto o seu cronograma “vai pro brejo”.