Ich habe den Rat zu dieser Frage gelesen, wie eine Ausnahme so nahe wie möglich behandelt werden soll.
Mein Dilemma bei der Best Practice ist, ob man einen Versuch / Fang / Endlich verwenden sollte, um eine Aufzählung zurückzugeben (oder ein Int, das einen Wert darstellt, 0 für Fehler, 1 für OK, 2 für Warnung usw., je nach Fall), damit Eine Antwort ist immer in Ordnung, oder sollte man die Ausnahme durchlaufen lassen, damit der aufrufende Teil sich darum kümmert?
Soweit ich das beurteilen kann, kann dies je nach Fall unterschiedlich sein, sodass der ursprüngliche Rat seltsam erscheint.
Zum Beispiel möchten Sie bei einem Webdienst natürlich immer einen Status zurückgeben, sodass jede Ausnahme sofort behandelt werden muss. Nehmen wir jedoch an, Sie möchten in einer Funktion, die einige Daten über http veröffentlicht / abruft, die Ausnahme (zum Beispiel im Fall von 404), um nur zu dem zu gelangen, der es ausgelöst hat. Wenn Sie dies nicht tun, müssten Sie eine Möglichkeit erstellen, um den aufrufenden Teil über die Qualität des Ergebnisses (Fehler: 404) sowie über das Ergebnis selbst zu informieren.
Obwohl es möglich ist, die 404-Ausnahme innerhalb der Hilfsfunktion abzufangen, die die Daten abruft / veröffentlicht, sollten Sie dies tun? Ist es nur ich, der eine Smallint verwendet, um Zustände im Programm zu kennzeichnen (und sie natürlich angemessen zu dokumentieren) und diese Informationen dann für Zwecke der Überprüfung der geistigen Gesundheit (alles in Ordnung / Fehlerbehandlung) außerhalb zu verwenden?
Update: Ich hatte eine schwerwiegende / nicht schwerwiegende Ausnahme für die Hauptklassifizierung erwartet, wollte diese jedoch nicht einbeziehen, um die Antworten nicht zu beeinträchtigen. Lassen Sie mich klarstellen, worum es bei der Frage geht: Behandeln der ausgelösten Ausnahmen, nicht Auslösen von Ausnahmen. Was der gewünschte Effekt ist: Erkennen Sie einen Fehler und versuchen Sie, ihn zu beheben. Wenn eine Wiederherstellung nicht möglich ist, geben Sie das aussagekräftigste Feedback.
Beim Beispiel http get / post lautet die Frage erneut: Sollten Sie ein neues Objekt bereitstellen, das beschreibt, was mit dem ursprünglichen Anrufer passiert ist? Wenn sich dieser Helfer in einer Bibliothek befindet, die Sie verwenden, würden Sie erwarten, dass er Ihnen einen Statuscode für den Vorgang liefert, oder würden Sie ihn in einen Try-Catch-Block aufnehmen? Wenn Sie es entwerfen , würden Sie einen Statuscode angeben oder eine Ausnahme auslösen und die obere Ebene ihn stattdessen in einen Statuscode / eine Statusnachricht übersetzen lassen?
Synopsis: Wie wählen Sie aus, ob ein Code anstelle einer Ausnahme einen Statuscode zusammen mit den daraus resultierenden Ergebnissen zurückgibt?
quelle
Antworten:
Ausnahmen sollten für außergewöhnliche Bedingungen verwendet werden. Das Auslösen einer Ausnahme bedeutet im Grunde die Aussage: "Ich kann diese Bedingung hier nicht behandeln. Kann jemand weiter oben im Aufrufstapel dies für mich abfangen und damit umgehen?"
Die Rückgabe eines Wertes kann vorzuziehen sein, wenn klar ist, dass der Anrufer diesen Wert nimmt und etwas Sinnvolles daraus macht. Dies gilt insbesondere dann, wenn das Auslösen einer Ausnahme Auswirkungen auf die Leistung hat, dh in einer engen Schleife auftreten kann. Das Auslösen einer Ausnahme dauert viel länger als das Zurückgeben eines Werts (um mindestens zwei Größenordnungen).
Ausnahmen sollten niemals zur Implementierung der Programmlogik verwendet werden. Mit anderen Worten, werfen Sie keine Ausnahme, um etwas zu erledigen. eine Ausnahme auslösen, um anzugeben, dass dies nicht möglich ist.
quelle
Einige gute Ratschläge, die ich einmal gelesen habe, waren: Ausnahmen auslösen, wenn Sie angesichts des Status der Daten, mit denen Sie sich befassen, nicht weiterkommen können. Wenn Sie jedoch eine Methode haben, die eine Ausnahme auslösen kann, geben Sie nach Möglichkeit auch eine Methode an, um festzustellen, ob die Daten tatsächlich vorhanden sind gültig, bevor die Methode aufgerufen wird.
Beispielsweise löst System.IO.File.OpenRead () eine FileNotFoundException aus, wenn die angegebene Datei nicht vorhanden ist. Es wird jedoch auch eine .Exists () -Methode bereitgestellt, die einen booleschen Wert zurückgibt, der angibt, ob die Datei vorhanden ist, die Sie zuvor aufrufen sollten Aufruf von OpenRead (), um unerwartete Ausnahmen zu vermeiden.
Um den Teil der Frage zu beantworten, wann ich mich mit einer Ausnahme befassen soll, würde ich sagen, wo immer Sie tatsächlich etwas dagegen tun können. Wenn Ihre Methode eine Ausnahme, die von einer aufgerufenen Methode ausgelöst wird, nicht verarbeiten kann, fangen Sie sie nicht ab. Lassen Sie es die Anrufkette höher anheben, um etwas zu erreichen, das damit umgehen kann. In einigen Fällen ist dies möglicherweise nur ein Logger, der Application.UnhandledException abhört.
quelle
Das ist ein schreckliches Design. Maskieren Sie keine Ausnahme, indem Sie sie in einen numerischen Code übersetzen. Lassen Sie es als eine richtige, eindeutige Ausnahme.
Dafür gibt es Ausnahmen.
Ist überhaupt keine universelle Wahrheit. Manchmal ist es eine gute Idee. In anderen Fällen ist es nicht so hilfreich.
quelle
if
Anweisungen anstelle einer (manchmal) einfacheren Ausnahmebehandlung. Die Antwort ("Wie wählen Sie ...") ist einfach. Tu es nicht . Ich denke, dies zu sagen, trägt zum Gespräch bei. Sie können diese Antwort jedoch ignorieren.Ich stimme S.Lott zu . Je nach Situation kann es eine gute oder eine schlechte Idee sein, die Ausnahme so nah wie möglich an der Quelle abzufangen. Der Schlüssel zur Behandlung von Ausnahmen besteht darin, sie nur dann abzufangen, wenn Sie etwas dagegen tun können. Das Abfangen und Zurückgeben eines numerischen Werts an die aufrufende Funktion ist im Allgemeinen ein schlechtes Design. Sie möchten sie nur schweben lassen, bis Sie sich erholen können.
Ich betrachte die Ausnahmebehandlung immer als einen Schritt von meiner Anwendungslogik entfernt. Ich frage mich: Wenn diese Ausnahme ausgelöst wird, wie weit muss der Aufrufstapel gesichert werden, bevor sich meine Anwendung in einem wiederherstellbaren Zustand befindet? In vielen Fällen, wenn ich in der Anwendung nichts tun kann, um sie wiederherzustellen, kann dies bedeuten, dass ich sie erst auf der obersten Ebene abfange und nur die Ausnahme protokolliere, den Job fehlschlage und versuche, ihn sauber herunterzufahren.
Es gibt wirklich keine feste Regel, wann und wie die Ausnahmebehandlung eingerichtet werden soll, außer sie in Ruhe zu lassen, bis Sie wissen, was Sie mit ihnen tun sollen.
quelle
Ausnahmen sind schöne Dinge. Mit ihnen können Sie eine klare Beschreibung eines Laufzeitproblems erstellen, ohne auf unnötige Mehrdeutigkeiten zurückgreifen zu müssen. Ausnahmen können typisiert, untertypisiert und nach Typ behandelt werden. Sie können zur Verarbeitung an anderer Stelle weitergegeben werden. Wenn sie nicht verarbeitet werden können, können sie erneut angehoben werden, um auf einer höheren Ebene in Ihrer Anwendung behandelt zu werden. Sie kehren auch automatisch von Ihrer Methode zurück, ohne dass Sie eine Menge verrückter Logik aufrufen müssen, um mit verschleierten Fehlercodes umzugehen.
Sie sollten sofort nach dem Auftreten ungültiger Daten in Ihrem Code eine Ausnahme auslösen. Sie sollten Aufrufe anderer Methoden in einem try..catch..finally-Vorgang einschließen, um eventuell ausgelöste Ausnahmen zu behandeln. Wenn Sie nicht wissen, wie Sie auf eine bestimmte Ausnahme reagieren sollen, geben Sie sie erneut aus, um höheren Ebenen anzuzeigen, dass Es stimmt etwas nicht, das an anderer Stelle behandelt werden sollte.
Das Verwalten von Fehlercodes kann sehr schwierig sein. Normalerweise haben Sie viele unnötige Duplikate in Ihrem Code und / oder viele unübersichtliche Logik, um mit Fehlerzuständen umzugehen. Ein Benutzer zu sein und auf einen Fehlercode zu stoßen, ist noch schlimmer, da der Code selbst nicht aussagekräftig ist und dem Benutzer keinen Kontext für den Fehler liefert. Eine Ausnahme hingegen kann dem Benutzer etwas Nützliches mitteilen, z. B. "Sie haben vergessen, einen Wert einzugeben" oder "Sie haben einen ungültigen Wert eingegeben, hier ist der gültige Bereich, den Sie verwenden können ..." oder "Ich nicht" Wenn Sie wissen, was passiert ist, wenden Sie sich an den technischen Support und teilen Sie ihnen mit, dass ich gerade abgestürzt bin, und geben Sie ihnen die folgende Stapelverfolgung ... ".
Meine Frage an das OP lautet also, warum um alles in der Welt möchten Sie KEINE Ausnahmen für die Rückgabe von Fehlercodes verwenden?
quelle
Alles gute Antworten. Ich möchte auch hinzufügen, dass die Rückgabe eines Fehlercodes anstelle einer Ausnahme den Code des Anrufers komplizierter machen kann. Angenommen, Methode A ruft Methode B auf, ruft Methode C auf, und C stößt auf einen Fehler. Wenn C einen Fehlercode zurückgibt, muss B nun über eine Logik verfügen, um festzustellen, ob dieser Fehlercode verarbeitet werden kann. Wenn dies nicht möglich ist, muss es an A zurückgegeben werden. Wenn A den Fehler nicht behandeln kann, was tun Sie dann? Eine Ausnahme machen? In diesem Beispiel ist der Code viel sauberer, wenn C einfach eine Ausnahme auslöst, B die Ausnahme nicht abfängt, sodass er automatisch abgebrochen wird, ohne dass zusätzlicher Code erforderlich ist, und A bestimmte Arten von Ausnahmen abfangen kann, während andere den Anruf fortsetzen Stapel.
Dies erinnert an eine gute Regel zum Codieren durch:
quelle
Ich habe eine Kombination beider Lösungen verwendet: Für jede Validierungsfunktion übergebe ich einen Datensatz, den ich mit dem Validierungsstatus (einem Fehlercode) fülle. Wenn am Ende der Funktion ein Validierungsfehler vorliegt, wird eine Ausnahme ausgelöst. Auf diese Weise wird keine Ausnahme für jedes Feld ausgelöst, sondern nur einmal.
Ich habe auch den Vorteil genutzt, dass das Auslösen einer Ausnahme die Ausführung stoppt, da ich nicht möchte, dass die Ausführung fortgesetzt wird, wenn Daten ungültig sind.
Beispielsweise
Wenn Sie sich nur auf Boolesche Werte verlassen, sollte der Entwickler, der meine Funktion verwendet, Folgendes berücksichtigen:
aber er kann vergessen und nur anrufen
Validate()
(ich weiß, dass er nicht sollte, aber vielleicht könnte er).Im obigen Code habe ich also die beiden Vorteile erhalten:
quelle
Hier gibt es keine Antwort - so wie es keine einzige Art von HttpException gibt.
Es ist sehr sinnvoll, dass die zugrunde liegenden HTTP-Bibliotheken eine Ausnahme auslösen, wenn sie eine 4xx- oder 5xx-Antwort erhalten. Das letzte Mal, als ich mir die HTTP-Spezifikationen angesehen habe, waren das Fehler.
Was das Auslösen dieser Ausnahme - oder das Umschließen und erneute Auslösen - betrifft, denke ich, dass dies wirklich eine Frage des Anwendungsfalls ist. Wenn Sie beispielsweise einen Wrapper schreiben, um einige Daten aus der API abzurufen und für Anwendungen verfügbar zu machen, können Sie entscheiden, dass semantisch eine Anforderung für eine nicht vorhandene Ressource, die ein HTTP 404 zurückgibt, sinnvoller ist, diese abzufangen und null zurückzugeben. Andererseits kann ein 406-Fehler (nicht akzeptabel) einen Fehler wert sein, da sich dadurch etwas geändert hat und die App abstürzen und brennen und um Hilfe schreien sollte.
quelle