Estou trabalhando como contratado para projetar aplicativos Java corporativos para meu cliente no papel de líder técnico. O aplicativo será usado pelos usuários finais e haverá uma equipe de suporte que o apoiará quando sairmos.
Os outros líderes técnicos com quem estou trabalhando têm a impressão de que o tratamento de exceções deixará o código sujo. O sistema deve lançar exceções verificadas apenas da camada Serviço e o restante do código deve lançar exceções de tempo de execução de todas as outras camadas, para que não haja necessidade de lidar com as exceções não verificadas.
Qual é a necessidade de sempre lançar uma exceção não verificada em um aplicativo de negócios?
Da minha experiência no passado sobre exceções de tempo de execução:
1) Exceções não verificadas tornam o código imprevisível, pois elas não aparecem no Javadoc.
2) Lançar exceções não verificadas em um aplicativo de negócios não faz sentido, porque quando você o lança e ele segue direto no rosto dos usuários, como você o explica? Já vi muitas aplicações web que mostram o 500 -Internal Error. Contact Administrator
que não significa nada para um usuário final ou para a equipe de suporte que gerencia a aplicação.
3) O lançamento de exceções de tempo de execução força os usuários da classe que lançam a exceção a percorrer o código-fonte para depurar e ver por que a exceção é lançada. Isso só pode ser evitado se o Javadoc da exceção de tempo de execução estiver excelentemente documentado, o que eu acho que nunca é um caso.
fonte
@throws
tag, o que, a propósito, é uma boa prática.@throws
tag Javadoc para documentar cada exceção não verificada que um método pode lançar, mas não use a palavra-chave throws para incluir exceções não verificadas na declaração do método.Respostas:
As exceções verificadas são uma falha no projeto da linguagem. Eles o forçam a ter abstrações extremamente vazadas e código sujo. Eles devem ser evitados o máximo possível.
Quanto aos seus pontos:
1) As exceções marcadas tornam o código sujo e não menos imprevisível, pois são exibidos em todos os lugares .
2) Como uma exceção verificada está sendo mostrada ao usuário melhor? A única diferença real entre as exceções marcadas e as não verificadas é técnica e afeta apenas o código fonte.
3) Já ouviu falar de rastreamentos de pilha? Eles informam exatamente onde a exceção foi lançada, independentemente de estar marcada ou desmarcada. Na verdade, as exceções verificadas tendem a ser piores para a depuração, porque geralmente são agrupadas, o que leva a rastreamentos de pilha mais longos e mais feios, ou até perdidos por causa do empacotamento incorreto.
Existem dois tipos de exceções: aquelas que ocorrem "normalmente" e geralmente são tratadas muito perto de onde elas ocorrem, e aquelas que são realmente excepcionais e podem ser tratadas genericamente em uma camada muito alta (basta interromper a ação atual e registrá-la / mostrar um erro).
As exceções verificadas foram uma tentativa de colocar essa distinção na sintaxe do idioma no momento em que as exceções são definidas. Os problemas com isso são
fonte
SQLException extends Exception
significar que escolher lançar umSQLException
porque um erro está relacionado ao acesso ao banco de dados significa automaticamente que a exceção é verificada. E você pode documentar exceções não verificadas nos comentários do Javadoc. Funciona bem para todos os outros idiomas.A meu ver, que tipo de exceção é lançada depende do que seu código está fazendo.
Lancei exceções verificadas quando espero que possam acontecer com bastante frequência (usuários inserindo dados duvidosos, por exemplo) e espero que o código de chamada lide com a situação.
Lancei exceções não verificadas / de tempo de execução (não tão frequentemente quanto verificadas) quando tenho uma situação rara que não espero que o código de chamada manipule. Um exemplo pode ser algum tipo de erro relacionado à memória estranha que eu nunca espero que ocorra. Desmarcado são os tipos de erros que você espera derrubar o aplicativo.
Nenhuma exceção deve aparecer na frente de um usuário sem algum nível de suporte. Mesmo que seja apenas um "recorte e cole esse despejo de erro em um email". Nada é mais irritante para um usuário do que saber que há um erro, mas não há detalhes ou ações que eles podem tomar para iniciar a correção.
Meu palpite é que a filosofia que você menciona vem de uma de duas fontes:
fonte
Se você não deseja exceções de tempo de execução desmarcadas, por que está usando java? Existe a possibilidade de exceções de tempo de execução em quase todos os lugares - principalmente as exceções NullPointerException, ArithmeticException, ArrayIndexOutOfBounds, etc.
E quando você ler os arquivos de log de algum sistema J2EE, como, por exemplo, uma instalação do SAP NetWeaver, verá que essas exceções acontecem literalmente o tempo todo.
fonte
Existem algumas regras para o tratamento de exceções que você deve ter em mente. Mas primeiro, é preciso lembrar que as exceções fazem parte da interface exposta pelo código; documentá-los . Isso é especialmente importante quando a interface é pública, é claro, mas também é uma boa ideia em interfaces privadas.
As exceções devem ser tratadas apenas no ponto em que o código pode fazer algo sensato com elas. A pior opção de manuseio é não fazer nada a respeito, o que deve ser feito apenas quando essa for exatamente a opção correta. (Quando tenho uma situação desse tipo no meu código, incluo um comentário nesse sentido, para não me preocupar com o corpo vazio.)
A segunda pior opção é lançar uma exceção não relacionada sem o original anexado como causa. O problema aqui é que as informações da exceção original que permitiriam o diagnóstico do problema foram perdidas; você está criando algo com o qual ninguém pode fazer nada (exceto reclamar que "não funciona" e todos sabemos como odiamos esses relatórios de erros).
Muito melhor é registrar a exceção. Isso permite que alguém descubra qual é o problema e corrija-o, mas você só deve registrar a exceção no ponto em que ela seria perdida ou relatada por uma conexão externa. Isso não ocorre porque o registro com mais frequência é um grande problema, como tal, mas porque o registro excessivo significa que o log consome mais espaço sem conter mais informações. Depois de registrar a exceção, você pode relatar uma précis ao usuário / cliente com boa consciência (desde que inclua também o tempo de geração - ou outro identificador de correlação) nesse relatório para que a versão curta possa ser correspondida com os detalhes, se necessário).
A melhor opção é, é claro, lidar completamente com a exceção, lidando com a situação de erro na sua totalidade. Se você pode fazer isso, faça de qualquer maneira! Pode até significar que você pode evitar ter que registrar a exceção.
Uma maneira de lidar com uma exceção é lançar outra exceção que fornece uma descrição de nível superior do problema (por exemplo, “
failed to initialize
” em vez de “index out of bounds
”). Esse é um bom padrão, desde que você não perca as informações sobre a causa da exceção; use a exceção detalhada para inicializar acause
exceção de nível superior ou registre os detalhes (conforme discutido acima). O registro é mais apropriado quando você está prestes a cruzar um limite entre processos, como uma chamada IPC, porque não há garantia de que a classe de exceção de baixo nível esteja presente no outro extremo da conexão. Manter como causa anexa é mais apropriado ao cruzar um limite interno.Outro padrão que você vê é pegar e soltar:
Esse é um anti-padrão, a menos que você tenha restrições de tipo de outras
catch
cláusulas, o que significa que você não pode simplesmente deixar a exceção passar por conta própria. Então é apenas um recurso feio do Java.Não há diferença real entre exceções verificadas e desmarcadas, exceto o fato de que você deve declarar exceções verificadas que cruzam os limites do método. Ainda é uma boa idéia documentar exceções não verificadas (com o
@throws
comentário do javadoc) se você souber que elas estão sendo lançadas deliberadamente pelo seu código. Não jogue deliberadamentejava.lang.Error
ou suas subclasses (a menos que esteja escrevendo uma implementação da JVM).Opinião: um caso de erro inesperado sempre representa um erro no seu código. As exceções verificadas são uma maneira de gerenciar essa ameaça, e onde os desenvolvedores usam deliberadamente exceções não verificadas como uma maneira de evitar problemas ao lidar com casos de erro, você está acumulando muitas dívidas técnicas que precisarão limpar por algum tempo se você quiser código robusto. A manipulação de erro superficial não é profissional (e observar a manipulação de erro é uma boa maneira de determinar quão bom é o programador).
fonte
Eu acho que você só deve lançar exceção marcada quando o aplicativo pode se recuperar. Portanto, os usuários da sua biblioteca devem capturar essas exceções e fazer o que for necessário para recuperar. Qualquer outra coisa deve ser desmarcada.
Como exemplo,
Se o seu aplicativo carregar dados de um arquivo ou de um banco de dados. Então,..
o chamador sempre pode capturar a MissingDataFileException verificada e, em seguida, tentar carregar os dados do banco de dados.
fonte