Ist es wirklich schlecht, allgemeine Ausnahmen zu erwischen?

57

Normalerweise stimme ich den meisten Warnungen zur Codeanalyse zu und versuche, diese einzuhalten. Allerdings fällt es mir hier schwerer:

CA1031: Allgemeine Ausnahmetypen nicht abfangen

Ich verstehe die Gründe für diese Regel. Aber wenn ich in der Praxis unabhängig von der ausgelösten Ausnahme die gleiche Aktion ausführen möchte, warum sollte ich dann jede einzelne speziell behandeln? Was passiert, wenn sich der von mir aufgerufene Code ändert, um in Zukunft eine neue Ausnahme auszulösen, wenn ich bestimmte Ausnahmen behandle? Jetzt muss ich meinen Code ändern, um diese neue Ausnahme zu behandeln. Wenn ich Exceptionmeinen Code einfach fange , muss er sich nicht ändern.

Wenn Foo beispielsweise Bar aufruft und Foo die Verarbeitung unabhängig von der Art der von Bar ausgelösten Ausnahmebedingung beenden muss, hat es dann einen Vorteil, die Art der Ausnahmebedingung zu bestimmen, die ich abfange?

Vielleicht ein besseres Beispiel:

public void Foo()
{
    // Some logic here.
    LogUtility.Log("some message");
}

public static void Log()
{
    try
    {
        // Actual logging here.
    }
    catch (Exception ex)
    {
        // Eat it. Logging failures shouldn't stop us from processing.
    }
}

Wenn Sie hier keine allgemeine Ausnahme abfangen, müssen Sie alle möglichen Arten von Ausnahmen abfangen. Patrick hat einen guten Punkt, der OutOfMemoryExceptionnicht auf diese Weise behandelt werden sollte. Was ist, wenn ich jede Ausnahme ignorieren möchte OutOfMemoryException?

Bob Horn
quelle
12
Was ist OutOfMemoryException? Gleicher Code wie alles andere?
Patrick
@ Patrick Guter Punkt. Ich habe meiner Frage ein neues Beispiel hinzugefügt, um Ihre Frage abzudecken.
Bob Horn
1
Allgemeine Ausnahmen abzufangen ist ungefähr so ​​schlimm wie allgemeine Aussagen darüber zu machen, was jeder tun sollte. Es gibt im Allgemeinen keinen einheitlichen Ansatz für alles.
4
@ Patrick das wäre OutOfMemoryError, die aus Exceptiondiesem Grund von der Erbschaft Baum getrennt ist
Darkhogg
Was ist mit Tastaturausnahmen wie Strg-Alt-Entf?
Mawg

Antworten:

33

Diese Regeln sind im Allgemeinen eine gute Idee und sollten daher befolgt werden.

Denken Sie jedoch daran, dass dies allgemeine Regeln sind. Sie decken nicht alle Situationen ab. Sie decken die häufigsten Situationen ab. Wenn Sie eine bestimmte Situation haben und argumentieren können, dass Ihre Technik besser ist (und Sie in der Lage sein sollten, einen Kommentar in den Code zu schreiben, um Ihr Argument dafür zu artikulieren), tun Sie dies (und lassen Sie es dann einer Peer-Review unterziehen).

Auf der Gegenseite des Arguments.

Ich sehe Ihr Beispiel oben nicht als eine gute Situation dafür. Wenn das Protokollierungssystem ausfällt (vermutlich eine andere Ausnahme), möchte ich wahrscheinlich nicht, dass die Anwendung fortgesetzt wird. Beenden und drucken Sie die Ausnahme in der Ausgabe, damit der Benutzer sehen kann, was passiert ist.

