Comment enseigner la gestion des exceptions pour les nouveaux programmeurs? [fermé]


21

Comment allez-vous enseigner la gestion des exceptions aux programmeurs. Toutes les autres choses sont enseignées facilement - Structures de données, ASP.NET, WinForms, WPF, WCF - vous l'appelez, tout peut être enseigné facilement.

Avec la gestion des exceptions, leur apprendre try-catch-finally n'est que la nature syntaxique de la gestion des exceptions.

Ce qui devrait être enseigné cependant, c'est - Quelle partie de votre code mettez-vous dans le bloc try ? Que faites-vous dans le bloc catch ?

Permettez-moi de l'illustrer avec un exemple.

Vous travaillez sur un projet Windows Forms (un petit utilitaire) et vous l'avez conçu comme ci-dessous avec 3 projets différents.

  1. UILayer
  2. BusinessLayer
  3. DataLayer

Si une exception (disons que le chargement d'un XDocument lève une exception) est déclenchée chez DataLayer (l'UILayer appelle BusinessLayer qui à son tour appelle DataLayer), faites-vous simplement ce qui suit

//In DataLayer
try {
    XDocument xd_XmlDocument = XDocument.Load("systems.xml");
} 
catch(Exception ex)
{
    throw ex;
}

qui est jeté à nouveau dans BusinessLayer et qui est pris dans UILayer où je l'écris dans le fichier journal?

Est-ce ainsi que vous gérez la gestion des exceptions?


15
Si vous étiez allez le faire, vous ne voulez pas catch (Exception ex) {throw ex; } - à la place, juste attraper {throw; }
Steven Evers

4
N'oublions pas enfin les blocs?
Chris

1
Vous devez spécifier la langue dans les balises. Vous obtenez plus de détails que la plupart des implémentations d'exceptions et ignorez les choses en dehors des blocs. En C ++, par exemple, la partie la plus importante de la gestion des exceptions est de savoir comment écrire des programmes sans exception.
David Thornley


J'espère que vous savez que c'est une mauvaise idée d'attraper une "exception". Vous devez avoir des blocs catch imbriqués pour intercepter des exceptions spécifiques et les gérer en conséquence (et pas simplement lever l'exception).
minSeven

Réponses:


29

Pour expliquer la gestion des exceptions, expliquez le concept derrière: le code où une erreur se produit fréquemment ne sait pas comment gérer correctement cette erreur. Le code qui sait comment le gérer correctement pourrait être la fonction qui l'a appelée, ou il pourrait être plus haut dans la pile des appels.

Lorsque vous écrivez une routine qui appelle une routine susceptible de lever une exception, si vous savez comment gérer correctement cette erreur, placez l'appel dans un bloc try et placez le code de gestion des erreurs dans le bloc catch. Sinon, laissez-le tranquille et laissez quelque chose au-dessus de vous dans la pile d'appels gérer l'erreur.

Dire "catch ex, throw ex" n'est pas un bon moyen de gérer les exceptions, car il ne gère rien. De plus, selon le fonctionnement du modèle d'exception dans votre langue, cela peut en fait être dangereux s'il efface les informations de trace de pile que vous auriez pu utiliser pour déboguer le problème. Laissez simplement l'exception se propager dans la pile des appels jusqu'à ce qu'elle atteigne une routine qui sait comment la gérer.


4
+1 pour "... car il ne gère rien du tout", les utilisateurs novices de la gestion des exceptions pensent si souvent que la capture signifie la gestion et ne réalisent pas que si vous ne faites rien pour réparer le problème, ce n'est pas la gestion des exceptions, il suffit de coder le ballonnement.
Jimmy Hoffa

13

