209 votes

Comment utilisation de try catch pour la gestion des exceptions est conseillée

tout en maintenant le code de mon collègue de même quelqu'un qui prétend être un développeur senior, je vois souvent le code suivant :

ou parfois ils écrivent les informations de journalisation pour enregistrer les fichiers comme suit `` bloc

Je me demande si ce qu’ils ont fait est la meilleure pratique ? Il me rend confus parce que dans ma pensée les utilisateurs sachent ce qui se passe avec le système.

S’il vous plaît me donner quelques conseils.

319voto

Larry Points 6257

Ma gestion des exceptions la stratégie est :

  • Pour attraper toutes les exceptions non gérées par l'accrochage pour l' Application.ThreadException event, puis de décider :

    • Pour une application d'INTERFACE utilisateur: de la pop à l'utilisateur avec un message d'excuses (winforms)
    • Pour un Service ou d'une application Console: l'enregistrer dans un fichier (de service ou de la console)

Ensuite, j'ai toujours entourer chaque morceau de code qui est exécuté en externe en try/catch :

  • Tous les événements déclenchés par le Winforms (infrastructure de Charge, Cliquez sur, SelectedChanged...)
  • Tous les événements déclenchés par les composants tiers

Puis-je le mettre dans 'try/catch"

  • Toutes les opérations que je sais peut ne pas fonctionner tout le temps (opérations d'e / s, les calculs avec un potentiel de division par zéro...). Dans ce cas, je lance un nouveau ApplicationException("custom message", innerException) pour garder une trace de ce qui s'est vraiment passé

En outre, j'ai essayer de mon mieux pour trier les exceptions correctement. Il y a des exceptions:

  • besoin d'être montré immédiatement à l'utilisateur
  • besoin d'un traitement pour mettre les choses ensemble quand ils arrivent à éviter les problèmes en cascade (c'est à dire: mettre .EndUpdate dans l' finally section au cours d'une TreeView de remplissage)
  • l'utilisateur n'a pas de soins, mais il est important de savoir ce qui s'est passé. J'ai donc toujours vous connecter:

    • Dans le journal des événements
    • ou de dans une .fichier journal sur le disque

C'est une bonne pratique pour la conception de certaines méthodes statiques pour gérer les exceptions dans l'application de haut niveau des gestionnaires d'erreur.

J'ai aussi me forcer à essayer:

  • Rappelez-vous TOUTES les exceptions sont des bulles vers le haut niveau. Il n'est pas nécessaire de mettre des gestionnaires d'exceptions partout.
  • Réutilisable ou profondes appelées les fonctions n'a pas besoin de l'afficher ou le journal des exceptions : ils sont eigher bouillonnait automatiquement ou relancés avec certains des messages personnalisés dans mon gestionnaires d'exception.

Donc finalement :

Mauvais:

// DON'T DO, THIS IS BAD
try
{
    ...
}
catch 
{
   // only air...
}

Inutile:

// DONT'T DO, THIS IS USELESS
try
{
    ...
}
catch(Exception ex)
{
    throw ex;
}

Avoir de l'essayer, enfin, sans une prise est parfaitement valide:

try
{
    listView1.BeginUpdate();

    // If an exception occurs in the following code, then the finally will be executed
    // and the exception will be thrown
    ...
}
finally
{
    // I WANT THIS CODE TO RUN EVENTUALLY REGARDLESS AN EXCEPTION OCCURED OR NOT
    listView1.EndUpdate();
}

Ce que je fais au plus haut niveau:

// i.e When the user clicks on a button
try
{
    ...
}
catch(Exception ex)
{
    ex.Log(ex); // Log exception
    // ex.LogAndDisplay(ex); // Log exception, then show it to the user with apologies...
}

Ce que je fais dans certaines fonctions dites:

// Calculation module
try
{
    ...
}
catch(Exception ex)
{
    // Add useful information to the exception
    throw new ApplicationException("Something wrong happened in the calculation module :", ex);
}

