499 votes

Les arguments contre les exceptions vérifiées

Depuis plusieurs années, je ne parviens pas à obtenir une réponse décente à la question suivante : pourquoi certains développeurs sont-ils si opposés aux exceptions vérifiées ? J'ai eu de nombreuses conversations, j'ai lu des choses sur des blogs, j'ai lu ce que Bruce Eckel avait à dire (la première personne que j'ai vue s'exprimer contre elles).

Je suis en train d'écrire un nouveau code et je fais très attention à la façon dont je traite les exceptions. J'essaie de comprendre le point de vue de la foule "nous n'aimons pas les exceptions vérifiées" et je n'y arrive toujours pas.

Toutes les conversations que j'ai se terminent par la même question qui reste sans réponse... Laissez-moi vous expliquer :

En général (d'après la façon dont Java a été conçu),

  • Error est pour les choses qui ne devraient jamais être prises (VM est allergique aux cacahuètes et quelqu'un a fait tomber un pot de cacahuètes sur lui)
  • RuntimeException est pour les choses que le programmeur a mal faites (le programmeur a oublié la fin d'un tableau).
  • Exception (sauf RuntimeException ) est pour les choses qui sont hors du contrôle du programmeur (le disque se remplit lors de l'écriture dans le système de fichiers, la limite du gestionnaire de fichiers pour le processus a été atteinte et vous ne pouvez plus ouvrir de fichiers).
  • Throwable est simplement le parent de tous les types d'exception.

Un argument courant que j'entends est que si une exception se produit, tout ce que le développeur va faire est de quitter le programme.

Un autre argument courant que j'entends est que les exceptions vérifiées rendent plus difficile le remaniement du code.

Pour l'argument "tout ce que je vais faire est de quitter", je dis que même si vous quittez, vous devez afficher un message d'erreur raisonnable. Si vous vous contentez de gérer les erreurs, vos utilisateurs ne seront pas très heureux lorsque le programme quittera sans indication claire de la raison.

Pour ceux qui pensent que "cela rend difficile le remaniement", cela indique que le niveau d'abstraction approprié n'a pas été choisi. Plutôt que de déclarer qu'une méthode lance un IOException le IOException devrait être transformée en une exception plus adaptée à ce qui se passe.

Je n'ai pas de problème à envelopper Main avec catch(Exception) (ou dans certains cas catch(Throwable) afin de s'assurer que le programme peut se terminer de manière élégante - mais j'attrape toujours les exceptions spécifiques dont j'ai besoin. Cela me permet, au minimum, d'afficher un message d'erreur approprié.

La question à laquelle les gens ne répondent jamais est la suivante :

Si vous lancez RuntimeException au lieu de Exception des sous-classes, alors comment savoir ce que vous êtes censé attraper ?

Si la réponse est catch Exception alors vous traitez les erreurs du programmeur de la même manière que les exceptions du système. Cela me semble erroné.

Si vous attrapez Throwable alors vous traitez les exceptions système et les erreurs VM (et autres) de la même manière. Cela me semble erroné.

Si la réponse est que vous n'attrapez que les exceptions que vous savez être levées, comment savez-vous lesquelles ? Que se passe-t-il lorsque le programmeur X lance une nouvelle exception et oublie de l'attraper ? Cela me semble très dangereux.

Je dirais qu'un programme qui affiche une trace de la pile est mauvais. Les personnes qui n'aiment pas les exceptions vérifiées ne sont-elles pas de cet avis ?

Donc, si vous n'aimez pas les exceptions contrôlées, pouvez-vous expliquer pourquoi et répondre à la question qui n'a pas reçu de réponse ?

Je ne cherche pas à savoir quand utiliser l'un ou l'autre modèle, ce que je cherche c'est pourquoi les personnes s'étendent de RuntimeException parce qu'ils n'aiment pas s'étendre de Exception et/ou pourquoi ils attrapent une exception et relancent ensuite une RuntimeException plutôt que d'ajouter des lancers à leur méthode. Je veux comprendre les raisons pour lesquelles on n'aime pas les exceptions vérifiées.

47 votes

Je ne pense pas que ce soit complètement subjectif - c'est une fonctionnalité de la langue qui a été conçue pour avoir une utilisation spécifique, plutôt que pour que chacun puisse décider de ce à quoi elle sert pour lui-même. Et ce n'est pas spécialement argumentatif, ça répond à l'avance à des réfutations spécifiques que les gens auraient pu facilement trouver.

7 votes

Allez. Considéré comme une caractéristique de la langue, ce sujet a été et peut être abordé de manière objective.

6 votes

@cletus "répondre à votre propre question" si j'avais la réponse je n'aurais pas posé la question !

2voto

ses Points 2924

Les bonnes preuves que les exceptions vérifiées ne sont pas nécessaires sont :

  1. Un grand nombre de cadres qui font un travail pour Java. Comme Spring qui transforme les exceptions JDBC en exceptions non vérifiées et envoie des messages dans le journal.
  2. Beaucoup de langages qui sont venus après java, même au sommet de la plate-forme java - ils ne les utilisent pas.
  3. Les exceptions vérifiées, c'est une sorte de prédiction sur la façon dont le client utiliserait le code qui lève une exception. Mais le développeur qui écrit ce code ne connaît pas le système et l'activité dans lesquels le client du code travaille. Par exemple, les méthodes Interfcace qui forcent à lancer une exception vérifiée. Il y a 100 implémentations sur le système, 50 ou même 90 implémentations ne lèvent pas cette exception, mais le client doit toujours attraper cette exception s'il fait référence à cette interface. Ces 50 ou 90 implémentations ont tendance à gérer elles-mêmes ces exceptions, en les mettant dans le journal (et c'est un bon comportement pour elles). Que devons-nous faire avec cela ? Je préférerais avoir une logique de fond qui ferait tout ce travail - envoyer le message au journal. Et si, en tant que client du code, je sens que je dois gérer l'exception, je le ferai. Je peux l'oublier, c'est vrai - mais si j'utilise le TDD, toutes mes étapes sont couvertes et je sais ce que je veux.
  4. Un autre exemple, lorsque je travaille avec des E/S en Java, cela me force à vérifier toutes les exceptions, si le fichier n'existe pas, que dois-je faire avec cela ? S'il n'existe pas, le système ne passe pas à l'étape suivante. Le client de cette méthode n'obtiendrait pas le contenu attendu de ce fichier - il peut gérer l'exception d'exécution, sinon je devrais d'abord vérifier l'exception vérifiée, mettre un message dans le journal, puis lancer l'exception hors de la méthode. Non...non - je préfère le faire automatiquement avec RuntimeEception, qui le fait / s'allume automatiquement. Il n'y a aucun sens à le gérer manuellement - je serais heureux de voir un message d'erreur dans le journal (AOP peut aider à cela... quelque chose qui répare java). Si, éventuellement, je décide que le système doit montrer un message pop-up à l'utilisateur final, je le montrerai, ce n'est pas un problème.

J'étais heureux si java me fournissait un choix ce qu'il faut utiliser lorsqu'on travaille avec les librairies principales, comme I/O. Like fournit deux copies des mêmes classes - une enveloppée avec RuntimeEception. Ensuite, nous pourrons comparer ce que les gens utiliseraient . Pour l'instant, cependant, beaucoup de gens préfèrent opter pour un framework au-dessus de Java, ou un langage différent. Comme Scala, JRuby ou autre. Beaucoup croient simplement que SUN avait raison.

1voto

Mister Smith Points 8587

Bien qu'ayant lu toute la page, je ne trouve toujours pas un seul argument raisonnable contre les exceptions vérifiées. La plupart des gens parlent plutôt d'une mauvaise conception de l'API, soit au niveau de certaines classes Java, soit au niveau de leurs propres classes.

Le seul scénario où cette fonctionnalité peut être gênante est le prototiping. Cela pourrait être résolu en ajoutant un mécanisme au langage (par exemple, une annotation @supresscheckedexceptions). Mais pour la programmation ordinaire, je pense que les exceptions vérifiées sont une bonne chose.

1voto

Jacob Toronto Points 11

Nous avons vu quelques références à l'architecte en chef de C#.

Voici un autre point de vue, celui d'un spécialiste de Java, sur les cas où il faut utiliser des exceptions vérifiées. Il reconnaît la plupart des inconvénients que d'autres ont mentionnés : Exceptions effectives

0voto

finnw Points 24592

Ici L'un des arguments contre les exceptions vérifiées (de joelonsoftware.com) :

Le raisonnement est que je considère que les exceptions ne sont pas meilleures que "goto's", considérés comme nuisibles depuis les années 1960, en ce qu'ils créent un saut abrupt d'un point du code à un autre. En fait, elles sont significativement pire que les goto's :

  • Ils sont invisibles dans le code source. En regardant un bloc de code, incluant des fonctions qui peuvent ou non lever des exceptions, il n'y a aucun moyen de voir moyen de voir quelles exceptions peuvent être lancées et d'où elles proviennent. Cela signifie que que même une inspection minutieuse du code ne révèle pas les bogues potentiels.
  • Ils créent trop de points de sortie possibles pour une fonction. Pour écrire correctement vous devez vraiment penser à tous les chemins de code possibles à travers votre fonction. Chaque fois que vous appelez une fonction qui peut soulever une exception et que vous ne l'attrapez pas sur-le-champ, vous créez des possibilités de des bogues surprises causés par des fonctions qui se terminent brusquement, en laissant données dans un état incohérent, ou d'autres chemins de code auxquels vous n'avez pas pensé. auxquelles vous n'avez pas pensé.

0voto

adrian.tarau Points 2023

J'ai lu beaucoup de choses sur la gestion des exceptions, même si (la plupart du temps) je ne peux pas vraiment dire que je suis heureux ou triste de l'existence des exceptions vérifiées, voici mon point de vue : les exceptions vérifiées dans le code de bas niveau (IO, réseau, OS, etc.) et les exceptions non vérifiées dans les API de haut niveau/niveau d'application.

Même s'il n'est pas si facile de tracer une ligne entre les deux, je trouve qu'il est vraiment ennuyeux/difficile d'intégrer plusieurs API/bibliothèques sous le même toit sans envelopper tout le temps beaucoup d'exceptions vérifiées mais d'un autre côté, parfois il est utile/meilleur d'être forcé d'attraper une exception et de fournir une autre exception qui a plus de sens dans le contexte actuel.

Le projet sur lequel je travaille prend beaucoup de bibliothèques et les intègre sous la même API, API qui est complètement basée sur des exceptions non vérifiées. Ce cadre fournit une API de haut niveau qui, au début, était pleine d'exceptions vérifiées et n'avait que quelques exceptions non vérifiées (Initialization Exception, ConfigurationException, etc.) et je dois dire que ce n'était pas très bon. amical . La plupart du temps, vous deviez attraper ou relancer des exceptions que vous ne saviez pas comment traiter, ou dont vous ne vous souciiez même pas (à ne pas confondre avec le fait d'ignorer les exceptions), surtout du côté client où un simple clic pouvait lancer 10 exceptions possibles (vérifiées).

La version actuelle (la troisième) n'utilise que les exceptions non vérifiées et possède un gestionnaire d'exceptions global qui est chargé de gérer tout ce qui n'a pas été attrapé. L'API fournit un moyen d'enregistrer les gestionnaires d'exception, qui décideront si une exception est considérée comme une erreur (la plupart du temps, c'est le cas), ce qui signifie qu'elle doit être consignée et notifiée à quelqu'un, ou si elle peut signifier autre chose - comme cette exception, AbortException, qui signifie qu'il faut interrompre le fil d'exécution actuel et ne pas consigner d'erreur parce qu'on le souhaite. Bien sûr, pour que tout cela fonctionne, les threads personnalisés doivent gérer la méthode run() avec un try {...} catch(all).

public void run() {

try {
     ... do something ...
} catch (Throwable throwable) {
     ApplicationContext.getExceptionService().handleException("Handle this exception", throwable);
}

}

Cela n'est pas nécessaire si vous utilisez le WorkerService pour planifier les tâches (Runnable, Callable, Worker), qui s'occupe de tout pour vous.

Bien sûr, ce n'est que mon avis, et il se peut qu'il ne soit pas le bon, mais il me semble que c'est une bonne approche. Je verrai après la sortie du projet si ce que je pense être bon pour moi, l'est aussi pour les autres... :)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X