Ich arbeite als Auftragnehmer und entwerfe Java-Unternehmensanwendungen für meinen Kunden als technischer Leiter. Die Anwendung wird von Endbenutzern verwendet und es wird ein Support-Team geben, das die Anwendung unterstützt, wenn wir sie verlassen.
Die anderen technischen Leads, mit denen ich zusammenarbeite, haben den Eindruck, dass die Ausnahmebehandlung den Code verschmutzt. Das System sollte nur aktivierte Ausnahmen von der Serviceebene auslösen, und der Rest des Codes sollte Laufzeitausnahmen von allen anderen Ebenen auslösen, damit die nicht aktivierten Ausnahmen nicht behandelt werden müssen.
Was ist die Notwendigkeit, jemals eine ungeprüfte Ausnahme in einer Geschäftsanwendung auszulösen?
Aus meiner Erfahrung in der Vergangenheit über Laufzeitausnahmen:
1) Nicht aktivierte Ausnahmen machen den Code unvorhersehbar, da sie selbst im Javadoc nicht angezeigt werden.
2) Das Auslösen von nicht aktivierten Ausnahmen in einer Geschäftsanwendung ist nicht sinnvoll, da Sie dem Benutzer erklären, wenn Sie sie auslösen und sie direkt auf das Gesicht des Benutzers übertragen. Ich habe genug von Webanwendungen gesehen, die zeigen, 500 -Internal Error. Contact Administrator
was für einen Endbenutzer oder das Support-Team, das die Anwendung verwaltet, nichts bedeutet.
3) Durch das Auslösen von Laufzeitausnahmen werden die Benutzer der Klasse, die die Ausnahme auslösen, gezwungen, den Quellcode zu durchlaufen, um zu debuggen und festzustellen, warum die Ausnahme ausgelöst wird. Dies kann nur vermieden werden, wenn das Javadoc der Laufzeitausnahme hervorragend dokumentiert ist, was meiner Meinung nach niemals der Fall ist.
quelle
@throws
Tag dokumentieren. Dies ist übrigens eine gute Vorgehensweise.@throws
Tag, um jede nicht aktivierte Ausnahme zu dokumentieren, die eine Methode auslösen kann. Verwenden Sie jedoch nicht das Schlüsselwort throw, um nicht aktivierte Ausnahmen in die Methodendeklaration aufzunehmen.Antworten:
Überprüfte Ausnahmen sind ein fehlgeschlagener Ausdruck im Sprachdesign. Sie zwingen Sie zu extrem undichten Abstraktionen und schmutzigem Code. Sie sollten so weit wie möglich vermieden werden.
Wie für Ihre Punkte:
1) Überprüfte Ausnahmen machen den Code schmutzig und nicht weniger unvorhersehbar, da sie überall angezeigt werden .
2) Wie wird dem Benutzer eine aktivierte Ausnahme besser angezeigt? Der einzige wirkliche Unterschied zwischen aktivierten und nicht aktivierten Ausnahmen ist technischer Natur und betrifft nur den Quellcode.
3) Schon mal was von Stapelspuren gehört? Sie sagen Ihnen genau, wo die Ausnahme ausgelöst wurde, unabhängig davon, ob sie aktiviert oder deaktiviert ist. Tatsächlich sind geprüfte Ausnahmen beim Debuggen in der Regel schlechter, da sie häufig umbrochen werden, was zu längeren und hässlicheren Stapelspuren führt, oder sogar zusammen verloren gehen, weil das Umbrechen falsch durchgeführt wurde.
Es gibt zwei Arten von Ausnahmen: solche, die "normal" auftreten und normalerweise sehr nahe an ihrem Ort behandelt werden, und solche, die wirklich außergewöhnlich sind und generisch in einer sehr hohen Ebene behandelt werden können (brechen Sie einfach die aktuelle Aktion ab und protokollieren Sie sie /) Fehler anzeigen).
Überprüfte Ausnahmen waren ein Versuch, diese Unterscheidung an dem Punkt, an dem die Ausnahmen definiert sind, in die Sprachsyntax aufzunehmen. Die Probleme damit sind
quelle
SQLException extends Exception
bedeutet, dass die Auswahl eines Auslösers,SQLException
weil ein Fehler mit dem DB-Zugriff zu tun hat, automatisch bedeutet, dass die Ausnahme überprüft wird. Und Sie können ungeprüfte Ausnahmen in Javadoc-Kommentaren problemlos dokumentieren. Funktioniert gut für alle anderen Sprachen.Meiner Ansicht nach hängt es davon ab, was Ihr Code tut, welche Art von Ausnahme ausgelöst wird.
Ich werfe geprüfte Ausnahmen aus, wenn ich erwarte, dass sie ziemlich häufig auftreten können (z. B. Benutzer, die zweifelhafte Daten eingeben), und ich erwarte, dass der aufrufende Code die Situation behandelt.
Ich löse ungeprüfte / Laufzeitausnahmen (nicht so oft wie aktiviert), wenn ich eine seltene Situation habe, von der ich nicht erwarte, dass der aufrufende Code sie behandelt. Ein Beispiel könnte ein seltsamer speicherbezogener Fehler sein, von dem ich nie erwarte, dass er auftritt. Deaktiviert sind die Arten von Fehlern, von denen Sie erwarten, dass sie die Anwendung zum Absturz bringen.
Ohne Unterstützung sollte keine Ausnahme vor einem Benutzer angezeigt werden. Auch wenn es nur ein "Bitte schneiden Sie diesen Fehler-Dump aus und fügen Sie ihn in eine E-Mail ein". Nichts ist für einen Benutzer ärgerlicher, als wenn ihm mitgeteilt wird, dass ein Fehler vorliegt, aber keine Details oder Maßnahmen angegeben werden, die er ergreifen kann, um die Behebung des Fehlers einzuleiten.
Ich vermute, dass die von Ihnen erwähnte Philosophie aus einer von zwei Quellen stammt:
quelle
Wenn Sie keine ungeprüften Laufzeitausnahmen wünschen, warum verwenden Sie dann Java? Es gibt fast überall die Möglichkeit von Laufzeitausnahmen - insbesondere NullPointerException-, ArithmeticException-, ArrayIndexOutOfBounds-Ausnahmen usw.
Und wenn Sie einmal die Protokolldateien eines J2EE-Systems gelesen haben, wie zum Beispiel eine SAP NetWeaver-Installation, werden Sie feststellen, dass solche Ausnahmen buchstäblich immer auftreten.
quelle
Es gibt einige Regeln für die Ausnahmebehandlung, die Sie berücksichtigen sollten. Zunächst müssen Sie jedoch berücksichtigen, dass Ausnahmen Teil der vom Code bereitgestellten Schnittstelle sind . dokumentieren sie . Dies ist natürlich besonders wichtig, wenn es sich um eine öffentliche Schnittstelle handelt, aber auch bei privaten Schnittstellen ist dies eine sehr gute Idee.
Ausnahmen sollten nur an dem Punkt behandelt werden, an dem der Code etwas Sinnvolles damit anfangen kann. Die schlechteste Handhabungsoption besteht darin, überhaupt nichts dagegen zu unternehmen, was nur getan werden sollte, wenn dies genau die richtige Option ist. (Wenn ich eine solche Situation in meinem Code habe, füge ich einen entsprechenden Kommentar hinzu, damit ich mir keine Sorgen um den leeren Körper machen muss.)
Die zweitschlechteste Option besteht darin, eine nicht verwandte Ausnahme auszulösen, ohne dass das Original als Ursache beigefügt ist. Das Problem hierbei ist, dass die Informationen innerhalb der ursprünglichen Ausnahme, die die Diagnose des Problems ermöglichen würden, verloren gehen. Sie erstellen etwas, mit dem niemand etwas anfangen kann (außer sich darüber zu beschweren, dass „es nicht funktioniert“ und wir alle wissen, wie wir diese Fehlerberichte hassen ).
Viel besser ist es, die Ausnahme zu protokollieren. Auf diese Weise kann jemand herausfinden, wo das Problem liegt, und es beheben. Sie sollten die Ausnahme jedoch nur an dem Punkt protokollieren, an dem sie sonst verloren gehen oder über eine externe Verbindung gemeldet werden würde. Dies liegt nicht daran, dass die Protokollierung häufiger ein großes Problem darstellt, sondern daran, dass eine übermäßige Protokollierung bedeutet, dass das Protokoll nur mehr Speicherplatz beansprucht, ohne mehr Informationen zu enthalten. Sobald Sie die Ausnahme protokolliert haben, können Sie dem Benutzer / Client mit gutem Gewissen eine Précis melden (sofern Sie auch den Zeitpunkt der Generierung - oder eine andere Korrelationskennung - in diesen Bericht aufnehmen, damit die Kurzversion abgeglichen werden kann ggf. mit dem Detail).
Die beste Option ist natürlich, die Ausnahme vollständig zu behandeln und die Fehlersituation in ihrer Gesamtheit zu behandeln. Wenn Sie dies können, tun Sie es auf jeden Fall! Dies kann sogar bedeuten, dass Sie die Ausnahme nicht protokollieren müssen.
Eine Möglichkeit, eine Ausnahme zu behandeln, besteht darin, eine andere Ausnahme auszulösen, die eine übergeordnete Beschreibung des Problems enthält (z. B. "
failed to initialize
" anstelle von "index out of bounds
"). Dies ist ein gutes Muster, solange Sie nicht die Informationen über die Ursache der Ausnahme verlieren. Verwenden Sie die detaillierte Ausnahme, um die Ausnahmecause
der übergeordneten Ausnahme zu initialisieren oder das Detail zu protokollieren (wie oben erläutert). Die Protokollierung ist am besten geeignet, wenn Sie eine prozessübergreifende Grenze überschreiten möchten, z. B. einen IPC-Aufruf, da nicht garantiert werden kann, dass die Ausnahmeklasse auf niedriger Ebene überhaupt am anderen Ende der Verbindung vorhanden ist. Das Festhalten als angehängte Ursache ist am besten geeignet, wenn eine innere Grenze überschritten wird.Ein weiteres Muster, das Sie sehen, ist Catch-and-Release:
Dies ist ein Anti-Pattern, es sei denn, Sie haben Typeinschränkungen aus anderen
catch
Klauseln, die bedeuten, dass Sie die Ausnahme nicht einfach von alleine übergehen lassen können. Dann ist es nur eine hässliche Funktion von Java.Es gibt keinen wirklichen Unterschied zwischen aktivierten und nicht aktivierten Ausnahmen außer der Tatsache, dass Sie aktivierte Ausnahmen deklarieren müssen , die Methodengrenzen überschreiten. Es ist immer noch eine gute Idee, ungeprüfte Ausnahmen (mit dem
@throws
Javadoc-Kommentar) zu dokumentieren, wenn Sie wissen, dass sie absichtlich von Ihrem Code ausgelöst werden. Werfen Sie nicht absichtlichjava.lang.Error
oder seine Unterklassen (es sei denn, Sie schreiben eine JVM-Implementierung).Meinung: Ein unerwarteter Fehlerfall stellt immer einen Fehler in Ihrem Code dar. Überprüfte Ausnahmen sind eine Möglichkeit, diese Bedrohung zu verwalten. Wenn Entwickler absichtlich ungeprüfte Ausnahmen verwenden, um die Probleme bei der Behandlung von Fehlerfällen zu vermeiden, bauen Sie eine Menge technischer Schulden auf, die Sie einige Zeit bereinigen müssen Wenn Sie robusten Code wünschen. Eine schlampige Fehlerbehandlung ist unprofessionell (und die Fehlerbehandlung ist ein guter Weg, um festzustellen, wie gut ein Programmierer wirklich ist).
quelle
Ich denke, Sie sollten NUR eine aktivierte Ausnahme auslösen, wenn die Anwendung wiederhergestellt werden kann. Benutzer Ihrer Bibliothek müssen diese Ausnahmen abfangen und das tun, was sie zur Wiederherstellung benötigen. Alles andere sollte deaktiviert sein.
Als Beispiel:
Wenn Ihre App Daten entweder aus einer Datei oder einer Datenbank lädt. Dann,..
Der Aufrufer konnte immer die überprüfte MissingDataFileException abfangen und dann versuchen, die Daten aus der Datenbank zu laden.
quelle