// IO module
try
{
    ...
}
catch(Exception ex)
{
    throw new ApplicationException(string.Format("I cannot write the file {0} to {1}", fileName, directoryName), ex);
}

Il y a beaucoup à faire avec la gestion des exceptions (Personnalisé Exceptions), mais ces règles, j'essaie de garder à l'esprit sont assez pour les applications simples que je fais.

69voto

Keith Points 46288

La meilleure pratique est que la gestion des exceptions ne doit jamais cacher les problèmes. Cela signifie qu' try-catch blocs doivent être extrêmement rares.

Il y a 3 circonstances qui ont été à l'aide d'un try-catch de sens.

  1. Toujours traiter connu des exceptions aussi bas que vous le pouvez. Toutefois, si vous attendez une exception, il est généralement préférable de tester d'abord. Par exemple, l'analyse, la mise en forme et à l'arithmétique, les exceptions sont presque toujours mieux traités par la logique de contrôle, plutôt que spécifique try-catch.

  2. Si vous avez besoin de faire quelque chose sur une exception (par exemple, l'exploitation forestière ou d'annuler une transaction) puis re-lancer l'exception.

  3. Toujours traiter avec des inconnus exceptions près aussi haut que vous le pouvez - et le seul code, qui doit consommer une exception et ne pas re-jeter, il devrait être l'INTERFACE ou API publique.

Supposons que vous vous connectez à un API à distance, ici, vous savez à s'attendre à certaines erreurs (et avoir des choses dans ces circonstances), c'est donc le cas 1:

try 
{
    remoteApi.Connect()
}
catch(ApiConnectionSecurityException ex) 
{
    // User's security details have expired
    return false;
}

return true;

Notez qu'aucun d'autres exceptions sont pris, comme ils ne sont pas attendus.

Maintenant, supposons que vous essayez de sauver quelque chose à la base de données. Nous avons à le restaurer en cas de panne, nous avons donc affaire 2:

try
{
    DBConnection.Save();
}
catch
{
    // Roll back the DB changes so they aren't corrupted on ANY exception
    DBConnection.Rollback();

    // Re-throw the exception, it's critical that the user knows that it failed to save
    throw;
}

Notez que nous avons re-lancer l'exception - le code plus haut, faut quand même savoir que quelque chose a échoué.

Enfin, nous avons de l'INTERFACE utilisateur - ici, nous ne voulons pas complètement les exceptions non gérées, mais nous ne voulons pas de les cacher. Nous avons ici un exemple de cas 3:

try
{
    // Do something
}
catch(Exception ex) 
{
    // Log exception for developers
    WriteException2LogFile(ex);

    // Display message to users
    DisplayWarningBox("An error has occurred, please contact support!");
}

Cependant, la plupart des API ou des cadres de l'INTERFACE utilisateur ont générique façons de faire de cas 3. Par exemple ASP.Net a un jaune d'erreur de l'écran qui vide les détails de l'exception, mais qui peut être remplacé avec un message générique dans l'environnement de production. A la suite de ces est la meilleure pratique car il vous permet d'économiser beaucoup de code, mais aussi parce que l'erreur de l'enregistrement et l'affichage devrait être la configuration des décisions plutôt que de codé en dur.

Tout cela signifie que le cas 1 (connu des exceptions) et le 3 (one-off de l'INTERFACE utilisateur de manutention), les deux ont de meilleures habitudes (éviter l'erreur ou de la main d'erreur de manipulation hors de l'INTERFACE utilisateur).