Martin York
quelle
2
Concur. Ganz am wenigsten jetzt , dass regelmäßige Protokollierung offline eine Art von Sorge getragen , dass die geben würden eine Art von Debug - Ausgaben, sonst wäre nichts STDERR.
Shadur
6
Ich habe Sie beide positiv bewertet, aber ich denke, Sie denken wie Entwickler, nicht wie Benutzer. Einem Benutzer ist es im Allgemeinen egal, ob eine Protokollierung stattfindet, solange die Anwendung verwendbar ist.
Mawg
1
Interessant, da log4net die App explizit nicht stoppen möchte, nur weil die Protokollierung fehlschlägt. Und ich denke, es hängt davon ab, was Sie protokollieren. Sicherheitsüberprüfungen beenden den Prozess. Aber Debug-Protokolle? Nicht so wichtig.
Andy
1
@ Andy: Ja, alles hängt davon ab, was du tust.
Martin York
2
Warum verstehst du sie nicht? Und sollten Sie nicht danach streben?
Mawg
31

Ja, allgemeine Ausnahmen zu erwischen ist eine schlechte Sache. Eine Ausnahme bedeutet normalerweise, dass das Programm nicht das tun kann, was Sie von ihm verlangt haben.

Es gibt ein paar Arten von Ausnahmen , die Sie könnten handhaben :

  • Schwerwiegende Ausnahmen : Nicht genügend Arbeitsspeicher, Stapelüberlauf usw. Eine übernatürliche Kraft hat gerade Ihr Universum durcheinander gebracht und der Prozess ist bereits im Sterben. Sie können die Situation nicht verbessern, also geben Sie einfach auf
  • Ausnahmefehler aufgrund von Fehlern im verwendeten Code : Versuchen Sie nicht, diese zu beheben, sondern beheben Sie die Ursache des Problems. Verwenden Sie keine Ausnahmen für die Flusskontrolle
  • Ausnahmesituationen : Behandeln Sie Ausnahmen nur in diesen Fällen. Hier können wir einschließen: Netzwerkkabel abgezogen, Internetverbindung funktioniert nicht mehr, fehlende Berechtigungen usw.

Oh, und in der Regel: Wenn Sie nicht wissen, was Sie mit einer Ausnahme tun sollen, wenn Sie sie abfangen, ist es besser, einfach schnell zu scheitern (übergeben Sie die Ausnahme an den Anrufer und lassen Sie ihn damit umgehen)

Victor Hurdugaci
quelle
1
Was ist mit dem konkreten Fall in der Frage? Wenn der Protokollierungscode einen Fehler enthält, ist es wahrscheinlich in Ordnung, die Ausnahme zu ignorieren, da der tatsächlich wichtige Code davon nicht betroffen sein sollte.
Svick
4
Warum nicht stattdessen den Fehler im Protokollcode beheben?
Victor Hurdugaci
3
Victor, es ist wahrscheinlich kein Fehler. Wenn auf dem Datenträger, auf dem sich das Protokoll befindet, nicht mehr genügend Speicherplatz zur Verfügung steht, ist dies ein Fehler im Protokollierungscode?
Carson63000
4
@ Carson63000 - na ja. Die Protokolle werden daher nicht geschrieben: Bug. Implementieren Sie rotierende Protokolle mit fester Größe.
Detly
5
Dies ist die beste Antwort, aber es fehlt ein entscheidender Aspekt: Sicherheit . Es gibt einige Ausnahmen, die dadurch entstehen, dass die Bösen versuchen, Ihr Programm zu verbessern. Wenn eine Ausnahme ausgelöst wird, die Sie nicht verarbeiten können, können Sie diesem Code nicht unbedingt mehr vertrauen. Niemand hört gerne, dass sie den Code geschrieben haben, der die Bösen
hereinlässt
15

Die oberste äußere Schleife sollte eine davon haben, um alles zu drucken, was sie kann, und dann einen schrecklichen, gewalttätigen und lauten Tod sterben (da dies nicht passieren sollte und jemand hören muss).

