90 votes

Les blocs Try/Catch imbriqués sont-ils une mauvaise idée ?

Imaginons que nous avons une structure comme celle-ci :

Essayer
  ' Code try externe, qui peut échouer avec des conditions plus génériques, 
  ' que je connais moins et que je pourrais ne pas être en mesure de gérer

  Essayer
    ' Code try interne, qui peut échouer avec des conditions plus spécifiques,
    ' que je connais probablement mieux, et que je suis susceptible de gérer de manière appropriée
  Attraper innerEx comme Exception
    ' Gérer l'exception interne
  Fin Essayer

Attraper outerEx comme Exception
  ' Gérer l'exception externe
Fin Essayer

J'ai entendu dire que l'imbrication des blocs Essayer de cette manière est découragée, mais je n'ai pas pu trouver de raisons spécifiques.

Ce code est-il mauvais ? Si oui, pourquoi ?

2 votes

Je ne suis pas sûr de la précision de l'extrait. Mais il n'y a pas grand-chose que vous sachiez vraiment lorsque vous attrapez une Exception. Cela peut être n'importe quoi. Considérez l'utilisation de la clause When que prend en charge VB.NET.

89voto

Basic Points 12796

Il y a certaines circonstances où c'est une bonne idée, par exemple un try / catch pour toute la méthode et un autre à l'intérieur d'une boucle car vous voulez gérer l'exception et continuer le traitement du reste d'une collection.

Vraiment, la seule raison de le faire est si vous voulez sauter la partie qui a généré une erreur et continuer, au lieu de dérouler la pile et perdre le contexte. Ouvrir plusieurs fichiers dans un éditeur en est un exemple.

Cela dit, les exceptions devraient (comme leur nom l'indique) être exceptionnelles. Un programme devrait les gérer mais essayer de les éviter dans le flux d'exécution normal. Elles sont coûteuses en termes de calcul dans la plupart des langages (Python étant une exception notable).

Une autre technique qui peut être utile est de capturer des types spécifiques d'exceptions...

Try
    'Some code to read from a file

Catch ex as IOException
    'Gérer les problèmes d'accès au fichier (éventuellement en silence en fonction de l'utilisation)
Catch ex as Exception
    ' Gérer toutes les autres exceptions.
    ' Si vous avez un gestionnaire plus haut, omettez simplement ce Catch et laissez l'exception se propager
    Throw
End Try

Nous utilisons également des try / catch imbriqués dans nos routines de gestion des erreurs...

    Try
        Dim Message = String.Format("...", )
        Try
            'Log to database
        Catch ex As Exception
            'Ne rien faire
        End Try

        Try
            'Log to file
        Catch ex As Exception
            'Ne rien faire
        End Try
    Catch ex As Exception
        'Abandonner et rentrer chez soi
    End Try

7 votes

Se connecter dans un fil d'arrière-plan est un endroit où j'utiliserai un bloc try/catch interne. Je ne veux pas que la méthode se termine car elle ne pourrait pas documenter ce qu'elle faisait.

0 votes

@Gooch vrai, je fais aussi ça, je vais l'ajouter à ma réponse.

41voto

Dan Tao Points 60518

En fait, je ne pense pas qu'il y ait quelque chose d'intrinsèquement faux à propos des blocs Try/Catch imbriqués, sauf qu'ils peuvent être difficiles à naviguer et sont probablement un signe que vous pourriez effectuer un certain refactoring (par exemple, déplacer le bloc Try/Catch interne dans sa propre méthode).

Mais je tiens à aborder ce commentaire :

' Code de test externe, qui peut échouer avec des conditions plus génériques,
' que je connais moins et que je pourrais ne pas être capable de gérer

Si vous ne savez pas comment gérer les exceptions dans une situation particulière, croyez-moi : ne les attrapez pas. Mieux vaut laisser votre application planter (je veux dire, vous savez, le journaliser; ne l'ignorez tout simplement pas) que d'attraper quelque chose dont vous ne savez pas comment récupérer et ensuite laisser votre application continuer joyeusement dans un état corrompu. Le comportement sera imprévisible au mieux à partir de ce moment.

0 votes

Cela est vrai. Au moment de capturer l'exception externe, je ne voudrais pas continuer. Je pensais plutôt à être capable d'arrêter/redémarrer l'application de manière élégante, et de ne pas choquer l'utilisateur avec un "plantage brutal".

11 votes

@Goro: Dans ce cas, je recommanderais un mécanisme de gestion des exceptions à l'échelle de l'application (par exemple, si vous utilisez WinForms, gérez l'événement Application.UnhandledException) plutôt que des blocs Try/Catch par méthode.

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