J'ai trouvé un morceau de code comme celui-ci dans l'un de nos projets:
SomeClass QueryServer(string args)
{
try
{
return SomeClass.Parse(_server.Query(args));
}
catch (Exception)
{
return null;
}
}
Autant que je sache, supprimer de telles erreurs est une mauvaise pratique, car cela détruit des informations utiles provenant de l'exception du serveur d'origine et fait en sorte que le code continue à exister alors qu'il devrait se terminer.
Quand est-il approprié de supprimer complètement toutes les erreurs de ce type?
programming-practices
language-agnostic
error-handling
utilisateur626528
la source
la source
Réponses:
Imaginez du code avec des milliers de fichiers en utilisant plusieurs bibliothèques. Imaginez que tous soient codés comme ceci.
Imaginons, par exemple, qu'une mise à jour de votre serveur provoque la disparition d'un fichier de configuration. et maintenant tout ce que vous avez, c'est une trace de pile, c'est une exception de pointeur nul lorsque vous essayez d'utiliser cette classe: comment voulez-vous résoudre ce problème? Cela peut prendre des heures. Au moins, la journalisation de la trace de pile brute du fichier non trouvé [chemin du fichier] peut vous permettre de résoudre momentanément.
Ou pire encore: une défaillance de l'une des bibliothèques que vous utilisez après une mise à jour qui fait planter votre code plus tard. Comment pouvez-vous suivre ce retour à la bibliothèque?
Même sans gestion d'erreur robuste, il suffit de faire
ou
peut vous faire gagner des heures.
Mais dans certains cas, vous pouvez vraiment vouloir ignorer l'exception et renvoyer null comme ceci (ou ne rien faire). Surtout si vous intégrez du code hérité mal conçu et que cette exception est attendue comme un cas normal.
En fait, vous devriez simplement vous demander si vous ignorez vraiment l'exception ou la "gestion appropriée" de vos besoins. Si renvoyer la valeur null "traite correctement" votre exception dans ce cas, faites-le. Et ajoutez un commentaire expliquant pourquoi c’est la bonne chose à faire.
Les meilleures pratiques sont les choses à suivre dans la plupart des cas, peut-être 80%, peut-être 99%, mais vous trouverez toujours un cas où elles ne s'appliqueront pas. Dans ce cas, laissez un commentaire sur la raison pour laquelle vous ne suivez pas la pratique pour les autres (ou même pour vous-même) qui liront votre code des mois plus tard.
la source
Il existe des cas où ce modèle est utile - mais ils sont généralement utilisés lorsque l'exception générée n'aurait jamais dû l'être (c'est-à-dire lorsque des exceptions sont utilisées pour un comportement normal).
Par exemple, imaginons qu'une classe ouvre un fichier et le stocke dans l'objet renvoyé. Si le fichier n'existe pas, vous pouvez considérer que ce n'est pas un cas d'erreur, vous renvoyez la valeur null et laissez l'utilisateur créer un nouveau fichier. La méthode file-open peut générer une exception ici pour indiquer qu'aucun fichier n'est présent. Il peut donc être correct de l'attraper en silence.
Cependant, il est rare que vous souhaitiez le faire, et si le code est encombré d'un tel motif, vous voudrez le traiter maintenant. À tout le moins, je m'attendrais à ce qu'une personne aussi silencieuse rédige une ligne de journal indiquant que c'est ce qui s'est passé (vous avez tracé, à droite) et un commentaire pour expliquer ce comportement.
la source
null
si c'est la meilleure langue que votre langue choisie peut offrir.Cela dépend du contexte à 100%. Si l'appelant d'une telle fonction a l'obligation d'afficher ou de consigner les erreurs quelque part, c'est évidemment un non-sens. Si l'appelant a ignoré toutes les erreurs ou tous les messages d'exception, il serait peu judicieux de renvoyer l'exception ou son message. Lorsque le code doit obligatoirement se terminer sans afficher de raison, un appel est alors envoyé.
serait probablement suffisant. Vous devez vous demander si cela rendra difficile la recherche de la cause de l'erreur par l'utilisateur. Si tel est le cas, il s'agit d'une forme incorrecte de traitement des erreurs. Cependant, si le code d'appel ressemble à ceci
alors vous devriez avoir un argument avec le développeur lors de la révision du code. Si quelqu'un implémente une telle forme de traitement sans erreur simplement parce qu'il est trop paresseux pour connaître les exigences correctes, ce code ne devrait pas entrer en production et son auteur devrait être informé des conséquences possibles d'une telle paresse. .
la source
Au cours de toutes mes années passées à programmer et à développer des systèmes, il n’ya que deux situations dans lesquelles j’ai trouvé le modèle en question utile (dans les deux cas, la suppression contenait également la journalisation de l’exception levée, je ne considère pas que la prise et le
null
retour simples soient une bonne pratique. ).Les deux situations sont les suivantes:
1. Lorsque l'exception n'a pas été considérée comme un état exceptionnel
C’est à ce moment-là que vous effectuez une opération sur certaines données, ce qui peut générer des jets, mais vous souhaitez tout de même que votre application continue de fonctionner, car vous n’avez pas besoin des données traitées. Si vous les recevez, c'est bien, si vous ne les recevez pas, c'est aussi bien.
Certains attributs facultatifs d'une classe peuvent être pris en compte.
2. Lorsque vous fournissez une nouvelle implémentation (meilleure, plus rapide?) D'une bibliothèque en utilisant une interface déjà utilisée dans une application
Imaginez que vous ayez une application utilisant une sorte d’ancienne bibliothèque, qui ne lançait pas d’exceptions, mais renvoyait des
null
erreurs. Vous avez donc créé un adaptateur pour cette bibliothèque, copiant à peu près l'API d'origine de la bibliothèque, et utilisez cette nouvelle interface (toujours non lancée) dans votre application etnull
gérez vous-même les vérifications.Une nouvelle version de la bibliothèque est fournie, ou peut-être une bibliothèque complètement différente offrant les mêmes fonctionnalités qui, au lieu de renvoyer
null
s, lève des exceptions et que vous souhaitez l’utiliser.Vous ne voulez pas laisser les exceptions dans votre application principale. Vous devez donc les supprimer et les consigner dans l'adaptateur que vous avez créé pour envelopper cette nouvelle dépendance.
Le premier cas n'est pas un problème, c'est le comportement souhaité du code. Dans le second cas, cependant, si partout la
null
valeur renvoyée par l'adaptateur de bibliothèque signifie vraiment une erreur, ilnull
peut être judicieux de refactoriser l'API pour générer une exception et de la capturer au lieu de la rechercher (et le code est généralement une bonne idée).Personnellement, je n’utilise la suppression d’exception que pour le premier cas. Je ne l'ai utilisé que dans le second cas, lorsque nous n'avions pas le budget nécessaire pour que le reste de la demande fonctionne avec les exceptions au lieu de l'
null
art.la source
Bien qu'il semble logique de dire que les programmes ne doivent capturer que les exceptions qu'ils savent comment gérer et ne peuvent pas savoir comment gérer des exceptions qui n'ont pas été anticipées par le programmeur, une telle revendication ignore le fait que de nombreuses opérations peuvent échouer dans un processus. un nombre presque illimité de voies qui n'ont pas d'effets secondaires, et que dans de nombreux cas, le traitement approprié pour la grande majorité de ces défaillances sera identique; les détails exacts de l'échec seront sans importance et, par conséquent, peu importe si le programmeur les a anticipés.
Si, par exemple, une fonction a pour but de lire un fichier de document dans un objet approprié et de créer une nouvelle fenêtre de document pour montrer à cet objet ou de signaler à l'utilisateur que le fichier n'a pas pu être lu, une tentative de chargement Un fichier de document non valide ne doit pas bloquer l'application. Il doit plutôt afficher un message signalant le problème, mais laisser le reste de l'application continuer à s'exécuter normalement sauf si, pour une raison quelconque, la tentative de chargement du document a corrompu l'état d'un autre élément du système. .
Fondamentalement, le traitement correct d’une exception dépendra souvent moins du type d’exception que de l’endroit où elle a été lancée; si une ressource est protégée par un verrou en lecture-écriture et qu'une exception est levée dans une méthode ayant acquis le verrou en lecture, le comportement approprié doit généralement être de le libérer, car la méthode n'a rien pu faire pour la ressource. . Si une exception est levée alors que le verrou est acquis pour l'écriture, le verrou doit souvent être invalidé, car la ressource protégée peut être dans un état non valide. si la primitive de verrouillage n'a pas d'état "invalidé", il convient d'ajouter un indicateur pour suivre cette invalidation. Libérer le verrou sans l'invalider est mauvais, car un autre code peut voir l'objet protégé dans un état non valide. Laisser la serrure pendante, cependant, n'est pas ta solution appropriée non plus. La bonne solution consiste à invalider le verrou afin que toute tentative d'acquisition en cours ou future échoue immédiatement.
S'il s'avère qu'une ressource invalide est abandonnée avant toute tentative d'utilisation, il n'y a aucune raison pour qu'elle supprime l'application. Si une ressource invalidée est essentielle au fonctionnement continu d'une application, celle-ci devra être supprimée, mais son invalidité le rendra probablement nécessaire. Le code qui a reçu l’exception initiale n’aura souvent aucun moyen de savoir quelle situation s’applique, mais s’il invalide la ressource, il peut s’assurer que les mesures correctes seront prises dans les deux cas.
la source
Avaler ce genre d'erreur n'est utile à personne. Oui, l'appelant initial peut ne pas s'inquiéter de l'exception, mais quelqu'un d'autre pourrait .
Alors que font-ils? Ils ajouteront du code pour gérer l'exception afin de voir quelle sorte d'exception ils récupéreront. Génial. Mais si le gestionnaire d'exceptions est laissé, l'appelant d'origine n'est plus nul et quelque chose se casse ailleurs.
Même si vous êtes conscient que du code en amont peut générer une erreur et ainsi renvoyer null, il serait sérieusement inerte de votre part de ne pas au moins essayer de contourner l'exception contenue dans le code appelant IMHO.
la source
J'ai vu des exemples où des bibliothèques tierces avaient des méthodes potentiellement utiles, sauf qu'elles génèrent des exceptions dans certains cas qui devraient fonctionner pour moi. Que puis-je faire?
Par exemple, la méthode de la bibliothèque
retourne le premier toto, mais s'il n'y en a pas, il lève une exception. Mais il me faut une méthode pour renvoyer le premier toto ou un null. Alors j'écris celui-ci:
Pas chouette. Mais parfois, la solution pragmatique.
la source