Est-ce une bonne pratique d'attraper une exception vérifiée et de lancer une RuntimeException?

70

J'ai lu le code d'un collègue et j'ai constaté qu'il attrapait souvent diverses exceptions et lançait toujours une "RuntimeException" à la place. J'ai toujours pensé que c'était une très mauvaise pratique. Ai-je tort?

RoflcoptrException
la source
17
"Le prix des exceptions cochées est une violation de principe Open / Closed. Si vous lâchez une exception cochée d'une méthode dans votre code et que le catch est supérieur à trois niveaux, vous devez déclarer cette exception dans la signature de chaque méthode entre vous et le catch. Cela signifie qu’une modification à un niveau bas du logiciel peut imposer des modifications de signature à de nombreux niveaux supérieurs. " —Robert C. Martin, «Clean Code», page 107
Songo
6
Il est intéressant de noter que Jim Waldo s'oppose aux exceptions non contrôlées dans "Java: les bonnes pièces" shop.oreilly.com/product/9780596803742.do disant que les programmeurs adultes ne devraient lancer que des exceptions vérifiées. Nous l'avons lu dans notre JUG il y a seulement 6 ans quand il est sorti et cela semblait être un bon conseil! Maintenant, avec la programmation fonctionnelle, les exceptions vérifiées sont complètement difficiles à manier. Des langues comme Scala et Kotlin ne les ont même pas. J'ai aussi commencé à intégrer des exceptions vérifiées non vérifiées.
GlenPeterson
@GlenPeterson vous avez également le conseil en FP d'éviter complètement les exécutions et d'utiliser des types de somme à la place
jk.
Il y a aussi le cas évident des interfaces fonctionnelles: les interfaces fonctionnelles intégrées (c. Function-à- d . Predicate, Etc. ) ne comportent pas de clause de projection paramétrée. Cela signifie que vous devez capturer, encapsuler et redistribuer les exceptions vérifiées dans la boucle interne de toutes les méthodes stream (). Cela en soi fait pencher la balance pour moi pour savoir si les exceptions vérifiées sont une mauvaise idée.
Joel Cornett
Il n'y a rien de mal à créer des sous-classes personnalisées de RuntimeException afin de communiquer le sens via votre exception.
Joel Cornett

Réponses:

55

Je ne connais pas suffisamment le contexte pour savoir si votre collègue fait quelque chose de mal ou pas, alors je vais en discuter de manière générale.

Je ne pense pas qu'il soit toujours incorrect de transformer les exceptions vérifiées en une sorte d'exception d'exécution . Les exceptions vérifiées sont souvent mal utilisées et abusées par les développeurs.

Il est très facile d'utiliser des exceptions vérifiées lorsqu'elles ne sont pas censées être utilisées (conditions irrécupérables, voire contrôle du flux). Surtout si une exception vérifiée est utilisée pour des conditions dans lesquelles l'appelant ne peut pas récupérer, je pense qu'il est justifié de transformer cette exception en une exception d'exécution avec un message / état utile. Malheureusement, dans de nombreux cas, lorsque l’on est confronté à une condition irrécupérable, on a tendance à avoir un bloc vide, ce qui est l’une des pires choses que vous puissiez faire. Déboguer un tel problème est l’un des plus gros problèmes qu’un développeur puisse rencontrer.

Donc, si vous pensez que vous avez affaire à une condition récupérable, vous devez la gérer en conséquence et l'exception ne doit pas être transformée en une exception d'exécution. Si une exception vérifiée est utilisée pour des conditions irrécupérables, il est justifié de la transformer en une exception d'exécution .

c_maker
la source
17
Dans la plupart des applications réelles, il existe très peu de conditions irrécupérables. Il y a presque toujours un niveau où vous pouvez et devriez dire "OK, cette action a échoué, nous affichons / consignons donc un beau message d'erreur et poursuivons avec / attendons le suivant".
Michael Borgwardt
6
C'est vrai, @MichaelBorgwardt, mais le lieu pour ce type de traitement est souvent au plus haut niveau de l'application. Ainsi, chaque fois que je vois des développeurs "manipuler" des exceptions à des niveaux inférieurs, il est généralement facile de supprimer leur traitement et de percoler l'exception. vers le haut. Par exemple, une infrastructure Web telle que JSF intercepte les exceptions au plus haut niveau, imprime les messages du journal et poursuit le traitement des autres demandes (sans préciser que le traitement par défaut est approprié, il s'agit simplement d'un exemple).
DavidS
40

