Wie zu lehren Ausnahmebehandlung für neue Programmierer? [geschlossen]

21

Wie unterrichten Sie Programmierern die Ausnahmebehandlung? Alle anderen Dinge sind einfach zu lernen - Datenstrukturen, ASP.NET, WinForms, WPF, WCF - Sie nennen es, alles kann einfach gelehrt werden.

Mit Ausnahmebehandlung, sie unterrichtend try-catch-finally ist nur die syntaktische Art der Ausnahmebehandlung.

Was Sie jedoch lernen sollten, ist: Welchen Teil Ihres Codes geben Sie in den Try- Block ein? Was tun Sie in dem catch - Block?

Lassen Sie es mich mit einem Beispiel veranschaulichen.

Sie arbeiten an einem Windows Forms-Projekt (einem kleinen Dienstprogramm) und haben es wie folgt mit drei verschiedenen Projekten entworfen.

  1. UILayer
  2. BusinessLayer
  3. DataLayer

Wenn bei DataLayer eine Ausnahme (z. B. das Laden eines XDocuments löst eine Ausnahme aus) ausgelöst wird (der UILayer ruft BusinessLayer auf, der wiederum den DataLayer aufruft), führen Sie einfach die folgenden Schritte aus

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

Was wird wieder in den BusinessLayer geworfen und was wird in UILayer abgefangen, wo ich es in die Protokolldatei schreibe?

Gehen Sie so bei der Ausnahmebehandlung vor?

Kanini
quelle
15
Wenn Sie wurden zu tun , gehen, wollen Sie nicht zu catch (Exception ex) {throw ex; } - stattdessen einfach fangen {werfen; }
Steven Evers
4
Vergessen wir nicht, endlich Blöcke?
Chris
1
Sie sollten die Sprache in den Tags angeben. Sie sind in mehr Detail zu gehen als die meisten Implementierungen von Ausnahmen üblich ist, und die Dinge außerhalb der Blöcke zu ignorieren. In C ++, zum Beispiel der wichtigste Teil der Ausnahmebehandlung ist , zu wissen , wie man schreibt Ausnahme sichere Programme.
David Thornley
mögliches Duplikat der Verbesserung der Ausnahmebehandlung? und der effizienten Nutzung
Mücke
Ich hoffe, Sie wissen, dass es eine schlechte Idee ist, eine "Ausnahme" abzufangen. Sie sollten verschachtelte catch - Blöcke haben spezifische Ausnahmen abfangen und behandeln sie entsprechend ( und nicht nur die Ausnahme werfen).
minusSeven

Antworten:

29

Um die Ausnahmebehandlung zu erläutern, erläutern Sie das Konzept dahinter: Der Code, in dem ein Fehler häufig auftritt, weiß nicht, wie dieser Fehler richtig behandelt wird. Der Code, der weiß, wie er richtig behandelt wird, könnte die Funktion sein, die diesen aufgerufen hat, oder er könnte weiter oben im Aufrufstapel liegen.

Wenn Sie eine Routine schreiben, die eine Routine aufruft, die möglicherweise eine Ausnahme auslöst, setzen Sie den Aufruf in einen Try-Block und den Fehlerbehandlungscode in den Catch-Block. Wenn nicht, lassen Sie es in Ruhe und lassen Sie etwas über sich in der Aufrufliste den Fehler behandeln.

Das Sprichwort "catch ex, throw ex" ist keine gute Methode zur Ausnahmebehandlung, da es eigentlich nichts behandelt. Abhängig davon, wie das Ausnahmemodell in Ihrer Sprache funktioniert, kann dies sogar schädlich sein, wenn Stack-Trace-Informationen gelöscht werden, die Sie zum Debuggen des Problems hätten verwenden können. Lassen Sie die Ausnahme einfach den Aufrufstapel weiterleiten, bis sie eine Routine erreicht, die weiß, wie sie damit umgeht.

Mason Wheeler
quelle
4
+1 für "... da es eigentlich nichts erledigt", denken Menschen, die sich mit Ausnahmebehandlung noch nicht auskennen, dass Fangen etwas bedeutet, und wissen nicht, ob Sie etwas tun, um das Problem zu beheben. Es ist keine Ausnahmebehandlung. einfach Code aufblähen.
Jimmy Hoffa
13