Comme la plupart des choses, les exceptions et la gestion des exceptions sembleront probablement une solution à la recherche d'un problème pour les nouveaux programmeurs jusqu'à ce que vous montriez pourquoi la solution apparemment plus simple (codes de retour de style C et errno) fonctionne si mal. Je commencerais par motiver le problème et le mettre en contexte. Montrez comment la gestion des erreurs peut être effectuée à l'aide de codes retour ou de variables globales / statiques. Donnez ensuite des exemples des raisons pour lesquelles cela ne fonctionne pas bien. Ensuite et seulement ensuite, introduisez des exceptions et expliquez qu'il s'agit d'une forme de signalisation hors bande et que le fait est que le comportement par défaut si vous ignorez une exception est de transmettre la responsabilité de la pile d'appels à quelqu'un qui peut gérer.

Conclusion: montrer comment la gestion des erreurs a été effectuée en C permettra aux élèves de comprendre à quoi servent vraiment les exceptions et pourquoi intercepter des exceptions que vous ne pouvez pas vraiment gérer, c'est essentiellement simuler la façon dont les choses ont été faites au Moyen Âge.


2
+1 pour la pratique pédagogique de les diriger dans les codes de retour et les numéros d'erreur de style C traditionnels et de leur montrer que cela fonctionne mal et, par conséquent, leur enseigner comment cela fonctionnera est un brillant!
Kanini

3
@Kanini: En général, je pense que la plupart des constructions relativement nouvelles / de haut niveau semblent être des solutions à la recherche de problèmes et sont faciles à mal utiliser si vous ne comprenez pas quel problème elles étaient censées résoudre et pourquoi elles ont été inventées.
dsimcha

Je suis d'accord qu'il est bon de montrer comment cela serait fait sans exceptions, mais vient ensuite le fardeau d'expliquer quand utiliser des exceptions et quand utiliser d'autres techniques (car toutes les situations ne sont pas exceptionnelles)
Matthieu M.

@Matthieu: D'accord. Mais si vous comprenez quels problèmes historiques les exceptions sont censées résoudre, plutôt que d'en apprendre dans le vide, il devient plus évident qu'il est idiot de les utiliser pour des situations non exceptionnelles.
dsimcha

à droite, c'est pourquoi vous avez obtenu mon +1. Je pensais juste que votre réponse pourrait être interprétée comme "n'utilisez jamais un autre mécanisme" :)
Matthieu M.

5

Je commencerais par Design Guidelines for Exceptions, son court et comprend DO, DO NOT et EVOID. Il explique également pourquoi.

Dans votre exemple, la section revelvent serait Wrapping Exceptions

Et s'attendrait à ce qu'il soit écrit de cette façon. Notez qu'il intercepte une exception spécifique et tente d'ajouter des informations afin qu'un message plus significatif soit propagé. Notez également que l'exception interne est toujours conservée à des fins de journalisation

//In DataLayer

try
{
XDocument xd_XmlDocument = XDocument.Load("systems.xml");
}
catch(FileNotFoundException ex)
{
        throw new TransactionFileMissingException(
                     "Cannot Access System Information",ex);
}

UPDATE Kanini demande s'il est même juste d'avoir ce bloc d'exception dans la couche de données ou si la vérification du fichier est disponible pour la couche métier.

Eh bien tout d'abord, je voudrais souligner que la justification des exceptions d'emballage est la suivante

Envisagez d'envelopper des exceptions spécifiques levées à partir d'une couche inférieure dans une exception plus appropriée, si l'exception de couche inférieure n'a pas de sens dans le contexte de l'opération de couche supérieure.

Donc, si vous pensez que la couche supérieure devrait connaître le fichier, votre couche de données devrait ressembler à ceci

//In DataLayer

XDocument xd_XmlDocument = XDocument.Load("systems.xml");

No Try No Catch.

