2010-09-08 1 views
2

Je travaille sur une base de code avec un groupe de développeurs qui ne sont pas principalement informatique ou en génie logiciel (surtout en génie informatique)Quand et comment attraper des exceptions

Je cherche un bon article sur le moment les exceptions devraient être attrapées et quand on devrait essayer de récupérer d'eux. J'ai trouvé un article il y a un moment que je pensais avoir bien expliqué les choses, mais Google ne m'aide pas à le retrouver.

Nous développons en C++. Les liens vers des articles sont une forme acceptable de réponse, tout comme les résumés avec des pointeurs. J'essaie d'enseigner ici, donc le format du tutoriel serait bon. Tout comme ce qui a été écrit pour être accessible aux ingénieurs non-logiciels. Merci.

+0

Il y a quelque temps, nous avons parlé sur les exceptions: http://stackoverflow.com/questions/1744070/why-should-exceptions-be-used-conservatively –

+2

Attraper exceptions est seulement une partie de l'écriture bonne et robuste code C++. Pensez-vous que vous et vos collègues avez une bonne compréhension de l'écriture de code de sécurité exceptionnelle, ou avez-vous besoin de références à cela aussi? –

+0

Été absent pendant un moment, désolé pour le retard.Je pense avoir une compréhension raisonnable de l'écriture de code de sécurité, mais pas tellement avec mes collègues, donc des références pour cela seraient également appréciées. – BitShifter

Répondre

5

Herb Sutter a un excellent article qui peut vous être utile. Il ne répond pas à votre question spécifique (quand/comment attraper) mais donne une vue d'ensemble et des lignes directrices pour gérer les conditions exceptionnelles.

J'ai copié son résumé ici textuellement

Distinguer entre les erreurs et nonerrors. Un échec est une erreur si et seulement si elle viole une capacité de fonction de respecter ses conditions de fonctions appelées, d'établir ses propres postconditions, ou de rétablir un partage invariant la responsabilité de maintenir . Tout le reste n'est pas une erreur .

Assurez-vous que les erreurs laissent toujours votre programme dans un état valide; c'est la garantie de base . Méfiez-vous des erreurs invariantes-destructrices (y compris, mais sans s'y limiter, fuites), qui sont tout simplement des bugs.

préfère pour garantir en outre que soit l'état final est soit le état d'origine (s'il y avait une erreur, l'opération a été annulée) ou état cible prévue (en l'absence d'erreur , l'opération était engagé); c'est la garantie forte.

Préférez de plus garantir que l'opération ne peut jamais échouer. Bien que ce n'est pas possible pour la plupart des fonctions , il est requis pour fonctions telles que les destructeurs et fonctions de désallocation.

Enfin, préférez utiliser les exceptions au lieu des codes d'erreur pour signaler les erreurs . Utiliser les codes d'erreur que lorsque exceptions ne peuvent pas être utilisés (lorsque vous ne contrôlez pas possible d'appeler code et ne peut pas garantir qu'il sera écrit en C++ et compilé en utilisant le même compilateur et compatible compilez options), et pour les conditions pas d'erreurs.

+0

Comme toujours j'aime le style de Sutter et ses conseils sont solides. Cependant, j'ai peur que "préférer utiliser des exceptions au lieu de codes d'erreur" pourrait être mal interprété. Ceci n'est pas une excuse d'exceptions disant que chaque "mésaventure" devrait être signalée comme une exception, cela signifie que si vous devez choisir entre retourner un code d'erreur ou lancer une exception, vous devriez lancer. Je ne suis pas si sûr de ça moi-même. –

+1

Les codes d'erreur ont leur place (ne remplacez pas tout avec une exception car vous pouvez (juste là où c'est approprié)). Par exemple: Dans une classe, il est correct d'utiliser des codes d'erreur entre des méthodes privées tant que le code d'erreur n'est jamais exposé à l'utilisateur de la classe. –

0

Le conseil le plus simpliste:

Si vous ne savez pas si vous attrapez ou non une exception, ne l'attrapez pas et laissez-la couler, quelqu'un le fera à un moment donné.

Le point à propos des exceptions est qu'elles sont exceptionnelles (pensez std::bad_alloc). Mis à part quelques utilisations bizarres pour la "sortie rapide" de blocs de code profondément imbriqués (que je n'aime pas beaucoup), les exceptions ne devraient être utilisées que lorsque vous remarquez quelque chose que vous n'avez aucune idée de comment faire.

Reprenons les exemples:

file = open('littlefile.txt', open.mode.Read) 

Il ne semble évident, pour moi, que cela peut échouer, et dans un certain nombre de conditions. Bien qu'il soit important de signaler la cause de l'échec (pour un diagnostic précis), je trouve que lancer une exception n'est PAS une bonne pratique.

En C++ Je voudrais écrire une telle fonction:

boost::variant<FileHandle,Error> open(std::string const& name, mode_t mode); 

La fonction peut soit renvoyer un descripteur de fichier (grande) ou une erreur (oups). Mais comme on s'y attend, mieux y faire face maintenant. En outre, il a le grand avantage d'être explicite, en regardant la signature signifie que vous savez à quoi vous attendre (ne parle pas de spécifications d'exception, c'est une fonctionnalité cassée).

En général, j'ai tendance à considérer ces fonctions comme des fonctions find. Lorsque vous recherchez quelque chose, on s'attend à ce que la recherche échoue, il n'y a rien d'exceptionnel ici.

Pensez le cas général d'un conteneur associatif:

template <typename Key, typename Value> 
boost::optional<Value const&> Associative::GetItem(Key const& key) const; 

Encore une fois, grâce à Boost, je précise que ma méthode peut (ou non) retourner la valeur attendue. Il n'est pas nécessaire d'émettre une exception ElementNotFound.

Encore un autre exemple: la validation de l'entrée de l'utilisateur devrait échouer. En général, les intrants devraient être hostiles/mal formés/mauvais. Pas besoin d'exceptions ici. D'autre part, supposons que mon logiciel traite une base de données et ne puisse pas fonctionner sans lui. Si la couche d'abstraction de la base de données perd la connexion à la base de données et ne peut pas en établir une nouvelle, il est logique de déclencher une exception.

Je réserve des exceptions pour des problèmes techniques (perte de connexion, mémoire insuffisante, etc ...).