Cela peut être bon . Lisez s'il vous plaît:

http://onjava.com/pub/a/onjava/2003/11/19/exceptions.html

La plupart du temps, le code client ne peut rien faire à propos de SQLExceptions. N'hésitez pas à les convertir en exceptions non contrôlées. Considérons le code suivant:

public void dataAccessCode(){
  try{
      ..some code that throws SQLException
  }catch(SQLException ex){
      ex.printStacktrace();
  }
} 

Ce bloc catch supprime simplement l'exception et ne fait rien. La justification est que mon client ne peut rien faire contre une exception SQLException. Que diriez-vous de le traiter de la manière suivante?

public void dataAccessCode(){
   try{
       ..some code that throws SQLException
   }catch(SQLException ex){
       throw new RuntimeException(ex);
   }
} 

Cela convertit SQLException en RuntimeException. Si une exception SQLException se produit, la clause catch lève une nouvelle exception RuntimeException. Le thread d'exécution est suspendu et l'exception est signalée. Cependant, je ne corrompt pas ma couche d'objet métier avec une gestion inutile des exceptions, d'autant plus qu'elle ne peut rien faire avec une exception SQLException. Si ma capture a besoin de la cause de l'exception racine, je peux utiliser la méthode getCause () disponible dans toutes les classes d'exceptions à partir de JDK1.4.

Lancer des exceptions vérifiées et ne pas être capable de s'en remettre ne sert à rien.

Certaines personnes pensent même que les exceptions vérifiées ne devraient pas être utilisées du tout. Voir http://www.ibm.com/developerworks/java/library/j-jtp05254/index.html.

Récemment, plusieurs experts réputés, dont Bruce Eckel et Rod Johnson, ont publiquement déclaré que, s’ils étaient initialement totalement en accord avec la position orthodoxe sur les exceptions vérifiées, ils ont conclu que le recours exclusif à des exceptions vérifiées n’était pas une aussi bonne idée. apparu au début et que les exceptions vérifiées sont devenues une source importante de problèmes pour de nombreux grands projets. Eckel adopte un point de vue plus extrême, suggérant que toutes les exceptions devraient être supprimées; Le point de vue de Johnson est plus conservateur, mais suggère néanmoins que la préférence orthodoxe pour les exceptions vérifiées est excessive. (Il est intéressant de noter que les architectes de C #, qui possédaient presque certainement beaucoup d’expérience dans l’utilisation de la technologie Java, ont choisi d’omettre les exceptions vérifiées de la conception du langage, en faisant toutes les exceptions non vérifiées.

Également du même lien:

La décision d'utiliser des exceptions non contrôlées est complexe et il est clair qu'il n'y a pas de réponse évidente. Le conseil de Sun est de les utiliser pour rien, l'approche C # (avec laquelle Eckel et d'autres sont d'accord) est de les utiliser pour tout. D'autres disent: "il y a un juste milieu".

mrmuggles
la source
13

Non, tu n'as pas tort. Sa pratique est extrêmement erronée. Vous devriez lancer une exception qui capture le problème qui l’a provoquée. RunTimeException est large et va trop loin. Il devrait s'agir d'une exception NullPointerException, ArgumentException, etc. Ce qui décrit avec précision ce qui s'est mal passé. Cela permet de différencier les problèmes que vous devez gérer et de laisser le programme survivre par rapport aux erreurs qui devraient constituer un scénario "Ne réussissez pas". Ce qu’il fait n’est que légèrement meilleur que "On Error Resume Next" sauf s’il manque quelque chose dans les informations fournies dans la question.

Plate-forme
la source
1
Merci pour l'allusion. Et s'il lève une exception personnalisée implémentée qui hérite directement de RuntimeException?
Exception RoflcoptrEx
27
@Gary Buyn: beaucoup de gens pensent que les exceptions vérifiées sont une expérience de conception de langage qui a échoué et que ce sont elles qui devraient être utilisées avec parcimonie, et non par habitude.
Michael Borgwardt
7
@Gary Buyn: Voici un article qui résume assez bien le débat: ibm.com/developerworks/java/library/j-jtp05254/index.html Notez également que plus de 15 ans après l'introduction de cette fonctionnalité par Java, aucun autre langage ne l'a adoptée. et C ++ a déconseillé d'utiliser une fonctionnalité similaire.
Michael Borgwardt
7
@c_maker: En fait, Bloch promeut principalement la vue orthodoxe et votre commentaire semble porter principalement sur l'utilisation d'un plus grand nombre d'exceptions, point final. Mon point de vue est que la seule raison valable pour utiliser une exception vérifiée est une condition que vous attendez de tous les appelants à gérer immédiatement.
Michael Borgwardt
14
Les exceptions vérifiées inutiles lancées violent l’encapsulation. Que faites-vous si une méthode simple telle que 'getAccounts ()' vous renvoie une 'SQLException', une 'NullPointerException' ou une 'FileNotFoundException'? Pouvez-vous vous en occuper? Vous aurez probablement juste "attraper (Exception e) {}". En outre, ces exceptions - sa mise en œuvre spécifique! Cela ne devrait pas faire partie du contrat! Tout ce que vous devez savoir, c'est qu'il y a une erreur . Et si l’implémentation change? Tout à coup, tout doit changer, car la méthode ne lance plus 'SQLException', mais un 'ParseXMLException' à la place!
KL
8

Ça dépend.

Cette pratique peut même être sage . Il existe de nombreuses situations (par exemple dans le développement Web), dans lesquelles, si une exception se produit, vous ne pouvez rien faire (car vous ne pouvez pas par exemple réparer une base de données incohérente à partir de votre code :-), seul un développeur peut le faire). Dans ces situations, il est sage d'encapsuler l'exception levée dans une exception d'exécution et de la renvoyer. Ensuite, vous pouvez intercepter toutes ces exceptions dans une couche de traitement des exceptions, consigner l’erreur et afficher à l’utilisateur un code d'erreur + un message bien localisé.