Wie die meisten Dinge werden Ausnahmen und Ausnahmebehandlungen für neue Programmierer wahrscheinlich wie eine Lösung auf der Suche nach einem Problem erscheinen, bis Sie zeigen, warum die scheinbar einfachere Lösung (C-Rückgabecodes und errno) so schlecht funktioniert. Ich würde damit beginnen, das Problem zu motivieren und in einen Kontext zu setzen. Zeigen Sie, wie die Fehlerbehandlung mithilfe von Rückkehrcodes oder globalen / statischen Variablen erfolgen kann. Dann geben Sie Beispiele, warum es nicht gut funktioniert. Führen Sie dann und nur dann Ausnahmen ein und erklären Sie, dass es sich um eine Form der Außerbandsignalisierung handelt. Der springende Punkt ist, dass das Standardverhalten, wenn Sie eine Ausnahme ignorieren, darin besteht, den Buck-up-Call-Stack an jemanden weiterzugeben, der dies kann damit umgehen.

Fazit: Wenn Sie zeigen, wie die Fehlerbehandlung in C durchgeführt wurde, verstehen die Schüler, wozu Ausnahmen wirklich gut sind, und warum das Abfangen von Ausnahmen, mit denen Sie nicht wirklich umgehen können, im Grunde die Art und Weise simuliert, wie die Dinge im Mittelalter getan wurden.

dsimcha
quelle
2
+1 für die Unterrichtspraxis, sie in den traditionellen C-Rückkehrcodes und Fehlernummern zu führen und ihnen zu zeigen, dass es schlecht funktioniert.
Kanini
3
@Kanini: Generell denke ich , die meisten relativ neu / hohe Konstrukte wie Lösungen auf der Suche nach Problemen scheinen und einfach zu bedienen ist falsch , wenn Sie nicht verstehen , was Problem , das sie gedacht waren , zu lösen und warum sie erfunden wurden.
dsimcha
Ich stimme zu, dass es gut ist zu zeigen, wie es ohne Ausnahmen gemacht wird, aber dann muss erklärt werden, wann Ausnahmen und wann andere Techniken anzuwenden sind (da nicht alle Situationen außergewöhnlich sind)
Matthieu M.
@Matthieu: Richtig. Wenn Sie jedoch verstehen, welche historischen Probleme mit Ausnahmen gelöst werden sollen, anstatt sie in einem luftleeren Raum kennenzulernen, wird klarer, dass es dumm ist, sie für nicht außergewöhnliche Situationen zu verwenden.
DSIMCHA
Richtig, das ist , warum Sie meine +1 bekommen. Ich hatte nur das Gefühl, Ihre Antwort könnte als "Niemals einen anderen Mechanismus verwenden" interpretiert werden :)
Matthieu M.
5

Ich würde mit Design-Richtlinien für Ausnahmen beginnen, die kurz sind und DO, DO NOT und AVOID enthalten. Es gibt auch die Gründe dafür.

In Ihrem Beispiel wäre der Revelvent-Abschnitt Wrapping Exceptions

Und würde erwarten, dass es so geschrieben wird. Beachten Sie, dass es fängt eine spezifische Ausnahme und versucht, Informationen hinzuzufügen, so dass eine aussagekräftigere Nachricht verbreitet wird. Beachten Sie auch, dass die innere Ausnahme für Protokollierungszwecke weiterhin beibehalten wird

//In DataLayer

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

UPDATE Kanini fragt ist es sogar direkt im Data Layer diesen Ausnahmeblock zu haben oder sollte die Überprüfung der Datei auf Business Layer zur Verfügung.

Zunächst möchte ich darauf hinweisen, dass die Begründung für das Umschließen von Ausnahmen die folgende ist

Ziehen Sie in Betracht, bestimmte Ausnahmen, die von einer niedrigeren Ebene ausgelöst wurden, in eine geeignetere Ausnahme einzubeziehen, wenn die Ausnahme für eine niedrigere Ebene im Kontext der Operation für eine höhere Ebene keinen Sinn ergibt.

Also, wenn Sie das Gefühl, die haben eine höhere Schicht über die Datei überhaupt, dann sollten Sie Ihre Datenschicht wie folgt aussehen wissen sollten

//In DataLayer

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

Kein Versuch kein Fang.

Persönlich bin ich der Meinung, dass es eine gute Sache ist, nichts zu tun oder die Ausnahme zu verpacken, wenn Ihre Datenschicht nicht etwas Nützliches wie die Verwendung einer Standarddatei systems.xml, die eine Assembly-Ressource darstellt, kann. ( throw exin diesem Fall oder dem bevorzugten throwauch, fügt aber keinen Wert hinzu). Dies bedeutet, dass Sie das Problem schnell beheben können, sobald Sie es identifiziert haben.