Andernfalls sollten Sie im Allgemeinen sehr vorsichtig sein, da Sie höchstwahrscheinlich nicht mit allem gerechnet haben, was an diesem Ort passieren könnte, und daher höchstwahrscheinlich nicht richtig damit umgehen werden. Sei so genau wie möglich, damit du nur diejenigen fängst, von denen du weißt, dass sie passieren werden, und lass diejenigen, die du nicht gesehen hast , bis zum oben erwähnten lauten Tod hochsprudeln.


quelle
1
Ich stimme dem theoretisch zu. Aber was ist mit meinem obigen Protokollierungsbeispiel? Was ist, wenn Sie Protokollierungsausnahmen einfach ignorieren und fortfahren möchten? Müssen Sie jede Ausnahme abfangen, die ausgelöst werden könnte, und mit jeder dieser Ausnahmen umgehen, während die schwerwiegendere Ausnahme in die Luft sprudelt?
Bob Horn
6
@ BobHorn: Zwei Betrachtungsweisen. Ja, Sie können sagen, dass die Protokollierung nicht besonders wichtig ist. Wenn sie fehlschlägt, sollte Ihre App nicht angehalten werden. Und das ist fair genug. Aber was ist, wenn Ihre Anwendung fünf Monate lang nicht protokolliert wurde und Sie keine Ahnung hatten? Ich habe gesehen, dass das passiert ist. Und dann brauchten wir die Protokolle. Katastrophe. Ich würde vorschlagen, alles zu tun, was Sie sich vorstellen können, um das Fehlschlagen der Protokollierung zu stoppen, anstatt es zu ignorieren, wenn dies der Fall ist. (Aber darüber werden Sie sich nicht einig sein.)
09.09.12
@pdr In meinem Protokollierungsbeispiel würde ich normalerweise eine E-Mail-Benachrichtigung senden. Oder wir verfügen über Systeme zur Überwachung von Protokollen. Wenn ein Protokoll nicht aktiv ausgefüllt wird, wird unser Support-Team benachrichtigt. Daher wurden wir auf andere Weise auf das Problem der Protokollierung aufmerksam.
Bob Horn
@BobHorn Ihr Logging Beispiel ist eher gekünstelt - die meisten Logging Frameworks ich kenne, gehen auf große Länge nicht alle Ausnahmen werfen und nicht so aufgerufen werden würde (wie es würde jeder machen „log - Anweisung in Zeile X passiert in Datei Y“ nutzlos )
@pdr Ich habe in der Rückmeldeliste (Java) die Frage aufgeworfen, wie das Protokollierungsframework die Anwendung anhalten soll, wenn die Protokollierungskonfiguration fehlschlägt, einfach weil es so wichtig ist, dass wir die Protokolle haben und ein unbeaufsichtigter Fehler nicht akzeptabel ist. Eine gute Lösung steht noch aus.
9

Es ist nicht so, dass es schlecht ist, es ist nur so, dass bestimmte Fänge besser sind. Wenn Sie spezifisch sind, bedeutet dies, dass Sie konkreter verstehen, was Ihre Anwendung tut, und mehr Kontrolle darüber haben. Im Allgemeinen, wenn Sie auf eine Situation stoßen, in der Sie nur eine Ausnahme abfangen, diese protokollieren und fortfahren, gibt es wahrscheinlich einige schlechte Dinge, die sowieso vor sich gehen. Wenn Sie speziell die Ausnahmen abfangen, von denen Sie wissen, dass sie ein Codeblock oder eine Codemethode auslösen kann, ist die Wahrscheinlichkeit höher, dass Sie sie tatsächlich wiederherstellen können, anstatt nur zu protokollieren und auf das Beste zu hoffen.

Ryan Hayes
quelle
5

Die beiden Möglichkeiten schließen sich nicht aus.

In einer idealen Situation würden Sie alle möglichen Arten von Ausnahmen abfangen, die Ihre Methode generieren könnte, diese auf Ausnahmebasis behandeln und am Ende eine allgemeine catchKlausel hinzufügen , um zukünftige oder unbekannte Ausnahmen abzufangen. Auf diese Weise erhalten Sie das Beste aus beiden Welten.

