Tratamento de exceção, de quem é a responsabilidade?

Nos artigos que li, informam que:

1.Não devemos tratar todas exçeções genericamente.
2.Não lancar exeções genérica ( pede-se para criar novos tipos )
3.Utilizar mecanismos de logging
4.Utilizar o finally para finalizar recursos.

Tenho feito isso, entretanto eu crio somente uma classe que herda exception e envio os erros para ele.
Gostaria de saber :
Perguntas :
Como o pessoal realiza essa tarefa nos códigos?
Quem deve tratar o erro de lógica , quem acessa ou o próprio método ?
Quem deve tratar o errro de persistencia de dados ?

vejam o que uso para exception


public class BusinessException  extends Exception{
	private static final long serialVersionUID = 1L;

	public BusinessException(String message ){
		super(message);
		
		
	}

}

[quote=albama@bol.com.br]Nos artigos que li, informam que:

1.Não devemos tratar todas exçeções genericamente.
2.Não lancar exeções genérica ( pede-se para criar novos tipos )
3.Utilizar mecanismos de logging
4.Utilizar o finally para finalizar recursos.

[/quote]

  1. se você quer dizer que temos que ser específicos é verdade, quanto mais você for mais facil será depois debugar o código, mas sem preciosismos… KISS
  2. idem anterior
  3. mecanismos de loggin facilitam bastante, você pode colocar data, linha onde ocorreu a excessão, thread, etc, além do que depois você pode mudar o layout do log, mudar para log em tabela, etc
  4. mesmo que você feche o recurso no finally é bom também fechar no catch

catch (Exception e) {
  if (recurso is oppened) {
    close();
  }
}
finally {
  close();
}

Eu gosto de criar uma excessão para cada coisa, uma para negócio, uma para BD, uma para GUI, etc
Eu acho que quem é responsável por tratar a excessão é sempre quem a originou…

você já leu isto aqui?

Edit: só mais um comentário, evite engolir excessões, trate eles sempre que possível, e se acontecer algo que não saiba como tratar logue o maior número de informações possíveis, principalmente se essas informações forem parar no log do seu servidor…
abs

Isso não seria redundância? Código repetido a toa? Afinal, se o finally existe, vamos usá-lo.

Quanto ao tratamento de excessões, é algo muito relativo. São casos e casos, mas em geral, quem trata as excessões (que são lançadas pelos métodos chamados) é quem chamou o método. Imagine a situação:

public class Empresa {
    List<Funcionario> funcionarios = null;

    public Empresa() {
        funcionarios = new ArrayList<Funcionario>();
    }

    public void addFuncionario(Funcionario f) {
        if (f == null) {
            throw new BussinesException("O funcioário não pode ser nulo.");
        }
        funcionarios.add(f);
    }

    public void listaTodosFuncionarios() {
        if (funcionarios.isEmpty()) {
            throw new BussinesException("Nenhum funcionário cadastrado.");
        }
        for (Funcionario f : funcionarios) {
            System.out.format("Funcionário: %s%nSalário: %f%n%n", f.getNome(), f.getSalario());
        }
    }
}

E quem construir um objeto Empresa e chamar os métodos, faz a verficação das excessões.

Vejam nest simples exemplo, de quem é a responsabilidade de trata essa exceção ?

Ela pertence as Exception sem as de RuntimeException.

		public int stringToInt(String value) throws NumberFormatException{
                    //codigo
            };
  Ao chamar o método stringToInt() , o desenvolvedor é obrigado a tratar a exceção, caso contrario dará erro de compilação.
  Isso acontece devido a presençaa da clausula throws na declaração de método e a checkagem de  NumberFormatException.
  Neste caso a responsabilidade é de quem chama  o método e não de quem  codificou.
  
 Vocês acham correto isso ?

 Marco Aurélio

[quote=albama@bol.com.br]Vejam nest simples exemplo, de quem é a responsabilidade de trata essa exceção ?

Ela pertence as Exception sem as de RuntimeException.

		public int stringToInt(String value) throws NumberFormatException{
                    //codigo
            };
  Ao chamar o método stringToInt() , o desenvolvedor é obrigado a tratar a exceção, caso contrario dará erro de compilação.
  Isso acontece devido a presençaa da clausula throws na declaração de método e a checkagem de  NumberFormatException.
  Neste caso a responsabilidade é de quem chama  o método e não de quem  codificou.
  
 Vocês acham correto isso ?

 Marco Aurélio

[/quote]
Nesse caso sim, pois quem codificou a classe não sabe exatamente o que vão fazer com ela. Se você usa a classe para ler a idade de uma pessoa, por exemplo, você deve tratar essa excessão em seu código, mostrando a mensagem “Idade inválida”. Já outra pessoa pode usar para ler códigos de barras e deve fazer uma verificação pois se a conversão for inválida precisa chamar determinado método ou etc. São ações diferentes, logo cada ação necessita de uma verificação.

Não pensei desta forma , mas concordo com você , porém neste caso seria uma espécie de método utilitário, aí entra outras questões.

1.Para ela ter varias funções ela deverá estár no local correto.Um local comum, pois se quem chama tratará o erro, da sua forma.