D'autre part , si l'exception n'est pas à l'exécution (est cochée), le développeur de l'API indique que cette exception est résolvable et doit être réparée. Si c'est possible, vous devriez absolument le faire.

L’autre solution pourrait être de rétablir cette exception vérifiée dans le calque appelant, mais si vous ne parvenez pas à la résoudre, où l’exception s’est produite, vous ne pourrez probablement pas la résoudre ici également ...

malejpavouk
la source
Vous espérez que le développeur de l'API savait ce qu'il faisait et utilisait bien les exceptions vérifiées. J'ai commencé à voir des API qui favorisent le lancement d'exceptions d'exécution tout en les documentant afin que le client ait la possibilité de les intercepter s'il le souhaite.
c_maker
Une méthode qui lève une exception ne peut généralement pas savoir si un appelant peut la récupérer. D'autre part, je suggérerais qu'une méthode ne laisse qu'une exception vérifiée levée par une méthode interne pour s'échapper si vous savez pourquoi la méthode interne a levé l'exception, et la raison est compatible avec l'API de la méthode externe. Si une méthode interne lève une exception vérifiée de manière inattendue, la laisser bouillonner comme une exception vérifiée peut laisser l'appelant mal informé de ce qui s'est passé.
Supercat
2
Merci de mentionner le exception handling layer- par exemple dans une application Web, un filtre.
Jake Toronto
5

J'aimerais avoir des commentaires à ce sujet, mais je trouve qu'il y a des moments où ce n'est pas nécessairement une mauvaise pratique. (Ou terriblement mauvais). Mais peut-être que je me trompe.

Souvent, une API que vous utilisez générera une exception que vous ne pouvez pas imaginer être réellement lancée dans votre cas d'utilisation spécifique. Dans ce cas, il semble parfaitement correct de lancer une exception RuntimeException avec l’exception interceptée comme cause. Si cette exception est levée, cela sera probablement la cause d'une erreur de programmation et ne se situe pas entre les limites d'une spécification correcte.

En supposant que l'exception RuntimeException ne soit pas interceptée et ignorée plus tard, ce n'est pas proche d'un OnErrorResumeNext.

OnErrorResumeNext se produirait quand quelqu'un attraperait une exception et l'ignorerait simplement ou l'imprimerait simplement. C'est une pratique terriblement mauvaise dans presque tous les cas.

