Validação de atributos - Melhores práticas!

[quote=CodeDeveloper]
É um ponto de vista interessante. Na verdade como você mesmo disse, os iniciantes devem ter essa preocupação quando estão começando… eu tenho a impressão que tenho que fazer de tudo ao meu alcançe para garantir a consistencia dos dados. Porém concordo com você também. Até que ponto isso vale a pena?

Obrigado por compartilhar Jose!! [/quote]

Programadores experientes também se preocupam com consistência dos dados. A diferença é que eles são mais eficientes, porque ao invés de validar toda vez que o sistema toca no banco de dados, o programador OO garante consistência usando o próprio modelo de objetos.

Neste caso, o banco de dados é 100% irrelevante e pode ser mapeado pra qualquer schema que suportar o seu modelo de objetos, seja relacional, NoSQL ou arquivos.

[quote=JoseIgnacio][quote=CodeDeveloper]JoseIgnacio,

Correto. Mas você concorda que não necessariamente um programador não sabe o que faz, mas por falta de informação em um projeto extremamente corrido, ou por uma distração (algo que pode acontecer com qualquer pessoa exausta e sob pressão), este problema poderia ocorrer?

Você aconselha então não se preocupar com a validação na classe DAO e tentar ao máximo ter programadores totalmente alinhados com o projeto e ótimos técnicamente? Desta forma, supostamente ninguém faria diretamente um “new LivroDAO().salvar(new Livro());” ?[/quote]

Exato. Se alguém pode fazer isso… compilar, testar, fazer o deploy, e ninguém percebeu nada, é porque existem problemas mais sérios que estão fora do escopo e alcance do seu software. Validação tb não vai impedir que alguém introduza incosistências conectando diretamente com o banco de dados. Então pra que se preocupar?
[/quote]

A única certeza que existe num projeto de software é aquilo que o codigo faz. Se o codigo dá uma exeção alertando um problema ele tem razão. O problema é visto por alguem (normalmente o usuário, porque ninguem testa a coisa direito) e leva a um bug que é corrigido. Se a verificação não está lá, simplesmente dá exception maluco que demora dias para saber o que é , e depois corrigir. É só uma questão de fazer direito e ser previdente. se existe uma regra, porque não verificá-la ? É simples. É automático. É barato. Então proque não fazer ? Vc pelos vistos confia muito nos programadores. Mas na vida real os programadores falam mais que o código.

todo o sistema deve ser confiável. E um sistema que faz cagada sem avisar não e´confiável. Eu prefiro que ele me avise e avise o usuário, do que se cale e corrompa os dados ou dê uma mensagem do tipo “contate o administrador”. É menos stressante e quando o usuario vê uma mensagem agradável ele não pensa que o sistema foi mal feito. E isso é qualidade.

É claro que confio nos meus programadores… quem cria seu código afinal, maker? lol

[quote=sergiotaborda]
todo o sistema deve ser confiável. E um sistema que faz cagada sem avisar não e´confiável. Eu prefiro que ele me avise e avise o usuário, do que se cale e corrompa os dados ou dê uma mensagem do tipo “contate o administrador”. É menos stressante e quando o usuario vê uma mensagem agradável ele não pensa que o sistema foi mal feito. E isso é qualidade.[/quote]

não fazer validação no DAO != fazer validação nenhuma

A discussão é sobre fazer validação no DAO, algo que pra mim é desnecessário se o modelo de objetos está sempre consistente com as regras do projeto.

[quote=JoseIgnacio][quote=sergiotaborda]
todo o sistema deve ser confiável. E um sistema que faz cagada sem avisar não e´confiável. Eu prefiro que ele me avise e avise o usuário, do que se cale e corrompa os dados ou dê uma mensagem do tipo “contate o administrador”. É menos stressante e quando o usuario vê uma mensagem agradável ele não pensa que o sistema foi mal feito. E isso é qualidade.[/quote]

não fazer validação no DAO != fazer validação nenhuma

A discussão é sobre fazer validação no DAO, algo que pra mim é desnecessário se o modelo de objetos está sempre consistente com as regras do projeto.[/quote]

