Não, isso não é normal. Exceções devem ser utilizadas apenas se você realmente está em um caso que não é normal. Mostrar mensagens de erro pro usuário é uma coisa corriqueira que toda a aplicação tem, isso não deve ser feito com exceções.
Não, isso não é normal. Exceções devem ser utilizadas apenas se você realmente está em um caso que não é normal. Mostrar mensagens de erro pro usuário é uma coisa corriqueira que toda a aplicação tem, isso não deve ser feito com exceções.[/quote]
++
Não, isso não é normal. Exceções devem ser utilizadas apenas se você realmente está em um caso que não é normal. Mostrar mensagens de erro pro usuário é uma coisa corriqueira que toda a aplicação tem, isso não deve ser feito com exceções.[/quote]
É que estou pensando no caso em que o negócio quer mandar uma mensagem para o usuário. Parece que as únicas mensagens que ele pode enviar, fora o retorno, são as exceções. Já que exceções não fazem parte do fluxo normal, neste caso a própria view deveria verificar o retorno e imprimir uma mensagem de acordo.
Acho que o conceito ta um pouco confuso. O négocio não manda mensagem para usuario. Quem manda mensagem para o usuário é o componente View. Eu acho que o negócio deva retornar objetos de negocios ou exceções em casos anormais.
<c:catch>
...
</c:catch>
Tem uma discussão legal que rolou sobre esse assunto no stackoverflow relacionada a esse assunto que eu andei dando uma lida e é bem legal. Inclusive fala sobre recursos de oturas linguagens para resolver algumas das situações.
Sou de arocdo com o artigo que o Brunno postou logo no inicio, do Sergio Taborda, e tente me adequar… ainda não aprendi perfeitamente o padrão handle… mais estou sempre criando as exceções por camadas, e deixando exceções verificadas nos limites da camada, ou seja, qualquer método que possa lançar exceções e que é chamado de fora da camada lança exceções verificadas a camada de cima… e quem kizer q a trate na camada acima ^^
sem quere desenterrar muito o tópico … mais la vai…
estou tentando seguir o que o sergio falou nos artigos dele… ser especifico, e não deixar para os outros tratarem os problemas q eu sei tratar…
sendo assim… estou fazendo tratamento bem legal das minhas exceções, criando Classes para auxiliar, o uso, e sempre que possivel, usando recursos já existente da propria API e otimizando esses recurso… abaixo vou mostar um exemplo do que estou fazendo…
Minhas entidadees recebem muitos argumentos, e estes argumentos devem seguir algumas regras, onde alguns podem ser nulos, outros não, alguns não podem exceder um comprimento tal, ou tem que ter um comprimento etnre X e Y … entre varias outras situações… para poder tratar na propria classe, e mesmo assim conseguir ser muito especifico no erro, e poder tratar do ERRO em uma camada la em cima depois, eu fiz o seguinte…
IllegalArgumentException
|
|-DetailedIllegalArgumentException //Aqui eu consigo guardar, Source,PropertyName,Argument
|
|-IllegalSizeException //Além dos dados anterior, guardo tb o Tamanho esperado, e o tamanho checado.
| |
| |-MaxMinSizeException //Apenas uma exceção generica pra usar no cautch, quando abrange as 2 de baixo.
| |
| |-MaximumSizeException //Guarda o valor maximo permitido e o valor encontrado
| |
| |-MinimumSizeException //Guarda o valor minimo permitido e o valor encontrado
|
|-IllegalNullArgumentException //Especifica que um argumento que não podia ser null foi passado como null
Explicando as classes e colocando os links
DetailedIllegalArgumentException - Esta classe alem do tradicional de IllegalArgumentException é capaz de armezanar tb informações como:
- Source: o objeto fonte (source) que esperava o argumento enviado, e que o constatou q este era invalido.
- Property Name: o nome da propriedade do objeto fonte, que iria receber o argumento passado.
- Argument: a referencia do objeto que foi passado como argumento e que foi dado como ilegal.
IllegalSizeException - Além do já citado antes, é capaz de guardar ainda o valor esperado, e especifica que o problema no argumento é relativo ao seu comprimento, além de informar tb o comprimento constatado no momento que a exceção foi gerada.
MaxMinSizeException - Indica que o problema foi pq o argumento passado tinha comprimento fora dos valores Maximo permitido ou Minimo permitido.
MaximumSizeException - Indica que é uma exceção de maximo.
MinimumSizeException - Indica que é uma exceção de minimo.
IllegalNullArgumentException - Indica que o argumento passado não podia ser nulo, alem de informar o restante de DetailedIllegalArgumentException.
…
Desta forma eu programo meus beans de forma bem mais coerente, e com a certeza que na camada superior vou conseguir recuperar todas as informações relevantes caso uma exceção seja lançada, sem precisar debugar o problema…
por exemplo um bean pessoa
public class Pessoa {
private String nome;
private String cpf;
private String email;
//...
public void setNome(String nome) {
if (nome == null)
throw new IllegalNullArgumentException(this,"nome",nome);
if (nome.length() > 45)
throw new MaximumSizeException(this,"nome",nome,45,nome.length());
this.nome = nome;
}
// o mesmo faço para cpf, email etc etc...
}
por exemplo… digamos que eu tenha um constrole que pegue os dados de 1 interface, passar para um bean e envie para cadastramento… ao coletar os dados da interface e passar para o bean, o bean vai automaticamente lançar as exceções, sem eu, neste momento ter q me preucupar muito com API do bean, basta verificar as throws que o set lança… digamos que meu bean Pessoa, com os dados do CPF, nome, e-mail sejam passados…
public Pessoa cadastraPessoa(String nome,String cpf,String email) {
Pessoa pessoa = new Pessoa();
pessoa.setNome(nome);
pessoa.setCpf(cpf);
pessoa.setEmail(email);
Repositories.save(pessoa);
return pessoa;
}
agora fazendo
[code]try {
Pessoa pessoaCadastrada = cadastraPessoa(nome,cpf,email);
catch(MaximumSizeException ex) {
//aqui eu consigo obter qualquer informação, como:
//nome da propriedade.
System.out.println(ex.getPropertyName());
//valor do argumento passado.
System.out.println(ex.getArgumento());
//valor maximo do comprimento permitido.
System.out.println(ex.getLimit());
//a entidade onde a exceção foi gerada
System.out.println(ex.getSource());
//o tamanho do comprimento encontrado
System.out.println(ex.getSize());
}[/code]
assim acredito que estou fazendo ficar bem facil e dinamico meu código e melhorando o tratamento de exceções…
Ps.: tenho uma classe chamda Consistencies, para fazer os testes pra mim, pra não ficar poluindo de + os bens com os testes de consistencia, assim ficaria algo assim
Ps.2: esse é uma pequena parte das minha exceções, apenas para exemplificar
E você pode me dizer onde que você está se recuperando do erro? Usar exceptions verificados e ainda por cima simplesmente para logar o erro não me parece uma boa estratégia por tudo que já foi debatido neste tópico.
E você pode me dizer onde que você está se recuperando do erro? Usar exceptions verificados e ainda por cima simplesmente para logar o erro não me parece uma boa estratégia por tudo que já foi debatido neste tópico.
[/quote]
Quem falou em usar exceptions verificadas só para logar erro ?? …
A questão ate onde entendo é que vc deve no limite da camada, mostrar para quem vá usa-la que ela lança exceções, e que o usuario deve estar ciente destas exceções, e trata-los como achar conviniente… caso não seja capaz de tratar, basta avisar com um throws, ou usando o padrão handle, convertendo a exceção gerada na camada de baixo, em uma desta camada, de forma que a proxima camada de cima, não precise conhecer a que esta abaixo desta…
Por exemplo, o meu start do banco, que cria o SessionFactory do Hibernate é um método que lança exceção verificada, isso se justifica, pois existe N possiveis casos onde isso pode gerar exceções, o banco pode não estar instalado na maquina, pode não haver conexão com a internet ou intranet para conectar com o banco, pode ocorrer N coisas, portanto tenho um exceção verificada nesse ponto… assim eu monto minha session factory explicitamente, através de uma chamada, que lança exceções… faço verificado nesse ponto, por acreditar que mesmo fazendo tudo certo dentro do programa, um fator totalmente externo (como uma desconexão com a internet) pode ocasionar em problemas aqui…
Os repositorios por sua vez, que utilizam a conexão do hibernate e o sessionfactory, caso a sessionFactory não esteja presente, eu não lanço exceções verificadas, pois acho q isso poluiria de verdade o código, faço um tratamento e lanço Runtimes, acredito que a conexão que foi feita de modo explicito anteriormente e com a exceção verificada, vai fazer um correto tratamento, posteriormente lembranco apenas que a exceção pode surgir, mais q não precisa ser verificada…
Eu tento tomar bastante cuidado, ao lançar as exceções verificadas, acredito que o melhor momento pra faze-lo é quando mesmo que vc esteja fazendo tudo direito, mesmo assim algo pode dar errado, por motivos externos, Um banco de dados desligado, um arquivo que deveria estar em um lugar e não esta… etc etc etc…
…
No exemplo do post acima, modelando uma entidade, não faço verificado, pois acredito que o erro seja realmente RunTime, não ha motivos de obrigar a fazer um try{}catch(){} em um set da entidade, o parametro estar dentro das especificações é algo q eu posso controlar antes de mandar o valor para entidade, portanto posso ter 100% de garantia que o valor q mando pra entidade é conforme…
já na hora de salvar uma entidade, por exemplo, não tenho como ter 100% de certeza que consigo salvar a entidade, não tenho como ter 100% de certeza que não vou esbarrar num CONSTRAINT de algum campo UNIQUE por exemplo, e nessa hora, mesmo eu fazendo tudo certo algo pode dar errado… por isso… Repositories.save(entity); gera exceções verificadas… assim acredito estar fazendo certo…
com findAll(), findById(id), findByNome()…, deletes(), por exemplo, não faço verificado, pois se eu garantir que os dados que estou mandando estão corretamente, o erro so vem, se a conexão com o banco estiver ausente, o que trato la no inicio, na hora de start o programa…
enfim… assim tenho exceções verificadas, e não verificadas…
Edit.: Não acho correto por exemplo, ao fazer um Repositories.save(clienteJoao); receber uma SQLException, apenas com uma mensagem “Constraint Violation Unique Key bla bla bla…” … como programando la no controle entre a view e o modelo, vou conseguir tratar um erro desse ??, tenho que dentro do repositorio conseguir entender o que é esse erro que o hibernate gera, que é gerado por conta de um erro do SQL, e tenho que tratalo, devo mastigar o erro, posi ali que estou programado com a camada de persistencia, ali eu tenho que fazer isso virar legivel, de forma que daqui, saia algo como ConstraintViolationException que contenhas informações como, a referencia a entidade que continha o valor que gerou a exceção (a partir dela da pra pegar o nome da entidade, ou ate mesmo recuperar os dados da entidade, mostrar de volta par a view, e pedir que seja alterado o compo onde há a violação), valor que não foi permitido (se possivel com o nome da propriedade, assim podendo especificar para a view o que o meu usuario deve mudar, para poder salvar o registro), o valor que era esperado, e outras coisas, que seja util, e de facil interpretação para que o controle, através de um try{}catch(){} obrigatoriamente verificado, possa tratar, e repassar o erro para a view, com algo elegante como:
Verificamos que o CPF : 123.456.789-00 já existe em nosso banco, cadastrado para o senhor “Fulano de tal”, assim não foi possível cadastrar o Senhor “Beltrano da Silva” sobre o mesmo número de CPF, o que deseja fazer ? carregar os dados de “Beltrano da silva”? Salvar as novas informações digitadas para “Fulano de tal” por cima dos dados de “Beltrano da silva” ?
enfim essas coisas eu posso verificar, no momento da exceção, por gerar uma Exception rica em informação, para melhroar o tratamento
E você pode me dizer onde que você está se recuperando do erro? Usar exceptions verificados e ainda por cima simplesmente para logar o erro não me parece uma boa estratégia por tudo que já foi debatido neste tópico.
[/quote]
Quem falou em usar exceptions verificadas só para logar erro ?? … [/quote]
O seu exemplo não fez nada alem de um sysout.
Para ele estar ciente basta você documentar no javadoc as invariantes do seu objeto, pré condições das operações e exceptions lançadas. Além disso, ter testes automatizados na sua API para que ele possa saber como usa-la corretamente.
E o que o cliente do seu objeto poderia fazer com essa exception alem de lança-la para uma camada acima? Daria para se recuperar? Percebe que não faz sentido essas checked exceptions?
[quote=Lavieri]Eu tento tomar bastante cuidado, ao lançar as exceções verificadas, acredito que o melhor momento pra faze-lo é quando mesmo que vc esteja fazendo tudo direito, mesmo assim algo pode dar errado, por motivos externos, Um banco de dados desligado, um arquivo que deveria estar em um lugar e não esta… etc etc etc…
…
já na hora de salvar uma entidade, por exemplo, não tenho como ter 100% de certeza que consigo salvar a entidade, não tenho como ter 100% de certeza que não vou esbarrar num CONSTRAINT de algum campo UNIQUE por exemplo, e nessa hora, mesmo eu fazendo tudo certo algo pode dar errado… por isso… Repositories.save(entity); gera exceções verificadas… assim acredito estar fazendo certo… [/quote]
Como eu disse acima, nesses casos, não existe como se recuperar do problema, não faz o menor sentido usar checked exceptions. E mesmo que fizesse, na resposta acima eu mostro como tornar a vida do cliente do seu objeto menos burocratica.
Dá uma relida com calma em toda essa thread desde a primeira página que tem várias dicas pra entender o que eu coloquei aqui.
[]s
A questão de se recuperar ou não do problema é algo parcial… em algum momento, a não ser que eu queira que o meu usuario veja um despejo de StackTrace eu vou ter que usar o Try-Cacth… sendo assim, ao conectar com o banco, gerando tal problema, eu devo tratar, e tomar alguma atitude.
Dizer que a exceção é checked, para mim é util, quando vc deve avisar para o cliente do seu objeto, que mesmo que ele faça tudo certo, mesmo assim, algo pode dar errado, e que ele arrume tratamento para isso, ou seja, que ele tenha o plano B, pois isso não depende do meu objeto, nem dele me passar todos os argumentos corretamente… por isso o que vai fazer é TENTAR(try) usar o meu objeto, ele nem eu tem como garantir que dará certo
As exceções não verificadas indicam ao cliente do meu objeto, que se ele não mandar todos os argumentos corretamente, neste caso uma exceção será lançada, esta exceção, só vai depender dele, e ele tem como resolver todos os problemas antes do argumento chegar a meu objeto de forma ilegal, sendo assim, ele não precisa usar TRY, ou seja, ele não precisa tentar usar o meu objeto, pois se os argumentos estão corretos o uso funcionará…
…
For isso, acredito que quando vc esta programando algo generico, fazendo utils, por exemplo, que serve a varios pontos do programa, essa sua “API” que vc ta montando, gera algumas exceções, que estes exceções devem ser bem documentados, e sempre que preciso (se baseando principalmente nos 2 pontos falado anteriormente) deve ser feito a exceção verificada sim…
Ps.: eu li a thread toda, só não concordo que exceções chekeds são inuteis, e que devem ser abolidas… assim como acredito como falei no outro post, ainda nesta mesma pagina, que as exceções devem ser tratadas sempre por quem mais entenda do assunto, e devem ser lançadas sempre com o maximo de detalhes possiveis, para que a pessoa que vá fazer o tratamento, possa saber como o problema ocorreu, sem necesssidades de debugs e etcs
Para isso se faz um tratamento genérico nas aplicações web onde existe uma páginas de erro com mensagens amigaveis. É bem simples de fazer e todos os frameworks atuais dão suporte a isso.
Como eu disse acima e em toda thread você obtem o mesmo resultado com exceções uncheked só que dá a liberdade para o seu cliente escolher ao invés de impor que ele faça um try-catch. Se ele achar por bem fazer alguma coisa ele ainda sim tem essa opção de fazer o try-catch.
Isso gera sim uma burocracia bem chata.
Curioso é que Java é uma das unicas se não a única linguagem que tem checked exceptions. Como será que os programadores das outras linguagens conseguem trabalhar sem esse recurso? Já dei uma dica nas citações acima. Seria java mais esperta que as demais?
Da uma lida no que Bruce eckel disse sobre o assunto a alguns anos atrás: http://www.mindview.net/Etc/Discussions/CheckedExceptions
[quote=Lavieri]
public class Pessoa {
private String nome;
private String cpf;
private String email;
//...
public void setNome(String nome) {
if (nome == null)
throw new IllegalNullArgumentException(this,"nome",nome);
if (nome.length() > 45)
throw new MaximumSizeException(this,"nome",nome,45,nome.length());
this.nome = nome;
}
// o mesmo faço para cpf, email etc etc...
}
Ps.2: esse é uma pequena parte das minha exceções, apenas para exemplificar[/quote]
Muito bem. É isso mesmo.
Apenas para o ajudar mais recomendo que implemente uma classe utilitária de consistencia.
Assim em vez de ifs vc faria
public void setNome(String nome) {
Consist.notNull(nome); // lança new IllegalNullArgumentException
Consist.maxLength(nome, 45); // lança new MaximumSizeException
this.nome = nome;
}
Avalie se o argumento this realmente é importante para os seus exceptions ( não deveria ser porque ele já consta do stacktrace)
[quote=sergiotaborda][quote=Lavieri]
public class Pessoa {
private String nome;
private String cpf;
private String email;
//...
public void setNome(String nome) {
if (nome == null)
throw new IllegalNullArgumentException(this,"nome",nome);
if (nome.length() > 45)
throw new MaximumSizeException(this,"nome",nome,45,nome.length());
this.nome = nome;
}
// o mesmo faço para cpf, email etc etc...
}
Ps.2: esse é uma pequena parte das minha exceções, apenas para exemplificar[/quote]
Muito bem. É isso mesmo.
Apenas para o ajudar mais recomendo que implemente uma classe utilitária de consistencia.
Assim em vez de ifs vc faria
public void setNome(String nome) {
Consist.notNull(nome); // lança new IllegalNullArgumentException
Consist.maxLength(nome, 45); // lança new MaximumSizeException
this.nome = nome;
}
Avalie se o argumento this realmente é importante para os seus exceptions ( não deveria ser porque ele já consta do stacktrace)
[/quote]
[quote=Lavieri]…
Ps.: tenho uma classe chamda Consistencies, para fazer os testes pra mim, pra não ficar poluindo de + os bens com os testes de consistencia, assim ficaria algo assim
Ps.2: esse é uma pequena parte das minha exceções, apenas para exemplificar[/quote]
Eu ja tinha ate falado no outro post que fazia por meio do Consistencies, só não coloquei direto no exemplo, pra ficar mais facil o exemplo…
Consistencies.java ai ta só uma parte do .java … ele é muito grande heheh, ai nem postei la o código todo…
Sergio… eu uso o “this” justamente pq a exceção quase nunca é lançada do proprio objeto, ela sempre passa pelmenos pelo “Consistenties” assim fica melhor de fazer a referencia ao objeto onde a exceção ocorreu, se tiver uma ideia melhor… gostaria q fosse facil de pegar o objeto… com apenas… ex.getSource()
[quote=Lavieri]
Sergio… eu uso o “this” justamente pq a exceção quase nunca é lançada do proprio objeto, ela sempre passa pelmenos pelo “Consistenties” assim fica melhor de fazer a referencia ao objeto onde a exceção ocorreu, se tiver uma ideia melhor… gostaria q fosse facil de pegar o objeto… com apenas… ex.getSource()[/quote]
Você pode utilizar o truque de determinar quem lançou a exceção, para isso basta analisar o stacktrace da exceção.