try
{
    this.Foo();
}
catch (BarException ex)
{
    Console.WriteLine("Foo has barred!");
}
catch (BazException ex)
{
    Console.WriteLine("Foo has bazzed!");
}
catch (Exception ex)
{
    Console.WriteLine("Unknown exception on Foo!");
    throw;
}

Denken Sie daran, dass Sie die genaueren Ausnahmen zuerst eingeben müssen, um sie zu erfassen.

Bearbeiten: Aus Gründen, die in den Kommentaren angegeben sind, wurde im letzten Fang ein erneuter Wurf hinzugefügt.

Rotem
quelle
2
Warten. Warum sollten Sie jemals eine unbekannte Ausnahme protokollieren, um zu trösten und fortzufahren? Wenn es sich um eine Ausnahme handelt, von der Sie nicht einmal wussten, dass sie vom Code ausgelöst werden könnte, handelt es sich wahrscheinlich um einen Systemfehler. In diesem Szenario weitermachen ist wahrscheinlich eine wirklich schlechte Idee.
pdr
1
@ pdr Sicher ist dir klar, dass es ein erfundenes Beispiel ist. Es ging darum, das Fangen spezifischer und allgemeiner Ausnahmen zu demostrieren und nicht, wie man damit umgeht.
Rotem
@Rotem Ich denke du hast hier eine gute Antwort. Aber pdr hat einen Punkt. Mit dem Code sieht es so aus, als würde man fangen und weitermachen. Ein Anfänger, der dieses Beispiel sieht, könnte denken, dass dies ein guter Ansatz ist.
Bob Horn
Erfunden oder nicht, es macht Ihre Antwort falsch. Sobald Sie anfangen, Ausnahmen wie "Out of Memory" und "Disk Full" abzufangen und sie nur zu verschlucken, beweisen Sie, warum das Abfangen allgemeiner Ausnahmen in Wirklichkeit schlecht ist.
pdr
1
Wenn Sie eine allgemeine Ausnahme nur zum Protokollieren abfangen, sollten Sie sie nach der Protokollierung erneut auslösen.
Victor Hurdugaci
5

Ich habe das gleiche kürzlich erwogen, und meine vorläufige Schlussfolgerung ist, dass die bloße Frage entsteht, weil die .NET-Ausnahmehierarchie stark durcheinander ist.

Nehmen wir zum Beispiel den Lowly, ArgumentNullExceptionder möglicherweise ein vernünftiger Kandidat für eine Ausnahme ist, die Sie nicht abfangen möchten, da er eher auf einen Fehler im Code als auf einen legitimen Laufzeitfehler hinweist. Ah ja. Abgesehen davon NullReferenceException, dass NullReferenceExceptiondies SystemExceptiondirekt erfolgt, gibt es keinen Bereich, in den Sie alle "logischen Fehler" einfügen können, um zu fangen (oder nicht zu fangen).

Dann gibt es den großen IMNSHO- Pfusch, SEHExceptionAbleiten (via ExternalException) zu haben SystemExceptionund es so zu einem "normalen" zu machen.SystemException Wenn Sie ein erhaltenSEHException, möchten Sie einen Dump schreiben und so schnell wie möglich beenden - und mit .NET 4 beginnen, zumindest einige SEH-Ausnahmen gelten als Ausnahmen für beschädigte Zustände , die nicht erfasst werden. Eine gute Sache und eine Tatsache, die dieCA1031Regel noch nutzloser macht, denn jetzt wird Ihr Faulercatch (Exception)diese schlimmsten Typen sowieso nicht fangen.

Dann scheint es, dass das andere Framework-Zeug entweder Exceptiondirekt oder über etwas inkonsistent abgeleitet wird SystemException, was jeden Versuch unternimmt, Catch-Klauseln nach so etwas wie Severity Moot zu gruppieren.