Personnellement, je pense qu'à moins que votre couche de données puisse faire quelque chose d'utile comme utiliser un fichier systems.xml par défaut qui est une ressource d'assemblage, ne rien faire ou encapsuler l'exception est un bon pari puisque votre journalisation vous dira quelle méthode et quel fichier ont été le problème. ( throw exdans ce cas ou le préféré throwaussi mais n'ajoute aucune valeur). Cela signifie qu'une fois identifié, vous pourrez résoudre le problème rapidement.

En tant qu'asside, cet exemple particulier a également le problème suivant en ce que XDocument.Load peut lancer quatre exceptions

  • ArgumentNullException
  • Exception de sécurité
  • FileNotFoundException
  • UriFormatException

Nous ne pouvons pas garantir en toute sécurité que le code suivant ne lèvera pas et FileNotFoundException, simplement parce qu'il pourrait être là lorsque nous vérifions l'existence et disparu lorsque nous chargeons. Avoir cela à la disposition de la couche métier n'aiderait pas.

 if (File.Exists("systems.xml")) 
     XDocument.Load("systems.xml");

SecurityException est encore pire car, entre autres raisons, si un autre processus s'empare d'un verrou de fichier exclusif, vous n'obtiendrez pas l'erreur jusqu'à ce que vous essayiez de l'ouvrir pour la lecture car il n'y a pas de méthode File.CanIOpenThis (). Et si une telle méthode existait, vous avez toujours le même problème qu'avec File.Exists


Correction: merci! Mais est-il même juste d'avoir ce bloc d'exception dans la couche de données? Le tout devrait-il vérifier si le fichier est disponible ou non dans la couche métier? Sinon, j'accepte votre méthode d'écriture du code.
Kanini

Corrigé: Dans ma langue maternelle, Kanini signifie un ordinateur tandis que Kani signifie un fruit ;-)
Kanini

Je peux dire que vous n'êtes pas trop contrarié par mon erreur, mais je suis vraiment désolé et je l'ai corrigé.
Conrad Frix

1
Correction: bouleversé? Pas du tout. Largement amusé. Mon frère n'a pas cessé de rire depuis que je lui ai fait remarquer cela principalement parce que, je ne ressemble en aucun cas à un fruit sauf peut-être pour la forme bizarre ...
Kanini

4