utilisateur606723
la source
Cela pourrait être le cas vers le haut de l'arbre des appels, où la seule chose que vous pouvez faire est d'essayer de récupérer avec élégance et de savoir que l'erreur spécifique ne vous aidera pas vraiment. Dans ce cas, vous devrez peut-être enregistrer l'erreur et passer à autre chose (traiter l'enregistrement suivant, informer l'utilisateur qu'une erreur s'est produite, etc.). Sinon, non. Vous devez toujours gérer les exceptions aussi près que possible de l'erreur, et non les envelopper comme un éléphant blanc pour le prochain gestionnaire.
Michael K
@MichaelK Le problème est "aussi proche de l'erreur qu'il est pratique" dans la pratique signifie souvent "à travers plusieurs couches intermédiaires qui sont hors de votre contrôle direct". Par exemple, si ma classe doit implémenter une certaine interface, mes mains sont liées. Cela peut arriver arbitrairement au plus profond de l’arbre d’appel. Même lorsque les interfaces sont sous mon contrôle, l’ajout de déclarations de projection peut entraîner une fuite de l’abstraction s’il n’ya qu’un ensemble limité d’implémentations concrètes pouvant être projetées. Faire en sorte que chaque client paie le coût de la mise en œuvre de quelques détails n’est pas un bon compromis de conception pour l’OMI.
Tim Seguine
4

TL; DR

Prémisse

  • Les exceptions d'exécution doivent être levées lorsque l'erreur est irrécupérable: lorsque l'erreur est dans le code et ne dépend pas de l'état externe (la récupération corrigerait donc le code).
  • Les exceptions vérifiées doivent être levées lorsque le code est correct, mais que l'état externe n'est pas conforme aux attentes: absence de connectivité réseau, fichier introuvable ou corrompu, etc.

Conclusion

Nous pouvons réexaminer une exception vérifiée en tant qu'exception d'exécution si le code de propagation ou d'interface suppose que l'implémentation sous-jacente dépend d'un état externe, alors que ce n'est clairement pas le cas.


Cette section aborde le sujet du moment où l’une des exceptions doit être levée. Vous pouvez passer à la barre horizontale suivante si vous souhaitez simplement lire une explication plus détaillée de la conclusion.

Quand est-il approprié de lancer une exception d'exécution? Vous lève une exception d'exécution lorsqu'il est clair que le code est incorrect et que la récupération est appropriée en modifiant le code.

Par exemple, il est approprié de lancer une exception d'exécution pour les éléments suivants:

float nan = 1/0;

Cela lève une exception d'exécution division par zéro. Ceci est approprié car le code est défectueux.

Ou par exemple, voici une partie du HashMapconstructeur de 's:

public HashMap(int initialCapacity, float loadFactor) {
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity);
    if (initialCapacity > MAXIMUM_CAPACITY)
        initialCapacity = MAXIMUM_CAPACITY;
    if (loadFactor <= 0 || Float.isNaN(loadFactor))
        throw new IllegalArgumentException("Illegal load factor: " +
                loadFactor);
    // more irrelevant code...
}

Afin de fixer la capacité initiale ou le facteur de charge, il convient que vous modifiiez le code pour vous assurer que les valeurs correctes sont bien transmises. Cela ne dépend pas de la disponibilité d’un serveur distant, de l’état actuel du disque, un fichier ou un autre programme. Ce constructeur appelé avec des arguments non valides dépend de l'exactitude du code appelant, qu'il s'agisse d'un calcul erroné ayant conduit aux paramètres non valides ou d'un flux inapproprié manquant une erreur.

Quand est-il approprié de lancer une exception cochée? Vous lève une exception cochée lorsque le problème est récupérable sans changer le code. Ou, pour le dire autrement, vous lâchez une exception vérifiée lorsque l'erreur est liée à l'état alors que le code est correct.

Maintenant, le mot "récupérer" peut être délicat ici. Cela peut signifier que vous trouvez un autre moyen d'atteindre l'objectif: par exemple, si le serveur ne répond pas, vous devriez essayer le serveur suivant. Si ce type de récupération est possible pour votre cas, c'est bien, mais ce n'est pas la seule chose que signifie récupération - la récupération peut simplement afficher une boîte de dialogue d'erreur indiquant à l'utilisateur ce qui s'est passé, ou bien s'il s'agit d'une application serveur, alors envoyer un courrier électronique à l'administrateur, ou même simplement consigner l'erreur de manière appropriée et concise.