Modelo de objetos não é a mesma coisa que modelo de dados. O modelo de objetos diz que o nome tem que ser um string. Mas seu eu passar @@!@$@#$@#$ como nome, obviamente não é o nome de ninguém. O mesmo se eu passar 31/2/2012. É uma data, mas não é uma data real. Portanto a verificação é muito importante. E sim, esta verificação não é feita no DAO.
A verificação do DAO é igual à do banco de dados. Se o campo não nulo, se tem o tamanho certo (tipo, o nome não é vazio e não é maior que 100 caracteres). Porque não deixar o banco fazer isto ? Primeiro porque se o encasulamento é bom eu nem sei se o banco faz isto. Aliás nem sei se existe um banco (por exemplo usar jpa no google app -engine). Segundo porque eu quero fail-fast. Porque perder tempo usando o protocolo de rede com o banco de dados só para ele me dizer que estou enviando dados errados ?

Pode parece inutil , mas não é. E ainda tem o problema de alguns bancos de dados dão uma mensagens nada a ver e vc fica perdido. No DAO vc mesmo crias as mensagens e testa as coias, então é muito mais simples resolver problemas.

[quote=sergiotaborda]
Modelo de objetos não é a mesma coisa que modelo de dados. O modelo de objetos diz que o nome tem que ser um string. Mas seu eu passar @@!@$@#$@#$ como nome, obviamente não é o nome de ninguém. O mesmo se eu passar 31/2/2012. É uma data, mas não é uma data real. Portanto a verificação é muito importante. E sim, esta verificação não é feita no DAO.
A verificação do DAO é igual à do banco de dados. Se o campo não nulo, se tem o tamanho certo (tipo, o nome não é vazio e não é maior que 100 caracteres). Porque não deixar o banco fazer isto ? Primeiro porque se o encasulamento é bom eu nem sei se o banco faz isto. Aliás nem sei se existe um banco (por exemplo usar jpa no google app -engine). Segundo porque eu quero fail-fast. Porque perder tempo usando o protocolo de rede com o banco de dados só para ele me dizer que estou enviando dados errados ?

Pode parece inutil , mas não é. E ainda tem o problema de alguns bancos de dados dão uma mensagens nada a ver e vc fica perdido. No DAO vc mesmo crias as mensagens e testa as coias, então é muito mais simples resolver problemas.[/quote]

Mas não é de objetos que estamos falando, já que o banco não faz nenhuma validação?

Se estiver falando de validações no banco, não tenho uma opinião formada sobre o assunto, mas não me parece simples ter que validar todo o schema em código e nem vejo muito sentido nisso.

Também não tenho idéia como faria validação sem fazer qualquer afirmação sobre a natureza do armazenamento. Teoricamente, um banco de dados com espaço infinito não faria mais sentido validar pelo tamanho, por exemplo.

E pra finalizar, 31/2/2012 não é uma data em Java.

[quote=JoseIgnacio][quote=sergiotaborda]
Modelo de objetos não é a mesma coisa que modelo de dados. O modelo de objetos diz que o nome tem que ser um string. Mas seu eu passar @@!@$@#$@#$ como nome, obviamente não é o nome de ninguém. O mesmo se eu passar 31/2/2012. É uma data, mas não é uma data real. Portanto a verificação é muito importante. E sim, esta verificação não é feita no DAO.
A verificação do DAO é igual à do banco de dados. Se o campo não nulo, se tem o tamanho certo (tipo, o nome não é vazio e não é maior que 100 caracteres). Porque não deixar o banco fazer isto ? Primeiro porque se o encasulamento é bom eu nem sei se o banco faz isto. Aliás nem sei se existe um banco (por exemplo usar jpa no google app -engine). Segundo porque eu quero fail-fast. Porque perder tempo usando o protocolo de rede com o banco de dados só para ele me dizer que estou enviando dados errados ?

Pode parece inutil , mas não é. E ainda tem o problema de alguns bancos de dados dão uma mensagens nada a ver e vc fica perdido. No DAO vc mesmo crias as mensagens e testa as coias, então é muito mais simples resolver problemas.[/quote]