Permet de faire un jeu de rôle. (ce n'est pas une blague)

Vous devriez faire un atelier où vous jouez la chaîne d'appel. Chaque personne est un objet. Vous aurez besoin de quelques débutants et de personnes qui comprennent le "jeu".

Utilisez un problème très simple comme le fichier IO. gui-> model-> file_io

La personne qui est le lecteur de fichiers doit informer le suivant ...

Faites-le d'abord avec les codes retour. (utiliser des post-it?)

si les interactions ne sont que «ce que dit le code», vous pourrez bientôt faire comprendre aux gens que les exceptions sont exceptionnelles.

pour les codes retour, passez un post-it.

pour les exceptions, jetez vos mains en l'air et dites quel est le problème.

puis demandez-leur de faire "attraper x, lancer x" et voir bien pire le diagnostic est ce que l'interface graphique obtient "le modèle avait une exception".

Je pense que cela fonctionnera pour former les gens que vous avez parce que les gens comprennent assez bien les interactions avec les autres.


+1 pour l'idée du jeu de rôle. Nous n'y avons jamais pensé plus tôt. Qui aurait pu penser que l'enseignement de la programmation pouvait se faire par le biais d'un jeu de rôle?
Kanini

1

J'imagine que pour comprendre les exceptions, vous devez d'abord comprendre la relation enfant / parent des classes par exemple. Si vous comprenez qu'un enfant peut hériter des fonctionnalités d'un parent, il pourrait être en mesure de comprendre au niveau élémentaire que si un enfant a un problème qu'il ne peut pas gérer, il transmettra ce problème (exception) à son parent et laissera le parent s'occuper avec ça.

Cela devient une relation enchaînée jusqu'à ce que vous vous retrouviez avec un endroit où quelque chose sait comment gérer l'exception.

Et pour ce qui est de la fin, c'est la partie triviale ... quand un problème survient, quelque chose doit le gérer pour que le programme ne se termine pas fatalement, après que cette exception est gérée, le bloc finally est là qui s'exécutera toujours quel que soit le try catch .

Un bon exemple de cela pourrait être avec le réseautage:

  • nous faisons le lien
  • la connexion est ok donc nous l'utilisons
  • une fois terminé, nous fermons et libérons les ressources

ou en cas d'exception:

  • établir une connexion
  • une exception se produit que quelque chose gère
  • à quel point nous libérons la connexion et les ressources associées

1

Donnez une application au débutant qui a une très bonne gestion des exceptions. Jetez une exception quelque part et laissez-les déboguer à l'aide de Logs. En suivant la propagation de l'exception, ils devraient pouvoir la déboguer. Faites cet exercice 3 ou 4 fois. Maintenant, supprimez tout le traitement des exceptions du code et laissez-les essayer de suivre la même exception.

Je crois que l'appréciation du code de gestion des exceptions sera instantanément appréciée.


Ça ma l'air bon. Avez-vous un exemple de code disponible sur Internet (par exemple, sourceforge.net) que vous recommanderiez?
Kanini

0

OMI, vous devriez penser que la gestion des exceptions et les instructions de contrôle de flux sont fondamentalement les mêmes. Vous les utilisez pour contrôler le flux de vos programmes en fonction de la condition dans laquelle ils se trouvent actuellement. La différence est que la gestion des exceptions ne réagira qu'en cas d'erreur (ou d'exception).


@denny: Bien que je sois d'accord avec "la gestion des exceptions ne réagira que lorsqu'une erreur (ou exception) se produira", je ne suis pas sûr de la déclaration selon laquelle "les instructions de gestion des exceptions et de contrôle de flux sont fondamentalement les mêmes". Je suis respectueusement en désaccord là-bas. Certes, le bloc de capture fait ce qu'il devrait faire dans cette condition. Cependant, le bloc try n'est pas du tout un flux ou un contrôle. Le bloc final, encore une fois, ne concerne pas du tout le débit ou le contrôle. Peut-être, j'ai mal compris votre réponse, mais pouvez-vous clarifier pour le bénéfice de moi et des autres?
Kanini

0

Cela n'aiderait probablement pas un nouveau programmeur, mais j'ai trouvé que je comprenais beaucoup mieux le concept des exceptions une fois que j'ai commencé à utiliser des monades dans la programmation fonctionnelle. Une monade vous oblige à considérer chaque «canal» à travers lequel les données peuvent entrer ou sortir d'un programme, car tout ce qu'il fait, il fournit une abstraction pratique pour «cacher» une partie de ce flux de données.

L'idée qu'une fonction peut avoir différents types de sortie, et une exception est comme un type de retour de priorité plus élevée de la fonction est assez nette.

Attention, je comprends que ce n'est pas ainsi que fonctionnent les exceptions dans la plupart des langues (détails d'implémentation), mais dans un sens abstrait, c'est ce qui se passe.


0

Imaginez qu'un singe utilise le clavier

J'avais l'habitude de dire à mes gars quand ils écrivaient du code pour prétendre qu'un singe serait assis au clavier et utiliserait cette application.

Cela leur a appris à anticiper toutes sortes de choses:

  • Données manquantes
  • Fichiers manquants
  • Caractères alpha lorsque vous attendez des nombres
  • Division par zéro

Je pense que c'était le mot image d'avoir un singe qui claquait des touches et de faire ce qu'il voulait au lieu de suivre gentiment qui a fait l'affaire. Ça a marché pour moi.


Singes? Je suppose que les utilisateurs de votre entreprise n'ont jamais entendu cela ;-)
Kanini

@Kanini - Bien. C'était à l'époque de mon Corps des Marines. Je voulais juste que mes gars sortent des sentiers battus en ce qui concerne le piégeage d'erreurs. Est-ce que je viens de dire le piégeage d'erreur ... Je voulais dire la gestion des exceptions.
Michael Riley - AKA Gunny
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.