Prenons l'exemple cité dans la réponse de mrmuggles:

public void dataAccessCode(){
   try{
       ..some code that throws SQLException
   }catch(SQLException ex){
       throw new RuntimeException(ex);
   }
}

Ce n'est pas la bonne façon de gérer l'exception vérifiée. La simple incapacité à gérer l'exception dans le champ d'application de cette méthode ne signifie pas que l'application doit être plantée. Au lieu de cela, il convient de le propager à une portée plus élevée comme ceci:

public Data dataAccessCode() throws SQLException {
    // some code that communicates with the database
}

Ce qui permet la possibilité de récupération par l'appelant:

public void loadDataAndShowUi() {
    try {
        Data data = dataAccessCode();
        showUiForData(data);
    } catch(SQLException e) {
        // Recover by showing an error alert dialog
        showCantLoadDataErrorDialog();
    }
}

Les exceptions cochées sont un outil d'analyse statique, elles indiquent clairement à un programmeur ce qui pourrait mal tourner lors d'un appel donné sans lui demander d'apprendre la mise en oeuvre ou de passer par un processus d'essais et d'erreurs. Cela permet de s'assurer facilement qu'aucune partie du flux d'erreur ne sera ignorée. Le fait de renvoyer une exception vérifiée en tant qu'exception d'exécution va à l'encontre de cette fonctionnalité d'analyse statique qui économise du travail.

Il est également intéressant de mentionner que la couche appelante a un meilleur contexte du plus grand schéma des choses, comme cela a été démontré ci-dessus. Il pourrait y avoir plusieurs causes à dataAccessCodel'appel, la raison spécifique de l'appel n'étant visible que par l'appelant - il est donc en mesure de prendre une meilleure décision lors de la récupération correcte en cas d'échec.

Maintenant que cette distinction est claire, nous pouvons en déduire le moment opportun pour réexaminer une exception vérifiée en tant qu’exception d’exécution.


Compte tenu de ce qui précède, à quel moment convient-il de rétablir une exception vérifiée en tant qu'exception RuntimeException? Lorsque le code que vous utilisez suppose une dépendance à un état externe, mais vous pouvez clairement affirmer qu'il ne dépend pas d'un état externe.

Considérer ce qui suit:

StringReader sr = new StringReader("{\"test\":\"test\"}");
try {
    doesSomethingWithReader(sr); // calls #read, so propagates IOException
} catch (IOException e) {
    throw new IllegalStateException(e);
}