Es gibt ein Stück von Herrn Lippert mit dem C#Titel Vexing Exception , in dem er eine nützliche Kategorisierung von Ausnahmen vorstellt : Sie könnten argumentieren, dass Sie nur "exogene" abfangen möchten, außer ... C#der Sprache und dem Design von .NET Rahmenausnahmen machen es unmöglich, "nur exogene zu fangen". (und beispielsweise ein OutOfMemoryExceptionmöglicherweise sehr gut ein ganz normaler behebbarer Fehler für eine API, die Puffer zuzuweisen hat , die irgendwie groß sind)

Fazit für mich ist, dass die Art C#und WeiseCA1031 , wie Catch-Blöcke funktionieren und wie die Framework-Ausnahmehierarchie entworfen ist, Regel jenseits von total nutzlos ist . Es gibt vor , bei der Grundfrage zu helfen: "Keine Ausnahmen verschlucken", aber das Verschlucken von Ausnahmen hat nichts mit dem zu tun, was Sie abfangen, sondern mit dem, was Sie dann tun:

Es gibt mindestens vier Möglichkeiten , um mit einem Fang legitim umzugehen Exception, und es CA1031scheint , als würde nur eine davon oberflächlich behandelt (nämlich der Fall des erneuten Werfens).


Als Randnotiz gibt es eine C # 6-Funktion namens Ausnahmefilter , die die CA1031Gültigkeit wieder etwas erhöht , da Sie in der Lage sind, die Ausnahmen, die Sie abfangen möchten, richtig und richtig zu filtern, und es gibt weniger Gründe, ungefiltert zu schreiben catch (Exception).

Martin Ba
quelle
1
Ein Hauptproblem dabei OutOfMemoryExceptionist, dass es keinen netten Weg gibt, wie Code sicher sein kann, dass er "nur" den Fehler einer bestimmten Zuordnung anzeigt, für die ein Fehler vorbereitet wurde. Es ist möglich, dass eine andere schwerwiegendere Ausnahme ausgelöst wurde und OutOfMemoryExceptionwährend des Abwickelns des Stapels von dieser anderen Ausnahme ein aufgetreten ist. Java mag mit seinen "try-with-resources" -Versuchen zu spät zu der Party gekommen sein, aber es behandelt Ausnahmen während des Abwickelns des Stacks ein bisschen besser als .NET.
Supercat
1
@supercat - das stimmt, aber das gilt so ziemlich für alle anderen allgemeinen Systemausnahmen, bei denen in einem der finalen Blöcke etwas kaputt geht.
Martin Ba
1
Das stimmt, aber man kann (und sollte im Allgemeinen) finallyBlöcke vor Ausnahmen schützen , von denen man realistisch erwarten kann, dass sie so auftreten, dass sowohl die ursprünglichen als auch die neuen Ausnahmen protokolliert werden. Leider erfordert dies häufig eine Speicherzuweisung, die zu eigenen Fehlern führen kann.
Supercat
4

Pokemon Ausnahmebehandlung (ich muss sie alle fangen!) Ist sicherlich nicht immer schlecht. Wenn Sie eine Methode einem Client, insbesondere einem Endbenutzer, zur Verfügung stellen, ist es häufig besser, alles und jeden zu erfassen, als Ihre Anwendung zum Absturz zu bringen und zu brennen.

Im Allgemeinen sollten sie jedoch vermieden werden, wo Sie können. Sofern Sie keine spezifischen Maßnahmen basierend auf dem Typ der Ausnahme ergreifen können, ist es besser, sie nicht zu behandeln und zuzulassen, dass die Ausnahme in die Luft sprudelt, anstatt die Ausnahme zu verschlucken oder sie falsch zu behandeln.

Schauen Sie sich diese SO-Antwort an, um mehr darüber zu lesen.

