sexta-feira, 6 de dezembro de 2013

Propagação Deficiente - Antipattern de exceção

Para entender melhor este antipattern, é necessário entender o que compõe uma exceção.

Exceção Exemplo #1
ApplicationException: Erro ao carregar configuracoes
    at LeitorConfiguracoes.lerArq(LeitorConfiguracoes.java:404)
    at DeamonAplicacao.iniciar(DeamonAplicacao.java:376)
    at java.lang.Thread.run(Thread.java:722)
Caused by: java.lang.NullPointerException
    at LeitorConfiguracoes.parser(LeitorConfiguracoes.java:120)
    at LeitorConfiguracoes.lerArq(LeitorConfiguracoes.java:386)
    ... 2 more
Identificando os componentes da exceção:
  • Classe: ApplicationException
  • Mensagem: Erro ao carregar configuracoes
  • Stack Trace: desde LeitorConfiguracoes.lerArq, até java.lang.Thread.run
  • Caused by: é a nova exceção a partir da linha "Caused by" (inclusive)
Lembrando que a mensagem, e o "caused by" não são obrigatórios.
Veja o outro exemplo abaixo:
Exceção Exemplo #2
java.util.NoSuchElementException
    at LeitorConfiguracoes.parser(LeitorConfiguracoes.java:124)
    at LeitorConfiguracoes.lerArq(LeitorConfiguracoes.java:386)
    at DeamonAplicacao.iniciar(DeamonAplicacao.java:376)
    at java.lang.Thread.run(Thread.java:722)
Identificando os componentes da exceção:
  • Classe: java.util.NoSuchElementException
  • Mensagem: não tem (ela deveria estar na frente do nome da classe da exceção)
  • Stack Trace: desde LeitorConfiguracoes.parser, até java.lang.Thread.run
  • Caused by: não tem
Com base nos exemplos acima, agora mostro o erro mais comum, quando se trata de exceção:
catch (Exception e) {
    log.error(e.getMessage());
}
Ou
catch (Exception e) {
    throw new ApplicationException(e.getMessage());
}
Para a Exceção Exemplo #1, dos 4 elementos que tem a exceção, a expressão "e.getMessage()" representa apenas "Erro ao carregar configuracoes". Ela seria logada da seguinte forma:

17:52:37 [ERROR] Erro ao carregar configuracoes
Somente com esta informação, como é possível fazer um trobbleshooting eficiente? A classe, a Stack Trace e o Caused By são MUITO importantes. A mensagem é apenas um fragmento da exceção.
Para a Exceção Exemplo #2, é muito pior. A exceção não tem mensagem. E apenas encontraríamos uma linha perdida no log com a seguinte aparência.
17:52:37 [ERROR] null
Uma linha assim não ajudaria em nada, praticamente.
Então lembre-se:

  • Em um log de erro, o primeiro parâmetro é uma mensagem, e o segundo parâmetro a exceção (com isso, todos os componentes da exceção são logados)
  • Se for encapsular e lançar a nova exceção, em geral, existe um construtor da exceção onde o primeiro parâmetro é uma mensagem, e o segundo parâmetro é a exceção (parâmetro cause)

catch (Exception e) {
    log.error("Erro na operacao", e);
}
Ou
catch (Exception e) {
    throw new ApplicationException("Erro na aplicacao", e);
}

Nenhum comentário:

Postar um comentário