2.Quando codificamos um método que tem uma função especifica, devemos tratar o erro na propría classe ? Ou lançar a exceção ?
Pois neste caso o metodo tem uma função específica.

[quote=marcobiscaro2112][quote=André Fonseca]

4. mesmo que você feche o recurso no finally é bom também fechar no catch


catch (Exception e) {
  if (recurso is oppened) {
    close();
  }
}
finally {
  close();
}


[/quote]
Isso não seria redundância? Código repetido a toa? Afinal, se o finally existe, vamos usá-lo.
[/quote]

Você está certo marco, eu me confundi

O que eu quis dizer é que é bom você chegar se o recurso não é nulo antes de você tentar fechá-lo, pois senão vai gerar outra excessão dentro do finally

Algo assim

finally { if (recurso!=null) { recurso.close(); } }

abs

[quote=André Fonseca][quote=marcobiscaro2112][quote=André Fonseca]

4. mesmo que você feche o recurso no finally é bom também fechar no catch


catch (Exception e) {
  if (recurso is oppened) {
    close();
  }
}
finally {
  close();
}


[/quote]
Isso não seria redundância? Código repetido a toa? Afinal, se o finally existe, vamos usá-lo.
[/quote]

Você está certo marco, eu me confundi

O que eu quis dizer é que é bom você chegar se o recurso não é nulo antes de você tentar fechá-lo, pois senão vai gerar outra excessão dentro do finally

Algo assim

finally { if (recurso!=null) { recurso.close(); } }

abs[/quote]
OK, essa observação é importante, para não gerar um NullPointerException. Bem observado. :slight_smile:

[quote=albama@bol.com.br]Não pensei desta forma , mas concordo com você , porém neste caso seria uma espécie de método utilitário, aí entra outras questões.

1.Para ela ter varias funções ela deverá estár no local correto.Um local comum, pois se quem chama tratará o erro, da sua forma.

2.Quando codificamos um método que tem uma função especifica, devemos tratar o erro na propría classe ? Ou lançar a exceção ?
Pois neste caso o metodo tem uma função específica.
[/quote]
Dificilmente se trata a exceção no próprio método, pois ela serve como uma espécie de notificação para o quem chamou esse método, informando que algo deu errado (e passa os detalhes). Se a exceção é tratada dentro do método, quem o chamou simplesmente não sabe se a execução correu como devia ou não, e isso pode influenciar na maneira como o programa deve seguir a partir de determinado ponto. Percebe o problema?

[quote=albama@bol.com.br]Vejam nest simples exemplo, de quem é a responsabilidade de trata essa exceção ?

Ela pertence as Exception sem as de RuntimeException.

		public int stringToInt(String value) throws NumberFormatException{
                    //codigo
            };
  Ao chamar o método stringToInt() , o desenvolvedor é obrigado a tratar a exceção, caso contrario dará erro de compilação.
  Isso acontece devido a presençaa da clausula throws na declaração de método e a checkagem de  NumberFormatException.
  Neste caso a responsabilidade é de quem chama  o método e não de quem  codificou.
  
 Vocês acham correto isso ?

 Marco Aurélio

[/quote]

c vc extender RuntimeException não é obrigado a tratar cada chamada de método por Try{}catch{}finally{} … pois isso quer dizer, que estas exceções ocorrerão apenas em tempo de execução, podendo o programador escolher não tratalas em código em algum trecho…

O ideal é vc deichar o responsavel tratar, vou te dar um exemplo… c vc tem 1 classe que mexe na persistencia do banco, lida diretamente no banco, quando alguem pede pra inserir dados, essa classe vai simplismente infiar o dado no banco, se o dado não entrar pq ta duplicado, ele vai jogar o erro pra cima, e isso e o correto, essa classe que trata o banco, não tem q entender do seu negocio, e por isso não tem que testar c o dado é ou não duplicado, só deve lançar uma exceção legível…

Digamos que vc tenha uma classe intermediaria e mediadora (um repositorio generico por exemplo) … que aceite comandos do tipo
add(Object obj) para adcionar a data base … e nessa calsse ele verifique pela calsse do objeto, a qual responsavel mandar para montar a SQL correspondente… apesar desta classe invocar o método da classe anterior de adcionar ao banco, de forma implicita, ela também não entende nada do negocio, então ela passa a informação, tenta inserir, deu erro ela devolve o erro pra cima e pronto…

La em cima tu tem uma classe que conversa com usuario, onde ele pede uma inserção no banco, vc tenta inserir e da a exceção de duplicação, nessa hora vc tem q tratar e falar pro usuario algo como, desculpe esse dado já existe e não é possivel duplicação para o campo X, assim vc mantem a integridade…

por outro lado, todas essas etapas podem testar coisas como a nulidade de algum registro, visto a facilidade dessa rotina, evitando enviar uma variável nula camadas mais abaixo onde ela sabe que ocorrerá um erro…

Por exemplo, o repositoio generico, sabe que a classe que lida diretamente com a persistencia não aceita objetos nulos, e ela sabe verificar se um objeto é nulo, então ela pode fazer a verificação, e devolver a exeção, sem ter que descer mais a fundo no código, enfim é tudo uma questão de ver quem é responsavel pelo que mesmo.