Tom Squires
quelle
1
Diese Situation (wenn ein Entwickler ein Pokemon-Trainer sein muss) tritt auf, wenn Sie eine gesamte Software selbst erstellen: Sie haben die Ebenen, Datenbankverbindungen und die Benutzeroberfläche erstellt. Ihre App muss sich von Situationen erholen, in denen die Konnektivität verloren gegangen ist, der Ordner des Benutzers gelöscht wurde, Daten beschädigt wurden usw. Endbenutzer mögen keine Apps, die abstürzen und brennen. Sie mögen Apps, die auf einem brennenden, explodierenden, abstürzenden Computer funktionieren können!
Broken_Window
Ich hatte bis jetzt noch nicht darüber nachgedacht, aber in Pokemon wird allgemein angenommen, dass Sie durch "alle fangen" genau eines von jedem wollen und es spezifisch fangen müssen, was das Gegenteil der gebräuchlichen Verwendung dieser Phrase ist unter Programmierern.
Magus
2
@Magus: Mit einer Methode wie dieser LoadDocument()ist es im Grunde unmöglich, alle Fehler zu identifizieren, aber 99% der Ausnahmen, die ausgelöst werden könnten, bedeuten einfach "Es war nicht möglich, den Inhalt einer Datei mit dem angegebenen Namen als zu interpretieren ein Dokument, damit umgehen. " Wenn jemand versucht, etwas zu öffnen, das keine gültige Dokumentdatei ist, sollte dies die Anwendung nicht zum Absturz bringen und keine anderen geöffneten Dokumente löschen. Pokemon Fehlerbehandlung in solchen Fällen ist hässlich, aber ich kenne keine guten Alternativen.
Supercat
@supercat: Ich habe gerade einen sprachlichen Punkt gemacht. Ungültige Dateiinhalte klingen jedoch nicht nach etwas, das mehr als eine Art von Ausnahme auslösen sollte.
Magus
1
@Magus: Es kann alle möglichen Ausnahmen auslösen - das ist das Problem. Es ist oft sehr schwierig, alle Arten von Ausnahmen zu antizipieren, die als Folge ungültiger Daten in einer Datei ausgelöst werden könnten. Wenn Sie die PokeMon-Behandlung nicht verwenden, besteht die Gefahr, dass eine Anwendung abbricht, da z. B. die geladene Datei eine außergewöhnlich lange Ziffernfolge an einer Stelle enthielt, die eine dezimal formatierte 32-Bit-Ganzzahl erforderte, und bei der ein numerischer Überlauf auftrat die Parsing-Logik.
Supercat
1

Das Abfangen einer allgemeinen Ausnahme ist schlecht, da Ihr Programm dadurch in einem undefinierten Zustand bleibt. Sie wissen nicht, wo etwas schief gelaufen ist, und wissen nicht, was Ihr Programm tatsächlich getan hat oder nicht getan hat.

Wenn ich ein Programm schließe, kann ich alles abfangen. Solange Sie es in Ordnung aufräumen können. Nichts ist so ärgerlich wie ein Programm, das Sie schließen, und das nur einen Fehlerdialog auslöst, der nichts anderes tut, als dort zu sitzen, nicht zu verschwinden und den Computer daran zu hindern, herunterzufahren.

In einer verteilten Umgebung kann Ihre Protokollmethode nach hinten losgehen: Wenn Sie eine allgemeine Ausnahme abfangen, kann dies bedeuten, dass Ihr Programm die Protokolldatei weiterhin sperrt und andere Benutzer daran hindert, Protokolle zu erstellen.

Pieter B
quelle
0

Ich verstehe die Gründe für diese Regel. Aber wenn ich in der Praxis unabhängig von der ausgelösten Ausnahme die gleiche Aktion ausführen möchte, warum sollte ich dann jede einzelne speziell behandeln?