Mas não é de objetos que estamos falando, já que o banco não faz nenhuma validação?
[/quote]

O banco sempre faz alguma validação porque ele tambem tem um modelo lá que vc usou para criá-lo ( em um linguagens de definição qualquer. Claro que vc pode por tudo varchar e não se preocupar com o tamanho, por exemplo. Mas isso não é um cenários em algumas empresas em que um DBA chato fica ponto char(10000) em vez de varchar)

Ora ai está. Então o DAO que usa esse banco não faria essa validação, mas o DAO que usa outro sim faria. Mas o modelo tem a informação lá, que o tamanho deve ser no máximo 100. E isto afeta até o input do usuário. Se o sistema é bom, ele vai travar além do centesimo caracter. então, aquilo que disse antes. O modelo é uma coisa, como se usa é outra. Meta-infomação é sempre bom porque vc pode decidir usá-la ou não conforme as circusntancias. Mas vc sempre tem que garantir que o sistema é coerente, que não currompe os dados. E é isso que o nosso amigo está tentando, e eu acho que vaz muito bem tentar. Já vi muito sistema sem validação apropriada e é um caos.

[quote]
E pra finalizar, 31/2/2012 não é uma data em Java.[/quote]

É se usar Calendar.setLenient(true). Ele aceita mesmo datas que não existem. :slight_smile:
Exatamente para vc pode validar depois.

Não lembro a última vez que tive que limitar o tamanho de nada. Espaço de armazenamento hoje é praticamente grátis.

Por outro lado, tempo do programador é cada vez mais escasso.

Poderia citar outro tipo de validação útil que o banco faz?

[quote=JoseIgnacio]Não lembro a última vez que tive que limitar o tamanho de nada. Espaço de armazenamento hoje é praticamente grátis.

Por outro lado, tempo do programador é cada vez mais escasso.

Poderia citar outro tipo de validação útil que o banco faz?

[/quote]

Esse é o ponto. A validação do banco é irrelevante. O Dao faz a validação que interessa ao sistema.
Se e quando o banco fizer alguma validação (tamanho, relacionamento, null , tipagem, etc…) ela será um espelho da que o DAO faz. E se isso acontecer é porque o banco é compatilhado ( o que é comum no setor financeiro onde muitas as integrações são feitas no nivel do banco em vez de no sistema). Vc diz que o banco não precisa fazer validaçao. concordo. Mas isso apenas se e só se o DAO fizer. Caso contrário a porta está aberta para corromper dados.

A mensagem é que a validação em sistema (em objetos) deve ser feita. Se vc não quer usar validação no DAO não use. Mas pelo menos a validação de Service tem que ser feita. Ou vai me dizer que seus sistemas não têm validação nenhuma ? Não , né ?!

sergiotaborda e demais pessoas que quiserem compartilhar,

Diante da discussão (muito produtiva, por sinal), venho com a seguinte questão:

Suponha que em um sistema financeiro exista a classe NotaFiscal , NotaFiscalService e NotaFiscalDAO.

NotaFiscalService.salva(NotaFiscal f) recebe uma NotaFiscal para salvá-la no sistema. Nesse método são feitas MUITAS verificações para saber se a nota é válida, se já existe no sistema (evitar duplicidade), e etc etc etc, e depois se tudo passar na verificação, ela chama o método NotaFiscalDAO.salva(NotaFiscal f) para persistí-la no banco.

Agora vamos as dúvidas:


1ª Dúvida - QUAL DESSAS ABORDAGEM É A MAIS CORRETA:

  • toda a validação no Service.
  • validação de regras de negócio no Service e “validação de dados” (notnull, apenas numeros positivos e etc etc… não sei o nome que se dá a esse tipo de validação) na classe DAO.
  • toda a validação no DAO (o que pelo que vi, parece não ser uma boa idéia)

