Recommander un modèle / approche de conception pour exposer / tolérer / récupérer des erreurs système, gestion des exceptions (par exemple en Java, C ++, Perl, PHP)

13

Pouvez-vous recommander un modèle / une approche de conception pour exposer / tolérer / récupérer des erreurs système, la gestion des exceptions (Java, C ++, Perl, PHP)?

Certaines erreurs doivent être signalées.

Certaines erreurs peuvent être traitées en interne (par une nouvelle tentative ou sont sans conséquence (peuvent être ignorées).

Comment structurez-vous le code pour les capturer?

Mais toutes les erreurs doivent être enregistrées.

Quelles sont les meilleures pratiques?

Et pour les simuler afin de pouvoir tester pleinement les composants qui sont impactés par eux?

Question générale non spécifique au langage de programmation applicable à plusieurs langages de programmation modernes, mais accueillant des exemples d'illustration de modèles, d'approches et de philosophies en Java, C ++, PHP et Perl.

(Également demandé dans stackoverflow: /programming/7432596/recommend-a-design-pattern-approach-to-exposing-tolerating-recovering-from-system mais j'ai pensé que cela devrait aussi être demandé aux programmeurs car Je pense que les questions et réponses des programmeurs couvrent des problèmes de programmation / logiciels plus larges alors que stackoverflow concerne davantage la mise en œuvre technique à mon humble avis).

therobyouknow
la source
2
Pour moi, votre question semble beaucoup trop générale et ouverte pour recevoir une réponse efficace. Essayez de le restreindre à des cas plus spécifiques et également à des types / environnements d'application spécifiques (par exemple, application / serveur GUI / ...).
Péter Török
Voir aussi stackoverflow.com/questions/937285/…
Péter Török
@ Péter Török, mikera apporte une bonne réponse, susceptible d'accepter la leur.
therobyouknow

Réponses:

16

Échouer rapidement est une excellente approche de conception, et peut-être peut-il être considéré comme un modèle: http://en.wikipedia.org/wiki/Fail-fast

J'ai également trouvé un certain nombre de principes utiles:

  • Considérez les exceptions comme faisant partie de l'interface de chaque fonction / module - c.-à-d. Documentez-les et le cas échéant / si votre langue le prend en charge, utilisez les exceptions vérifiées.
  • Ne truquez jamais un échec - s'il a échoué, n'essayez pas de continuer en essayant de "supposer" comment procéder. Par exemple, une gestion spéciale pour les cas nuls est souvent une odeur de code pour moi: si votre méthode a besoin d'une valeur non nulle, elle devrait lever immédiatement une exception si elle rencontre un null (soit NullPointerException ou idéalement une IllegalArgumentException plus descriptive).
  • Écrivez des tests unitaires pour des cas exceptionnels ainsi que des tests normaux - parfois, ces tests peuvent être difficiles à configurer, mais cela en vaut la peine lorsque vous voulez être sûr que votre système est résistant aux défaillances
  • Journal au point où l'erreur a été détectée et gérée (en supposant que l'erreur était suffisamment grave pour être enregistrée). La raison en est que cela implique que vous avez compris la cause et que vous avez eu une approche pour gérer l'erreur, vous pouvez donc rendre le message de journal significatif .....
  • N'utilisez des exceptions que pour des conditions / échecs vraiment inattendus. Si votre fonction "échoue" d'une manière qui est réellement attendue (par exemple, interrogation pour voir si plus d'entrée est disponible, et n'en trouver aucune), alors elle devrait retourner une réponse normale ("aucune entrée disponible"), ne pas lever d'exception
  • Échec gracieusement (crédit à Steven Lowe!) - nettoyez avant de terminer si possible, généralement en annulant les modifications, en annulant la transaction ou en libérant des ressources dans une instruction «enfin» ou l'équivalent. Le nettoyage devrait idéalement avoir lieu au même niveau auquel les ressources ont été engagées dans un souci de clarté et de cohérence logique.
  • Si vous devez échouer, échouez fort - une exception qu'aucune partie de votre code n'a été en mesure de gérer (c'est-à-dire percolée au niveau supérieur sans être capturée + manipulée) devrait provoquer une défaillance immédiate, forte et visible qui attire votre attention sur elle. J'arrête généralement le programme ou la tâche et j'écris un rapport d'exception complet sur System.out.
mikera
la source
1
échouent également gracieusement - nettoyez avant de terminer si possible
Steven A. Lowe
+1 @mikera pour des points clairs sur ce qu'il faut considérer. Réponse probablement acceptée, je vais laisser ouverte un peu plus longtemps pour que d'autres contribuent.
therobyouknow
+1 @Steve A. Lowe - pour une conception centrée sur l'utilisateur. par exemple, comme enregistrer des fichiers, ne pas laisser traîner les fichiers temporaires. Voir ma question sur «l'hygiène des données» comme sujet connexe dans ma liste de questions.
therobyouknow
5

Ayant travaillé avec des exceptions en Java et .NET ET après avoir lu beaucoup d'articles sur comment / quand / pourquoi intercepter des exceptions, j'ai finalement trouvé les étapes suivantes que je traverse dans ma tête chaque fois que je vois une exception potentielle se produire, ou un exception je dois attraper (Java) ... même si ça n'arrive jamais (soupir ...). Et cela semble fonctionner, au moins pour moi:

  1. Y a-t-il quelque chose d'utile que je peux faire avec cette exception (sauf la journalisation)? Si la réponse est oui, écrivez le code de la solution de contournement et si la solution de contournement peut lever des exceptions, passez à 2:
  2. Enveloppez l'exception autour d'une exception d'exécution, jetez-la, passez à 3.
  3. Dans la classe de niveau supérieur où une éventuelle transaction de base de données / processus a été lancée, interceptez l'exception, annulez la transaction, renvoyez l'exception.
  4. Au niveau supérieur (qui peut être celui où la transaction a été initiée), enregistrez l'exception à l'aide d'un cadre de journalisation tel que slf4j (couplé à log4j par exemple) ou log4net . Si possible, envoyez directement l'exception à une liste de distribution composée de développeurs de l'application.
  5. S'il existe une interface graphique, affichez un message d'erreur indiquant de la manière la plus conviviale la cause du problème; n'affiche pas l'exception / stacktrace, l'utilisateur s'en fiche et n'a pas besoin de savoir qu'il s'agissait d'une NullPointerException.

Je devrais également ajouter l' étape 0 , où je lève intentionnellement ce que j'appelle une exception "métier" (une nouvelle exception que je crée en étendant la classe "Exception") lorsqu'un traitement complexe ne peut pas être exécuté en raison d'erreurs de données, MAIS cela sont connus car ils ont été identifiés comme des cas d'exception au cours de l'analyse.

À l'exception de la partie enregistrement, je suis entièrement d'accord avec les points écrits par "mikera"; J'ajouterai simplement que l'exception doit être enregistrée une fois seule .

En outre, les étapes que j'ai répertoriées peuvent être différentes si ce que vous écrivez est une API / Framework . Là, le lancement d'exceptions bien conçues est obligatoire pour aider les développeurs à comprendre leurs erreurs.

En ce qui concerne le test des exceptions, en utilisant des objets fictifs, vous devriez pouvoir tester presque tout, qu'il soit exceptionnel ou non, à condition que vos classes respectent la meilleure pratique "une classe pour faire une chose". Je m'assure également personnellement de marquer les méthodes les plus importantes mais cachées comme "protégées" au lieu de "privées" afin de pouvoir les tester sans trop de tracas. En dehors de cela, tester les exceptions est simple, il suffit de provoquer l'exception et de "s'attendre" à ce qu'une exception se produise en l'attrapant. Si vous n'obtenez pas d'exception, vous avez une erreur de cas de test unitaire.

Jalayn
la source
+1 @Jalayn pour la mention log4j en tant qu'approche, c'est ce que j'utilise donc cela le renforce de savoir que quelqu'un d'autre l'est aussi.
therobyouknow
0

Construisez vos objets de la bonne façon, ne vous inquiétez pas des facteurs externes. Si vous choisissez de profiter des exceptions, faites en sorte que vos objets lèvent des exceptions s'ils échouent à quelque chose.

Une fois que tous vos objets fonctionnent correctement, il devrait être assez facile de créer une hiérarchie de responsabilité de gestion des erreurs propre dans votre conception.

Yam Marcovic
la source