Même cas 2 peut être remplacé par de meilleures habitudes, par exemple de transaction étendues (using blocs de restauration toute transaction engagés au cours de l') bloc de rendre plus difficile pour les développeurs pour obtenir la meilleure pratique pattern de mal.

Par exemple, supposons que vous avez une grande échelle ASP.Net application. La journalisation des erreurs peut-être par l'intermédiaire de ELMAH, erreur d'affichage peut être instructif YSoD localement et une belle localisée message dans la production. Connexions de base de données peuvent tous être via la transaction et des étendues using blocs. Vous n'avez pas besoin d'un seul try-catch bloc.

TL;DR: la Meilleure pratique est en fait de ne pas utiliser try-catch blocs.

37voto

Matías Fidemraizer Points 16842

Une exception est une erreur fatale.

Tout d'abord, la meilleure pratique doit être de ne pas jeter des exceptions pour tout type d'erreur, mais seulement si c'est une erreur de blocage.

Si l'erreur est fatale, puis jetez-le d'exception. Une fois l'exception est déjà jetés, il n'y a pas besoin de le cacher parce que c'est exceptionnel: permettre à l'utilisateur de savoir à ce sujet (vous devez reformater l'ensemble de l'exception à quelque chose d'utile à l'utilisateur dans l'INTERFACE utilisateur).

Votre travail en tant que développeur de logiciels seront toujours en essayant de ne pas tomber dans un cas exceptionnel où un certain nombre de paramètres ou de l'exécution de la situation peut mettre fin à une exception. Qui est, les exceptions ne doivent pas être coupé, mais qui doivent être évitées.

Par exemple, si vous savez que certaines entier d'entrée pourrait venir avec un format non valide, utilisez int.TryParse au lieu de int.Parse. Il y a beaucoup de cas où vous pouvez le faire au lieu de dire "s'il échoue, il suffit de lancer une exception".

De lever des exceptions est cher.

Si, après tout, une exception est levée, au lieu d'écrire l'exception pour le journal une fois qu'il a été jeté, l'un des meilleurs pratiques de l'attraper dans une première chance gestionnaire d'exception. Par exemple:

  • ASP.NET: Mondial.asax Application_Error
  • Autres: Domaine D'Application.FirstChanceException événement.

Ma suggestion est local essayer/captures sont mieux adaptés pour la manipulation cas particulier où l'on peut traduire une exception dans un autre, ou quand vous voulez "mute" pour un très très très très très spéciales (une bibliothèque bug de jeter un autre exception que vous avez besoin pour mettre en sourdine afin de contourner l'ensemble de bug).

Pour le reste des cas:

  • Essayez d'éviter les exceptions.
  • Si ce n'est pas possible: la première chance, les gestionnaires d'exception.
  • Ou utiliser un PostSharp aspect (AOP).

8voto

ChrisCW Points 31

Le seul moment où vous devriez vous inquiéter de vos utilisateurs à propos de quelque chose qui s'est passé dans le code, si il y a quelque chose qu'ils peuvent ou doivent faire pour éviter le problème. Si elles peuvent modifier des données dans un formulaire, appuyez sur un bouton ou de modifier un paramètre d'application afin d'éviter la question, alors laissez-leur savoir. Mais des avertissements ou des erreurs que l'utilisateur n'a pas la capacité à ne pas se contenter de leur fait perdre confiance en votre produit.

Les Exceptions et les Journaux sont pour vous, le développeur, pas votre utilisateur final. La compréhension de la bonne chose à faire lorsque vous attrapez chaque exception est beaucoup mieux que de simplement appliquer de la règle d'or ou de s'appuyer sur une application à l'échelle de filet de sécurité.

Aveugle de codage est le SEUL genre de mauvais codage. Le fait que vous sentez qu'il y a quelque chose de mieux à faire dans ces situations montre que vous êtes investi dans de bonnes codage, mais éviter d'essayer de timbre de certains génériques de règle dans ces situations et de comprendre la raison de quelque chose à jeter en premier lieu et de ce que vous pouvez faire pour la récupérer.

1voto

Faisal Hafeez Points 1635

Meilleure approche est deuxième (le sur où vous dire spécifiquement type d’exception). L’avantage de cela, que vous savez que ce type d’exception peut est venu dans votre code. Vous gérez ce type d’exception et vous pouvez reprendre. Mais si toute autre exception est venu qui signifie quelque chose ne va pas qui vous aideront à trouver des bugs dans votre code. Demande volonté finit par accident mais vous viendra de savoir que quelque chose vous manqué (bug) qui a besoin d’être réparé.

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