Wie andere gesagt haben, ist es wirklich schwierig (wenn nicht unmöglich), sich eine Aktion vorzustellen, die Sie unabhängig von der ausgelösten Ausnahme ausführen möchten. Nur ein Beispiel sind Situationen, in denen der Status des Programms beschädigt wurde und jede weitere Verarbeitung zu Problemen führen kann (dies ist der Grund dafür Environment.FailFast).

Was passiert, wenn sich der von mir aufgerufene Code ändert, um in Zukunft eine neue Ausnahme auszulösen, wenn ich bestimmte Ausnahmen behandle? Jetzt muss ich meinen Code ändern, um diese neue Ausnahme zu behandeln. Wobei sich mein Code nicht ändern muss, wenn ich einfach Exception erwischt habe.

Für Hobby-Code ist es in Ordnung, ihn zu fangen Exception, aber für professionellen Code, der einen neuen Ausnahmetyp einführt, sollte er mit dem gleichen Respekt behandelt werden wie eine Änderung der Methodensignatur, dh, er gilt als brechende Änderung. Wenn Sie diesen Standpunkt abonnieren, ist es sofort offensichtlich, dass das Ändern (oder Überprüfen) des Client-Codes die einzig richtige Vorgehensweise ist.

Wenn Foo beispielsweise Bar aufruft und Foo die Verarbeitung unabhängig von der Art der von Bar ausgelösten Ausnahmebedingung beenden muss, hat es dann einen Vorteil, die Art der Ausnahmebedingung zu bestimmen, die ich abfange?

Sicher, denn Sie werden nicht nur Ausnahmen abfangen, die von Ihnen geworfen werden Bar. Es wird auch Ausnahmen geben, die die Clients von Bar oder sogar die Laufzeit während der Zeit Barauf dem Aufrufstapel auslösen können. Ein gut geschriebener BarBenutzer sollte bei Bedarf einen eigenen Ausnahmetyp definieren, damit der Aufrufer die von ihm selbst ausgegebenen Ausnahmen gezielt abfangen kann.

Was ist, wenn ich jede Ausnahme außer OutOfMemoryException ignorieren möchte?

IMHO ist dies der falsche Weg, um über die Ausnahmebehandlung nachzudenken. Sie sollten mit Whitelists arbeiten (Ausnahmetypen A und B abfangen), nicht mit Blacklists (alle Ausnahmen mit Ausnahme von X abfangen).

Jon
quelle
Es ist häufig möglich, eine Aktion anzugeben, die für alle Ausnahmen ausgeführt werden soll, die darauf hinweisen, dass ein versuchter Vorgang fehlgeschlagen ist und keine Nebenwirkungen oder nachteilige Auswirkungen auf den Zustand des Systems hat. Wenn ein Benutzer beispielsweise eine Dokumentdatei zum Laden auswählt, übergibt ein Programm seinen Namen an eine Methode zum Erstellen eines Dokuments mit Daten aus einer Festplattendatei. Diese Methode schlägt aus einem bestimmten Grund fehl, den die Anwendung nicht erwartet hatte (aber welche) Wenn die oben genannten Kriterien erfüllt sind, sollte die Meldung "Dokument kann nicht geladen werden" angezeigt werden, anstatt die Anwendung zum Absturz zu bringen.
Supercat
Leider gibt es keine Standardmethode, mit der eine Ausnahme angeben kann, was der Client-Code am wichtigsten wissen möchte - ob dies einen negativen Einfluss auf den Systemstatus hat, der über die Unfähigkeit hinausgeht, die angeforderte Operation auszuführen. Selbst wenn also Situationen, in denen alle Ausnahmen behandelt werden sollen, selten sind, gibt es viele Situationen, in denen viele Ausnahmen auf die gleiche Weise behandelt werden sollen, und es gibt kein Kriterium, das von allen solchen Ausnahmen erfüllt wird, das auch von einigen seltenen erfüllt würde sollte anders gehandhabt werden.
Supercat
0

