Permet de considérer la situation où vous avez le code fourni de:
public void delete() throws IOException, SQLException { // Non-Compliant
/* ... */
}
Le danger ici est que le code que vous écrivez pour appeler delete()
ressemblera à ceci :
try {
foo.delete()
} catch (Exception e) {
/* ... */
}
C'est mauvais aussi. Et il sera attrapé avec une autre règle qui drapeaux attrapant la classe de base Exception.
La clé est de ne pas écrire de code qui vous donne envie d'écrire du mauvais code ailleurs.
La règle que vous rencontrez est plutôt commune. Checkstyle l' a dans ses règles de conception:
ThrowsCount
Limite le nombre d'instructions au nombre spécifié (1 par défaut).
Justification: les exceptions font partie de l'interface d'une méthode. Déclarer une méthode générant trop d'exceptions ayant une racine différente rend la gestion des exceptions fastidieuse et conduit à des pratiques de programmation médiocres telles que l'écriture de code tel que catch (Exception ex). Cette vérification oblige les développeurs à placer les exceptions dans une hiérarchie telle que, dans le cas le plus simple, un seul type d'exception doit être vérifié par un appelant, mais toute sous-classe peut être interceptée spécifiquement si nécessaire.
Ceci décrit précisément le problème et le problème et pourquoi vous ne devriez pas le faire. C’est une norme bien acceptée que de nombreux outils d’analyse statique vont identifier et signaler.
Et bien que vous puissiez le faire en fonction de la conception de la langue, et il peut arriver que ce soit la bonne chose à faire, c'est quelque chose que vous devriez voir et que vous devriez immédiatement dire "pourquoi je fais ça?" Cela peut être acceptable pour un code interne où tout le monde est assez discipliné pour ne jamais le faire catch (Exception e) {}
, mais le plus souvent, j'ai vu des gens prendre des raccourcis, en particulier dans des situations internes.
Ne faites pas que les gens qui utilisent votre classe veuillent écrire du mauvais code.
Je devrais souligner que l'importance de cela est réduite avec Java SE 7 et les versions ultérieures, car une seule instruction catch peut intercepter plusieurs exceptions ( capture de plusieurs types d'exceptions et retransmission d'exceptions avec une vérification de type améliorée à partir d'Oracle).
Avec Java 6 et les versions antérieures, vous auriez un code ressemblant à ceci:
public void delete() throws IOException, SQLException {
/* ... */
}
et
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;
}
Aucune de ces options avec Java 6 n'est idéale. La première approche viole DRY . Plusieurs blocs faisant la même chose, encore et encore - une fois pour chaque exception. Vous souhaitez enregistrer l'exception et la renvoyer? D'accord. Les mêmes lignes de code pour chaque exception.
La deuxième option est pire pour plusieurs raisons. Premièrement, cela signifie que vous attrapez toutes les exceptions. Le pointeur Null se fait attraper là (et il ne devrait pas). De plus, vous renvoyez un mot, Exception
ce qui signifie que la signature de la méthode serait une source de deleteSomething() throws Exception
dégâts supplémentaires dans la pile, car les utilisateurs de votre code sont désormais contraints de le faire catch(Exception e)
.
Avec Java 7, ce n’est pas aussi important car vous pouvez faire:
catch (IOException|SQLException ex) {
logger.log(ex);
throw ex;
}
De plus, le type de vérification si l' on n'Attrapez les types des exceptions étant jeté:
public void rethrowException(String exceptionName)
throws IOException, SQLException {
try {
foo.delete();
} catch (Exception e) {
throw e;
}
}
Le vérificateur de type reconnaîtra qu'il nee
peut s'agir que de types ou . Je ne suis toujours pas très enthousiaste à propos de l'utilisation de ce style, mais cela ne cause pas le même code que sous Java 6 (dans lequel la signature de la méthode vous obligerait à utiliser la superclasse qui étend les exceptions).IOException
SQLException
Malgré tous ces changements, de nombreux outils d'analyse statiques (Sonar, PMD, Checkstyle) appliquent toujours les guides de style Java 6. Ce n'est pas une mauvaise chose. J'ai tendance à être d'accord avec un avertissement selon lequel celles-ci doivent toujours être appliquées, mais vous pouvez changer la priorité en priorité majeure ou mineure en fonction de la manière dont votre équipe les hiérarchise.
Si les exceptions doivent cocher ou décocher ... qui est une question de g r e un t débat que l' on peut facilement trouver d' innombrables messages de blog qui se place de chaque côté de l'argument. Toutefois, si vous utilisez des exceptions vérifiées, vous devriez probablement éviter de lancer plusieurs types, du moins sous Java 6.