Dans cet exemple, le code se propage IOExceptioncar l'API de Readerest conçue pour accéder à un état externe. Cependant, nous savons que la StringReadermise en œuvre n'accède pas à un état externe. À ce niveau, où nous pouvons certainement affirmer que les parties impliquées dans l’appel n’ont pas accès à IO ou à tout autre état externe, nous pouvons sans risque rediffuser l’exception comme une exception d’exécution, sans surprendre des collègues qui ne sont pas au courant de notre implémentation (et sont éventuellement en supposant que le code d'accès IO jettera un IOException).


La raison pour garder strictement vérifiées les exceptions dépendantes de l'état externe est qu'elles ne sont pas déterministes (contrairement aux exceptions dépendantes de la logique, qui seront reproduites de manière prévisible pour une version du code). Par exemple, si vous essayez de diviser par 0, vous obtiendrez toujours une exception. Si vous ne divisez pas par 0, vous ne produirez jamais d'exception et vous ne devrez pas gérer ce cas d'exception, car cela n'arrivera jamais. Dans le cas de l'accès à un fichier, toutefois, réussir une fois ne signifie pas que vous réussirez la prochaine fois: l'utilisateur peut avoir modifié les autorisations, un autre processus peut l'avoir supprimé ou modifié. Donc, vous devez toujours gérer ce cas exceptionnel, ou vous avez probablement un bogue.

Ben Barkay
la source
2

Pour les applications autonomes. Lorsque vous savez que votre application ne peut pas gérer l'exception, vous pouvez, au lieu de lancer l'exception RuntimeException cochée, lancer Error, laisser l'application planter, espérer des rapports de bogues et réparer votre application. (Voir la réponse de mrmuggles pour une discussion plus approfondie sur les avantages et les inconvénients de coché ou non coché.)

Kasper van den Berg
la source
2

C'est une pratique courante dans de nombreux cadres. Eg Hibernatefait exactement cela. L'idée est que les API ne doivent pas être intrusives pour le côté client et Exceptionsont intrusives car vous devez écrire explicitement du code pour les manipuler à l'endroit où vous appelez l'API. Mais cet endroit pourrait ne pas être le bon endroit pour gérer l'exception en premier lieu.
En fait, pour être honnête, il s’agit d’un sujet «brûlant» et de nombreux différends. Je ne prendrai donc pas parti pour cela, mais je dirai que ce que votre ami fait / propose n’est pas inhabituel ou inhabituel.

utilisateur10326
la source
1

Toute "chose vérifiée" est une mauvaise idée.

La programmation structurée permet uniquement aux informations d'être transmises (ou, en java, aux méthodes) lorsqu'elles sont "proches". Plus précisément, les informations ne peuvent circuler entre les fonctions que de deux manières:

  1. D'appelant à appelé, en passant d'argument.

  2. De l'appelé à l'appelant, en tant que valeurs de retour.

C'est une chose fondamentalement bonne. C'est ce qui vous permet de raisonner localement sur votre code: si vous avez besoin de comprendre ou de modifier une partie de votre programme, il vous suffit de regarder cette partie et les autres "proches".

Cependant, dans certaines circonstances, il est nécessaire d’envoyer des informations à une fonction "distante", sans que quiconque "sache" au milieu. C’est précisément le moment où des exceptions doivent être utilisées. Une exception est un message secret envoyé par un leveur (toute partie de votre code pouvant contenir une throwinstruction) à un gestionnaire (toute partie de votre code pouvant contenir un catchbloc compatible avec l'exception qui était thrown).

Les exceptions vérifiées détruisent le secret du mécanisme et, avec lui, la raison même de son existence. Si une fonction peut se permettre de laisser son appelant "connaître" une information, envoyez-la directement en tant que partie de la valeur de retour.

pyon
la source
Il peut être intéressant de mentionner que ce type de problème peut réellement causer des ravages dans les cas où une méthode exécute une fonction fournie par son appelant. Dans bien des cas, l’auteur de la méthode qui reçoit la fonction n’a aucune raison de savoir ni ce que l’appelant attend de la part de l’appel, ni quelles exceptions l’appelant peut s’attendre. Si le code qui reçoit la méthode ne s'attend pas à ce qu'il lève une exception vérifiée, la méthode fournie devra peut-être encapsuler toutes les exceptions vérifiées qu'elle jetterait dans des exceptions non contrôlées que son fournisseur pourrait alors intercepter.
Supercat
0

Cela peut dépendre de cas à cas. Dans certains scénarios, il est sage de faire ce que fait votre ami, par exemple lorsque vous exposez une API pour certains clients et que vous souhaitez que le client soit moins au courant des détails de la mise en œuvre, sachant que certaines exceptions peuvent être spécifiques à la mise en œuvre. détails de mise en œuvre et non exposés au client.

En gardant les exceptions vérifiées à l'écart, vous pouvez exposer des API permettant au client d'écrire du code plus propre, car le client lui-même pourrait pré-valider les conditions exceptionnelles.

Par exemple, Integer.parseInt (String) prend une chaîne, renvoie son équivalent entier et lève une exception NumberFormatException si la chaîne n'est pas numérique. Imaginons maintenant qu'une soumission de formulaire avec un champ agesoit convertie via cette méthode, mais que le client se soit déjà assuré de la validation. Il est donc inutile de forcer la vérification de l'exception.

utilisateur94369
la source
0

Il y a vraiment quelques questions ici

  1. Devez-vous transformer les exceptions vérifiées en non vérifiées?

La règle générale est que les exceptions que l'appelant doit intercepter et récupérer doivent être vérifiées. Les autres exceptions (celles dans lesquelles le seul résultat raisonnable est d'abandonner toute l'opération ou si vous les considérez suffisamment improbables pour que leur gestion spécifique ne vaille pas la peine) devraient être décochées.

Parfois, votre jugement sur le point de savoir si une exception mérite une capture et la récupération est différent de celui de l'API avec laquelle vous travaillez. Parfois, le contexte compte, une exception qui vaut la peine d’être traitée dans une situation donnée peut ne pas valoir la peine d’être traitée dans une autre. Parfois, votre main est forcée par les interfaces existantes. Donc oui, il y a des raisons légitimes de transformer une exception vérifiée en une exception non vérifiée (ou en un type différent d'exception vérifiée)

  1. Si vous voulez transformer une exception non contrôlée en une exception contrôlée, comment procéder?

Tout d’abord et surtout, assurez-vous d’utiliser le système de chaînage d’exceptions. Ainsi, les informations de l'exception d'origine ne sont pas perdues et peuvent être utilisées pour le débogage.

Deuxièmement, vous devez choisir le type d’exception à utiliser. L'utilisation d'une exception d'exécution simple complique la tâche de l'appelant pour déterminer ce qui s'est mal passé, mais si l'appelant tente de déterminer ce qui s'est mal passé, cela peut indiquer que vous n'auriez pas dû modifier l'exception pour la décocher.

Peter Green
la source
0

Dans une question booléenne, il est difficile de répondre différemment après deux réponses controversées, mais je voudrais vous donner une perspective qui, même mentionnée à quelques endroits, n’a pas été suffisamment soulignée pour l’importance qu’elle revêt.

Au fil des années, j’ai constaté qu’il y avait toujours de la confusion chez un individu au sujet d’un problème trivial, mais il lui manquait une compréhension de certains des principes fondamentaux.

Superposition. Une application logicielle (du moins supposée être) est une pile de couches superposées. Une des attentes importantes pour une bonne superposition est que les couches inférieures fournissent des fonctionnalités pour potentiellement plusieurs composants de la couche supérieure.

Supposons que votre application comporte les couches suivantes: NET, TCP, HTTP, REST, MODÈLE DE DONNÉES, BUSINESS.

Si votre couche métier souhaite exécuter un appel en attente ... attendez une seconde. Pourquoi j'ai dit ça? Pourquoi n'ai-je pas dit requête HTTP ou transaction TCP ni envoyé de paquet réseau? Parce que ceux-ci ne sont pas pertinents pour ma couche métier. Je ne vais pas les gérer, je ne vais pas regarder dans les détails d'eux. Je suis parfaitement d'accord s'ils sont au cœur des exceptions que j'ai comme cause et je ne veux pas savoir qu'elles existent même.

De plus, c’est mauvais si je connais les détails, car si demain je voudrais changer les protocoles de transport soulignés qui traitent de détails spécifiques au protocole TCP, mon abstraction REST n’a pas fait du bon travail pour s’abstenir. la mise en œuvre spécifique.

Lors du passage d'une exception d'une couche à l'autre, il est important de revenir sur chaque aspect de celle-ci et de déterminer le sens que cela donnera à l'abstraction fournie par la couche actuelle. Cela pourrait être de remplacer l'exception par une autre, cela pourrait combiner plusieurs exceptions. Cela pourrait également les faire passer de coché à non coché ou vice versa.

Bien sûr, les lieux réels que vous avez mentionnés ont-ils du sens, est-ce une histoire différente, mais en général - oui, cela pourrait être une bonne chose à faire.

gsf
la source
-2

À mon avis,

Au niveau de la structure, nous devrions être des exceptions d’exécution, afin de réduire davantage le nombre de tentatives d’attrape effectuées par l’invocateur au même endroit.

Au niveau de l'application, nous capturons rarement les exceptions d'exécution et je pense que cette pratique était mauvaise.

Mark xie
la source
1
Et que ferez-vous de ces exceptions au niveau du cadre?
Matthieu
S'il existe une couche d'interface utilisateur dans la structure capable de gérer les exceptions, l'interface utilisateur affichera un message d'erreur indiquant que quelque chose s'est mal passé. Dans le cas d'une application javascript d'une page, l'application pourrait présenter un message d'erreur. Certes, la couche d'interface utilisateur ne doit gérer l'erreur que si une couche plus profonde ne peut vraiment pas récupérer de l'erreur.
Jake Toronto