Vielleicht . Es gibt Ausnahmen zu jeder Regel und keine Regel sollte unkritisch befolgt werden. Ihr Beispiel könnte möglicherweise einer der Fälle sein, in denen es sinnvoll ist, alle Ausnahmen zu verschlucken. Zum Beispiel, wenn Sie einem kritischen Produktionssystem eine Ablaufverfolgung hinzufügen und absolut sicher sein möchten, dass Ihre Änderungen die Hauptaufgabe der App nicht stören.

Allerdings sollten Sie sorgfältig über mögliche Gründe für das Scheitern denken , bevor Sie sich entscheiden, still , sie alle zu ignorieren. Was ist zum Beispiel, wenn der Grund für die Ausnahme ist:

  • Ein Programmierfehler in der Protokollierungsmethode, der dazu führt, dass immer eine bestimmte Ausnahme ausgelöst wird
  • Ein ungültiger Pfad zur Protokolldatei in der Konfiguration
  • Die Festplatte ist voll

Möchten Sie nicht sofort benachrichtigt werden, dass dieses Problem vorliegt, damit Sie es beheben können? Das Verschlucken der Ausnahme bedeutet, dass Sie nie wissen, dass etwas schief gelaufen ist.

Einige Probleme (z. B. der Datenträger ist voll) können auch dazu führen, dass andere Teile der Anwendung fehlschlagen. Dieser Fehler wird jedoch jetzt nicht protokolliert, sodass Sie es nie erfahren.

JacquesB
quelle
0

Ich möchte dies eher aus einer logischen als aus einer technischen Perspektive heraus ansprechen.

Jetzt muss ich meinen Code ändern, um diese neue Ausnahme zu behandeln.

Nun, jemand würde damit umgehen müssen. Das ist die Idee. Bei der Erstellung von Bibliothekscodes ist es jedoch ratsam, neue Ausnahmetypen hinzuzufügen, da dies wahrscheinlich zum Absturz von Clients führt. Dies sollte jedoch nicht häufig vorkommen.

Ihre Frage lautet im Grunde: "Was ist, wenn es mich nicht interessiert, was schief gelaufen ist? Muss ich wirklich die Mühe machen, herauszufinden, was es war?"

Hier ist der Beauty-Teil: Nein, tust du nicht.

"Also, kann ich einfach wegschauen und alles, was böse auftaucht, automatisch unter den Teppich kehren lassen und damit fertig sein?"

Nein, so funktioniert es auch nicht.

Der Punkt ist, die Sammlung möglicher Ausnahmen ist immer größer als die Sammlung, die Sie erwarten, und interessiert sich für den Kontext Ihres lokalen kleinen Problems. Sie behandeln die, die Sie erwarten, und wenn etwas Unerwartetes passiert, überlassen Sie es den übergeordneten Bearbeitern, anstatt es zu verschlucken. Wenn Sie sich nicht für eine Ausnahme interessieren, die Sie nicht erwartet haben, setzen Sie auf jemanden, der den Call-Stack aktiviert, und es wäre Sabotage, eine Ausnahme zu beenden, bevor sie ihren Handler erreicht.

"Aber ... aber ... dann könnte eine dieser anderen Ausnahmen, die mir egal sind, dazu führen, dass meine Aufgabe fehlschlägt!"

Ja. Aber sie werden immer wichtiger als die lokal gehandhabten. Wie ein Feueralarm oder der Chef, der dir sagt, du sollst aufhören, was du tust, und eine dringendere Aufgabe übernehmen, die auftaucht.

Martin Maat
quelle
-3

Sie sollten allgemeine Ausnahmen auf der obersten Ebene jedes Prozesses abfangen und diese behandeln, indem Sie den Fehler so gut wie möglich melden und dann den Prozess beenden.

Sie sollten keine allgemeinen Ausnahmen abfangen und versuchen, die Ausführung fortzusetzen.

ddyer
quelle