MethodA ruft eine MethodB auf, die wiederum MethodC aufruft.
In MethodB oder MethodC gibt es KEINE Ausnahmebehandlung. In MethodA gibt es jedoch eine Ausnahmebehandlung.
In MethodC tritt eine Ausnahme auf.
Jetzt sprudelt diese Ausnahme zu MethodA, die sie entsprechend behandelt.
Was ist daran falsch?
Meiner Meinung nach wird ein Aufrufer irgendwann MethodB oder MethodC ausführen, und wenn in diesen Methoden Ausnahmen auftreten, was sich aus der Behandlung von Ausnahmen in diesen Methoden ergibt, die im Wesentlichen nur ein try / catch / finally-Block statt nur let sind sie sprudeln bis zum angerufenen?
Die Aussage oder der Konsens in Bezug auf die Ausnahmebehandlung lautet, dass ausgelöst werden muss, wenn die Ausführung aus diesem Grund nicht fortgesetzt werden kann - eine Ausnahme. Ich verstehe das. Aber warum nicht die Ausnahme weiter oben in der Kette abfangen, anstatt Try / Catch-Blöcke ganz unten zu haben?
Ich verstehe es, wenn Sie Ressourcen freisetzen müssen. Das ist eine ganz andere Sache.
quelle
try-catch
Block erforderlich .Result<T>
Typ implementieren (einen Typ, der entweder ein Ergebnis einer Berechnung oder einen Fehler speichert) und ihn von Ihren ansonsten auslösenden Funktionen zurückgeben. Das Übertragen eines Fehlers auf den Stapel würde das Lesen jedes Rückgabewerts, das Überprüfen, ob es sich um einen Fehler handelt, und das Zurückgeben eines Fehlers erfordern, wenn dies der Fall ist.Antworten:
Fangen Sie grundsätzlich keine Ausnahmen ab, es sei denn, Sie wissen, was Sie damit tun sollen. Wenn MethodC eine Ausnahme auslöst, aber MethodB keine sinnvolle Möglichkeit hat, damit umzugehen, sollte es der Ausnahme ermöglichen, sich auf MethodA zu verbreiten.
Die einzigen Gründe, warum eine Methode einen Fang- und Rückwurfmechanismus haben sollte, sind:
Anderenfalls führt das Abfangen von Ausnahmen auf der falschen Ebene dazu, dass der Code unbemerkt fehlschlägt, ohne dem aufrufenden Code (und letztendlich dem Benutzer der Software) eine nützliche Rückmeldung zu geben. Die Alternative, eine Ausnahme abzufangen und sie dann sofort erneut zu werfen, ist sinnlos.
quelle
try ... finally ...
, dann verwenden Sie das, nicht fangen und werfenLoadDataException
und fügen Sie die ursprünglichen Ausnahmedetails entsprechend Ihren Sprachfunktionen hinzu, damit zukünftige Betreuer die Ursache erkennen können, ohne einen Debugger anhängen und herausfinden zu müssen, wie das Problem reproduziert werden kann.Absolut gar nichts.
"Behandelt es angemessen" ist der wichtige Teil. Das ist der Kern der strukturierten Ausnahmebehandlung.
Wenn Ihr Code mit einer Ausnahme etwas "Nützliches" bewirken kann, versuchen Sie es. Wenn nicht, dann lass es gut sein.
Genau das sollten Sie tun. Wenn Sie Code lesen, der Handler / Rethrower "ganz unten" hat, dann lesen Sie [wahrscheinlich] ziemlich schlechten Code.
Leider sehen einige Entwickler Catch-Blöcke nur als "Boiler-Plate" -Code, den sie in jede Methode, die sie schreiben, einschleusen (kein Wortspiel beabsichtigt), oft, weil sie die Ausnahmebehandlung nicht wirklich "verstehen" und denken, dass sie etwas hinzufügen müssen dass Ausnahmen nicht "entkommen" und ihr Programm beenden.
Ein Teil der Schwierigkeit dabei ist, dass dieses Problem die meiste Zeit nicht einmal bemerkt wird, da Ausnahmen nicht die ganze Zeit geworfen werden, aber wenn dies der Fall ist , wird das Programm sehr viel Zeit und Zeit verschwenden Versuchen Sie nach und nach, die Auswahl des Aufrufstapels aufzuheben, um zu einem Punkt zu gelangen, der mit der Ausnahme tatsächlich etwas Nützliches bewirkt.
quelle
catch
auf der höchstmöglichen Ebene eine einzige vorhanden sein, die den Fehler protokolliert und eine Fehlerantwort zurückgibt. Nichtcatch
überall verstreute Blöcke. Wenn Sie nicht alle möglichen überprüften Ausnahmen (in Sprachen wie Java) auflisten möchten, schließen Sie sie einfach in ein ein,RuntimeException
anstatt sie dort zu protokollieren, fortzufahren und auf weitere Fehler oder sogar Schwachstellen zu stoßen.Sie müssen einen Unterschied zwischen Bibliotheken und Anwendungen machen.
Bibliotheken können unaufgefangene Ausnahmen frei werfen
Wenn Sie eine Bibliothek entwerfen, müssen Sie sich irgendwann Gedanken machen, was schief gehen kann. Parameter liegen möglicherweise im falschen Bereich oder
null
externe Ressourcen sind möglicherweise nicht verfügbar usw.Ihre Bibliothek wird meist nicht in der Lage sein , vernünftig mit ihnen umzugehen. Die einzig sinnvolle Lösung besteht darin, eine entsprechende Ausnahme auszulösen und den Entwickler der Anwendung damit zu beauftragen.
Bewerbungen sollten immer irgendwann Ausnahmen fangen
Wenn eine Ausnahme abgefangen wird, möchte ich sie entweder als Fehler oder als schwerwiegende Fehler kategorisieren . Ein regulärer Fehler bedeutet, dass ein einzelner Vorgang in meiner Anwendung fehlgeschlagen ist. Beispielsweise konnte ein geöffnetes Dokument nicht gespeichert werden, da das Ziel nicht beschreibbar war. Es ist nur sinnvoll, dass die Anwendung den Benutzer darüber informiert, dass der Vorgang nicht erfolgreich abgeschlossen werden konnte. Geben Sie für den Benutzer lesbare Informationen zum Problem und lassen Sie den Benutzer entscheiden, was als Nächstes zu tun ist.
Ein schwerwiegender Fehler ist ein Fehler, den die Hauptanwendungslogik nicht beheben kann. Wenn beispielsweise der Grafikgerätetreiber in einem Videospiel abstürzt, kann die Anwendung den Benutzer nicht ordnungsgemäß informieren. In diesem Fall sollte eine Protokolldatei geschrieben und der Benutzer nach Möglichkeit auf die eine oder andere Weise informiert werden.
Selbst in solch einem schwerwiegenden Fall sollte die Anwendung diese Ausnahme auf sinnvolle Weise behandeln. Dies kann das Schreiben einer Protokolldatei, das Senden eines Absturzberichts usw. umfassen. Es gibt keinen Grund, warum die Anwendung auf die Ausnahme in irgendeiner Weise nicht reagiert.
quelle
HDDPluggedOutDuringWritingException
kann ein Problem behandelt werden und ist für die Anwendung nicht schwerwiegend. Das Programm kann entscheiden, was damit geschehen soll.Was an dem von Ihnen beschriebenen Muster falsch ist, ist, dass Methode A nicht in der Lage ist, drei Szenarien zu unterscheiden:
Methode B schlug in vorweggenommener Weise fehl.
Methode C schlug in einer Weise fehl, die von Methode B nicht erwartet wurde, während Methode B jedoch eine Operation ausführte, die sicher abgebrochen werden konnte.
Methode C schlug in einer Weise fehl, die von Methode B nicht erwartet wurde, aber während Methode B eine Operation ausführte, die die Dinge in einen vermeintlich vorübergehenden inkohärenten Zustand versetzte, den B aufgrund des Fehlers von C nicht bereinigte.
Die einzige Möglichkeit, wie Methode A diese Szenarien unterscheiden kann, besteht darin, dass die von B geworfene Ausnahme Informationen enthält, die für diesen Zweck ausreichen, oder dass der Stapel, der für Methode B abgewickelt wird, das Objekt in einem explizit ungültig gemachten Zustand belässt . Leider machen die meisten Ausnahmeframeworks beide Muster umständlich, was Programmierer dazu zwingt, "weniger böse" Entwurfsentscheidungen zu treffen.
quelle