In diesem speziellen Beispiel tritt außerdem das folgende Problem in XDocument.Load auf, das vier Ausnahmen auslösen kann

  • ArgumentNullException
  • Sicherheitsaußnahme
  • FileNotFoundException
  • UriFormatException

Wir können nicht sicher garantieren, dass der folgende Code keine FileNotFoundException auslöst, da er möglicherweise vorhanden ist, wenn wir die Existenzprüfung durchführen, und nicht mehr vorhanden ist, wenn wir ihn laden. Dies der Business-Schicht zur Verfügung zu haben, würde nicht helfen.

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

SecurityException ist noch schlimmer, da unter anderem, wenn ein anderer Prozess eine exklusive Dateisperre hat, die Fehlermeldung erst angezeigt wird, wenn Sie ihn zum Lesen öffnen, da es keine File.CanIOpenThis () - Methode gibt. Und wenn eine solche Methode existiert, haben Sie immer noch das gleiche Problem wie bei File.Exists

Conrad Frix
quelle
Fix: Danke! Aber ist es überhaupt richtig, diesen Ausnahmeblock in der Datenschicht zu haben? Sollte die gesamte Prüfung, ob die Datei verfügbar ist oder nicht, in Business Layer erfolgen? Ansonsten stimme ich Ihrer Methode zum Schreiben des Codes zu.
Kanini
Fix: In meiner Muttersprache bedeutet Kanini einen Computer, während Kani eine Frucht bedeutet ;-)
Kanini
Ich kann Ihnen sagen, dass mein Fehler Sie nicht zu sehr aufregt, aber es tut mir sehr leid und ich habe ihn korrigiert.
Conrad Frix
1
Fix: Verärgert? Keineswegs. Weitgehend amüsiert. Mein Bruder hat nicht aufgehört zu lachen, seit ich ihn in erster Linie darauf hingewiesen habe, weil ich sowieso keiner Frucht ähnele, außer vielleicht wegen der merkwürdigen Form ...
Kanini
4

Lass uns eine Rolle spielen. (Dies ist kein Scherzbeitrag)

Sie sollten einen Workshop machen, in dem Sie die Anrufkette ausleben. Jede Person ist ein Objekt. Du brauchst ein paar Neulinge und ein paar Leute, die verstehen, dass das "Spiel" hilft.

Verwenden Sie ein wirklich einfaches Problem wie Datei-E / A. gui-> model-> file_io

Die Person, die der Dateileser ist, muss die nächste Person informieren ....

Tun Sie es zuerst mit Rückkehrcodes. (Post-It-Zettel verwenden?)

Wenn die Interaktionen nur "das sind, was der Code sagt", können Sie die Leute dazu bringen, zu erkennen, dass Ausnahmen außergewöhnlich sind.

Übergeben Sie für Rückkehrcodes einen Post-It-Zettel.

Für Ausnahmen werfen Sie Ihre Hände in die Luft und sagen Sie, was das Problem ist.

Lassen Sie sie dann "catch x, throw x" ausführen und sehen, dass die Diagnose "das Modell hatte eine Ausnahme" lautet.

Ich denke, das wird funktionieren, um die Leute zu schulen, die Sie haben, weil die Leute die Interaktionen mit anderen Leuten ziemlich gut verstehen.

Tim Williscroft
quelle
+1 für die Rollenspielidee. Daran haben wir noch nie gedacht. Wer hätte gedacht, dass das Unterrichten von Programmierung durch Rollenspiele möglich ist?
Kanini
1

Ich würde mir vorstellen, Ausnahmen zu verstehen, die Sie zuerst benötigen, um beispielsweise die Beziehung zwischen Kind und Eltern von Klassen zu verstehen. Wenn Sie verstehen, dass ein Kind Funktionen von einem Elternteil erben kann, kann es auf elementarer Ebene möglicherweise verstehen, dass ein Problem, das ein Kind nicht lösen kann, dieses Problem (Ausnahme) an sein Elternteil weiterleitet und es dem Elternteil überlässt damit.

Dies wird zu einer verketteten Beziehung, bis Sie an einen Ort gelangen, an dem etwas weiß, wie mit der Ausnahme umzugehen ist.

Und so weit es geht, ist dies der triviale Teil ... wenn ein Problem auftritt, muss etwas damit umgehen, damit das Programm nicht fatal beendet wird. Nachdem diese Ausnahme behandelt wurde, ist der finally-Block da, der unabhängig vom try-catch immer ausgeführt wird .

Ein gutes Beispiel hierfür könnte das Networking sein:

  • wir machen verbindung
  • Verbindung ist in Ordnung, so verwenden wir es
  • Wenn wir fertig sind, schließen wir und geben Ressourcen frei

