Vamos considerar a situação em que você tem o código fornecido de:
public void delete() throws IOException, SQLException { // Non-Compliant
/* ... */
}
O perigo aqui é que o código que você escreve para chamar delete()
será:
try {
foo.delete()
} catch (Exception e) {
/* ... */
}
Isso também é ruim. E ele será pego com outra regra que sinaliza a captura da classe Exception base.
A chave é não escrever o código que faz você querer escrever um código ruim em outro lugar.
A regra que você está encontrando é bastante comum. O Checkstyle tem nas suas regras de design:
ThrowsCount
Restricts throws statements to a specified count (1 by default).
Rationale: Exceptions form part of a method's interface. Declaring a method to throw too many differently rooted exceptions makes exception handling onerous and leads to poor programming practices such as writing code like catch(Exception ex). This check forces developers to put exceptions into a hierarchy such that in the simplest case, only one type of exception need be checked for by a caller but any subclasses can be caught specifically if necessary.
Isso descreve precisamente o problema e qual é o problema e por que você não deve fazer isso. É um padrão bem aceito que muitas ferramentas de análise estática identificarão e sinalizarão.
E enquanto você pode fazê-lo de acordo com o design da linguagem, e pode ser momentos em que é a coisa certa a fazer, é algo que você deve ver e imediatamente "hum, por que estou fazendo isso?" Pode ser aceitável para o código interno, onde todos são disciplinados o suficiente para nunca catch (Exception e) {}
, mas na maioria das vezes eu vi pessoas cortando cantos, especialmente em situações internas.
Não faça pessoas usando sua turma quiserem escrever códigos ruins.
Devo salientar que a importância disso é diminuída com o Java SE 7 e posterior porque uma única instrução catch pode capturar várias exceções (Captando vários tipos de exceção e relançando as exceções com verificação de tipos aprimorada do Oracle).
Com o Java 6 e anterior, você teria um código semelhante a:
public void delete() throws IOException, SQLException {
/* ... */
}
e
try {
foo.delete()
} catch (IOException ex) {
logger.log(ex);
throw ex;
} catch (SQLException ex) {
logger.log(ex);
throw ex;
}
ou
try {
foo.delete()
} catch (Exception ex) {
logger.log(ex);
throw ex;
}
Nenhuma dessas opções com o Java 6 é ideal. A primeira abordagem viola DRY . Vários blocos fazendo a mesma coisa, de novo e de novo - uma vez para cada exceção. Você deseja registrar a exceção e relançá-la? Está bem. As mesmas linhas de código para cada exceção.
A segunda opção é pior por vários motivos. Primeiro, isso significa que você está pegando todas as exceções. Ponteiro nulo é pego lá (e não deveria). Além disso, você está relançando um Com o Java 7, isso não é importante porque você pode: Além disso, o tipo que verifica se um faz capturar os tipos de exceção que estão sendo lançados: O verificador de tipos reconhecerá que Apesar de todas essas mudanças, muitas ferramentas de análise estática (Sonar, PMD, Checkstyle) ainda estão aplicando os guias de estilo do Java 6. Não é uma coisa ruim. Tenho a tendência de concordar com um aviso para que ainda seja aplicado, mas você pode alterar a prioridade para eles em maior ou menor de acordo com a forma como sua equipe os prioriza. Se as exceções devem ser marcadas ou desmarcadas ... essa é uma questão de g r e um t debate que é fácil encontrar inúmeros posts ocupando cada lado do argumento. No entanto, se você estiver trabalhando com exceções verificadas, provavelmente deverá evitar lançar vários tipos, pelo menos no Java 6. Exception
, o que significa que a assinatura do método seria deleteSomething() throws Exception
, o que só faz uma bagunça na pilha, já que as pessoas que usam seu código agora são catch(Exception e)
. / p>
catch (IOException|SQLException ex) {
logger.log(ex);
throw ex;
}
public void rethrowException(String exceptionName)
throws IOException, SQLException {
try {
foo.delete();
} catch (Exception e) {
throw e;
}
}
e
pode somente ser dos tipos IOException
ou SQLException
. Eu ainda não estou muito entusiasmado com o uso desse estilo, mas ele não está causando código tão ruim quanto era no Java 6 (onde ele forçaria você a ter a assinatura do método como a superclasse que as exceções estendem). / p>