2ª Dúvida - PROBLEMA QUE VEJO NAS ABORDAGENS

  • se toda a validação for no Service, o sistema permite que uma nota fiscal seja criada e passada diretamente para o DAO, ao invés, do Service, causando um grande problema de consistencia de dados.
  • se apenas a “validação de dados” (notnull, apenas numeros positivos e etc etc) for feita no DAO, o sistema permite que uma nota fiscal seja criada e passada diretamente para o DAO, não verificando as regras de negócios e causando problemas de consistencia.
  • se toda a validação for feita no DAO, garantimos a consistencia dos dados, porém ao meu ver, não faz sentido a classe DAO executar validações de regras de negócio.

Gostaria de saber a opinião de vocês nessas abordagens para tentar chegar em uma possível “forma ideal”. Concordo em parte quando dizem que não da pra fazer um super sistema invencível a tolos em prazos apertados. Mas também acho que podemos garantir um bom nível de consistencia de dados.
Fico no aguardo dos mais experientes!

[quote=CodeDeveloper]sergiotaborda e demais pessoas que quiserem compartilhar,

Diante da discussão (muito produtiva, por sinal), venho com a seguinte questão:

Suponha que em um sistema financeiro exista a classe NotaFiscal , NotaFiscalService e NotaFiscalDAO.

NotaFiscalService.salva(NotaFiscal f) recebe uma NotaFiscal para salvá-la no sistema. Nesse método são feitas MUITAS verificações para saber se a nota é válida, se já existe no sistema (evitar duplicidade), e etc etc etc, e depois se tudo passar na verificação, ela chama o método NotaFiscalDAO.salva(NotaFiscal f) para persistí-la no banco.

Agora vamos as dúvidas:


1ª Dúvida - QUAL DESSAS ABORDAGEM É A MAIS CORRETA:

  • toda a validação no Service.
  • validação de regras de negócio no Service e “validação de dados” (notnull, apenas numeros positivos e etc etc… não sei o nome que se dá a esse tipo de validação) na classe DAO.
  • toda a validação no DAO (o que pelo que vi, parece não ser uma boa idéia)

2ª Dúvida - PROBLEMA QUE VEJO NAS ABORDAGENS

  • se toda a validação for no Service, o sistema permite que uma nota fiscal seja criada e passada diretamente para o DAO, ao invés, do Service, causando um grande problema de consistencia de dados.
  • se apenas a “validação de dados” (notnull, apenas numeros positivos e etc etc) for feita no DAO, o sistema permite que uma nota fiscal seja criada e passada diretamente para o DAO, não verificando as regras de negócios e causando problemas de consistencia.
  • se toda a validação for feita no DAO, garantimos a consistencia dos dados, porém ao meu ver, não faz sentido a classe DAO executar validações de regras de negócio.

Gostaria de saber a opinião de vocês nessas abordagens para tentar chegar em uma possível “forma ideal”. Concordo em parte quando dizem que não da pra fazer um super sistema invencível a tolos em prazos apertados. Mas também acho que podemos garantir um bom nível de consistencia de dados.
Fico no aguardo dos mais experientes!

[/quote]

O que vc deve fazer é criar um NotFscalValidator que contém as regras. Depois o NotaFiscalService vai simplesmente invocar o validator.
O seu problema de algum desavisado chamar o DAO diretamente sem passar pelo service e por isso tenho que validar no DAO não procede. Se o cara programou errado, problema dele.
Do ponto de vista do design o DAO não é um objeto de dominio e não pode saber das regras. Aliás, em algumas circusntancias vc não vai querer esa validação. O serviço que o DAO provê é simples Acesso (Data Acess Object). Regras não é com ele.
E como já discutimos antes, a validação feita no DAO (null etc … ) é apenas para não sobrecarregar o banco de dados e a rede.

A separação de camadas tem precedencia sobre “programadores desavisados”.E na prática, o DAO vai salvar em varias circusntancias, não apenas no create , por isso ele não deve validar demais. O service por sua vez, pode pegar uma nota e processaá-la de diferentes formas e salvar no final. Cada forma terá sua validação. Entao é o método do service que escolhe o validator, o validator que valida, e o DAO simplesmente grava.