oder in Ausnahmefällen:

  • eine Verbindung herstellen
  • Eine Ausnahme tritt auf, die etwas behandelt
  • An diesem Punkt setzen wir die damit verbundenen Verbindungen und Ressourcen frei
Chris
quelle
1

Geben Sie dem Neuling eine Anwendung, die eine sehr gute Ausnahmebehandlung bietet. Wirf irgendwo eine Ausnahme und lass sie mit Hilfe von Logs debuggen. Indem sie die Propogation von Exception verfolgen, sollten sie in der Lage sein, sie zu debuggen. Mache diese Übung 3 oder 4 mal. Entfernen Sie jetzt einfach alle Ausnahmebehandlungen aus dem Code und lassen Sie sie versuchen, die gleiche Ausnahme zu verfolgen.

Ich glaube, die Anerkennung für den Ausnahmebehandlungscode wird sofort gewürdigt.

Aussenseiter
quelle
Klingt wie ein Plan. Ist im Internet ein Beispielcode verfügbar (z. B. sourceforge.net), den Sie empfehlen würden?
Kanini
0

IMO, Sie sollten denken, dass Ausnahmebehandlung und Ablaufsteuerungsanweisungen im Grunde gleich sind. Sie verwenden sie, um den Ablauf Ihrer Programme basierend auf dem aktuellen Zustand zu steuern. Der Unterschied besteht darin, dass die Ausnahmebehandlung nur dann reagiert, wenn ein Fehler (oder eine Ausnahme) auftritt.


quelle
@denny: Obwohl ich der Aussage "Ausnahmebehandlung reagiert nur, wenn ein Fehler (oder eine Ausnahme) auftritt" zustimme, bin ich mir nicht sicher, ob "Ausnahmebehandlung und Ablaufsteuerungsanweisungen grundsätzlich gleich sind". Da bin ich mit Respekt anderer Meinung. Der catch-Block tut zugegebenermaßen, was er unter dieser Bedingung tun sollte. Der try-Block handelt jedoch überhaupt nicht von Fluss oder Kontrolle. Beim finally-Block geht es wiederum überhaupt nicht um Fluss oder Steuerung. Vielleicht habe ich Ihre Antwort falsch verstanden, aber können Sie zum Wohle von mir und anderen etwas klarstellen?
Kanini
0

Es würde wahrscheinlich keinem neuen Programmierer helfen, aber ich stellte fest, dass ich das Konzept der Ausnahmen viel besser verstand, als ich anfing, Monaden in der funktionalen Programmierung zu verwenden. Eine Monade zwingt Sie, jeden "Kanal" zu betrachten, durch den Daten in ein Programm gelangen oder aus einem Programm herausfließen können, da dies eine bequeme Abstraktion darstellt, um einen Teil dieses Datenflusses "zu verbergen".

Die Idee, dass eine Funktion verschiedene Ausgabetypen haben kann und eine Ausnahme wie ein Rückgabetyp mit höherer Priorität von der Funktion ist, ist ziemlich ordentlich.

Wohlgemerkt, ich verstehe, dass Ausnahmen in den meisten Sprachen nicht so funktionieren (Implementierungsdetails), aber im abstrakten Sinne ist das, was passiert.

CodexArcanum
quelle
0

Stellen Sie sich vor, ein Affe benutzt die Tastatur

Ich habe meinen Jungs immer gesagt, wenn sie Code schreiben, um so zu tun, als würde ein Affe im Tastenfeld sitzen und diese Anwendung verwenden.

Dies brachte ihnen bei, wie man alle möglichen Dinge vorwegnimmt:

  • Fehlende Daten
  • Fehlende Dateien
  • Alpha-Zeichen, wenn Sie Zahlen erwarten
  • Durch Null teilen

Ich denke, es war das Wortbild, dass ein Affe nur Schlüssel knallte und tat, was er wollte, anstatt gut mitzugehen, was den Trick brachte. Es hat bei mir funktioniert.

Michael Riley - AKA Gunny
quelle
Affen? Ich nehme an, Ihre Geschäftsanwender haben das noch nie gehört ;-)
Kanini
@ Kanini - Gute. Das war zu Zeiten meines Marine Corps. Ich wollte nur, dass meine Jungs über den Tellerrand hinaus denken, wenn es um die Fehlerbehebung geht. Habe ich gerade Fehlerbehebung gesagt ... ich meinte Ausnahmebehandlung.
Michael Riley - AKA Gunny