Java-Ausnahmebehandlungs-Idiome ... wer hat recht und wie geht man damit um?

7

Ich habe momentan einen technischen Unterschied zu einem Bekannten. Kurz gesagt, es ist der Unterschied zwischen diesen beiden grundlegenden Arten der Java-Ausnahmebehandlung:

Option 1 (meins):

%Vor%

Option 2 (sein):

%Vor%

Sein Argument - nachdem ich umfangreiche Links über Benutzereingabeprüfung, Ausnahmebehandlung, Behauptungen und Verträge usw. verwendet hatte, um meinen Standpunkt zu bestätigen - ging auf Folgendes ein:

"Es ist ein gutes Modell. Ich habe es benutzt, seit ich und ein Freund von mir 1998 vor fast zehn Jahren damit angefangen haben. Sehen Sie sich das mal an und Sie werden sehen, dass wir Kompromisse zu den akademischen Argumenten gemacht haben macht viel Sinn. "

Hat jemand ein knock-down Argument dafür, warum Option 1 der richtige Weg ist?

    
Steven Huwig 04.03.2009, 05:00
quelle

11 Antworten

19

Wenn Sie eine switch-Anweisung haben, sind Sie weniger objektorientiert. Es gibt auch mehr Möglichkeiten für Fehler, eine " break; " -Anweisung zu vergessen und zu vergessen, einen Fall für Exception hinzuzufügen, wenn Sie eine neue Exception hinzufügen, die geworfen wird.

Ich finde auch, dass es viel besser lesbar ist, und es ist das Standard-Idiom, das alle Entwickler sofort verstehen werden.

Für meinen Geschmack ist die Menge an Kesselplatte, um die Methode Ihres Bekannten zu tun, die Menge an Code, die nichts mit der tatsächlichen Handhabung der Ausnahmen zu tun hat, inakzeptabel. Je mehr Standardcode um Ihre eigentliche Programmlogik herum vorhanden ist, desto schwieriger ist es, den Code zu lesen und zu pflegen. Und eine ungewöhnliche Sprache zu verwenden macht den Code schwieriger zu verstehen.

Aber der Deal Breaker ist, wie ich oben sagte, dass wenn Sie die aufgerufene Methode modifizieren, so dass sie ein zusätzliches Exception wirft, Sie automatisch wissen, dass Sie Ihren Code ändern müssen, weil er nicht kompiliert werden kann. Wenn Sie jedoch die Methode Ihres Bekannten verwenden und die aufgerufene Methode so ändern, dass eine neue Variante von AppException ausgelöst wird, weiß Ihr Code nicht, dass sich an dieser neuen Variante etwas ändert und Ihr Code kann im Stillen fehlschlagen, indem er einen unangemessenen Fehler herunterfährt. Bein handhaben. Dies setzt voraus, dass du dich daran erinnerst, einen Standard zu setzen, so dass es zumindest gehandhabt und nicht stillschweigend ignoriert wird.

    
Eddie 04.03.2009, 05:04
quelle
6
  • die Art und Weise, wie Option 2 codiert ist, wird jeder unerwartete Ausnahmetyp verschluckt! (Dies kann behoben werden, indem im Standardfall erneut geworfen wird, aber das ist wohl eine hässliche Sache - viel besser / effizienter, um es überhaupt nicht zu fangen)
  • Option 2 ist eine manuelle Wiederherstellung dessen, was Option 1 höchstwahrscheinlich unter der Haube tut, d.h. sie ignoriert die bevorzugte Syntax der Sprache, um ältere Konstrukte zu verwenden, die aus Gründen der Wartung und Lesbarkeit am besten vermieden werden. Mit anderen Worten, Option 2 erfindet das Rad neu, indem sie eine hässlichere Syntax verwendet als die Sprachkonstrukte.

klar, beide Wege arbeiten; Option 2 wird lediglich durch die modernere Syntax ersetzt, die von Option 1 unterstützt wird.

    
Steven A. Lowe 04.03.2009 05:22
quelle
4

Ich weiß nicht, ob ich einen Knockdown-Argument habe, aber die ersten Gedanken sind

  • Option 2 funktioniert, bis Sie versuchen, eine Exception abzufangen, die getCode () nicht implementiert.
  • Option 2 ermutigt den Entwickler, allgemeine Ausnahmen abzufangen. Dies ist ein Problem, denn wenn Sie keine case-Anweisung für eine bestimmte Unterklasse von AppException implementieren, wird der Compiler Sie nicht warnen. Natürlich könnte das gleiche Problem mit Option 1 auftreten, aber Option 1 aktiviert dies nicht aktiv.
hhafez 04.03.2009 05:04
quelle
4

Mit Option 1 hat der Aufrufer die Möglichkeit, genau auszuwählen, welche Ausnahme abgefangen werden soll und alle anderen zu ignorieren. Mit Option 2 muss der Aufrufer daran denken, alle nicht explizit abgefangenen Ausnahmen erneut zu werfen.

Außerdem gibt es eine bessere Selbstdokumentation mit Option 1, da die Methodensignatur genau angeben muss, welche Ausnahmen ausgelöst werden, und nicht nur eine einzige Ausnahme.

Wenn eine allumfassende AppException erforderlich ist, können die anderen Ausnahmetypen immer davon erben.

    
Kevin Lacquement 04.03.2009 05:05
quelle
3

Das Knock-down-Argument wäre, dass es die Kapselung bricht, da ich jetzt etwas über die Unterklasse der öffentlichen Schnittstelle von Exception wissen muss, um mit Ausnahmen umgehen zu können. Ein gutes Beispiel für diesen "Fehler" im JDK ist java.sql.SQLException, wobei die Methoden getErrorCode und getSQLState verfügbar gemacht werden.

    
jonathan.cone 04.03.2009 05:30
quelle
3

Es sieht so aus, als würden Sie in beiden Fällen Ausnahmen verwenden. Als allgemeine Regel versuche ich, Ausnahmen nur dann auszulösen, wenn beide der folgenden Bedingungen zutreffen:

  1. Eine unerwartete Bedingung ist aufgetreten, die hier nicht behandelt werden kann.
  2. Jemand wird sich um die Stapelverfolgung kümmern.

Wie wäre es mit einem dritten Weg? Sie könnten für den Fehlertyp enum verwenden und ihn einfach als Teil des Methodentyps zurückgeben. Verwenden Sie dazu beispielsweise Option<A> oder Either<A, B> .

Sie hätten beispielsweise:

%Vor%

und statt

%Vor%

Sie werden

haben %Vor%

Werfen / fangen ist ein bisschen wie goto / comefrom. Einfach zu missbrauchen. Siehe Go To Statement als schädlich. und Lazy Fehlerbehandlung

    
Apocalisp 04.03.2009 06:16
quelle
1

Ich denke, es hängt davon ab, in welchem ​​Umfang dies genutzt wird. Ich hätte sicherlich nicht "eine Ausnahme, um sie alle zu beherrschen", die von allem geworfen wird. Auf der anderen Seite, falls gibt es eine ganze Klasse von Situationen, die mit ziemlicher Sicherheit auf die gleiche Weise behandelt werden, aber Sie müssen möglicherweise zwischen ihnen unterscheiden für (sagen wir) Benutzer-Feedback-Zwecke, Option 2 würde Sinn machen nur für diese Ausnahmen . Sie sollten sehr eng gefasst sein - so dass, wo immer es Sinn macht, dass ein "Code" geworfen wird, sollte es wahrscheinlich sinnvoll sein, auch alle anderen zu werfen.

Der entscheidende Test für mich wäre: "Würde es jemals Sinn machen, ein AppException mit einem Code zu fangen, aber einen anderen Code nicht abgefangen zu lassen?" Wenn ja, sollten sie unterschiedliche Typen sein.

    
Jon Skeet 04.03.2009 06:23
quelle
1

Jede überprüfte Ausnahme ist eine, um, Ausnahme Bedingung, die muss behandelt werden, damit das Programmverhalten definiert wird. Es gibt keine Notwendigkeit, auf vertragliche Verpflichtungen einzugehen, und was auch immer, es ist eine einfache Frage der Sinnhaftigkeit. Sagen Sie, Sie fragen einen Ladenbesitzer, wie viel etwas kostet und es stellt sich heraus, dass der Artikel nicht zu verkaufen ist. Wenn Sie darauf bestehen, dass Sie für eine Antwort nur nicht negative Zahlenwerte akzeptieren, gibt es keine richtige Antwort, die Ihnen jemals zur Verfügung gestellt werden könnte. Dies ist der Punkt mit geprüften Ausnahmen. Sie möchten, dass eine Aktion ausgeführt wird (möglicherweise eine Antwort) und wenn Ihre Anfrage nicht sinnvoll durchgeführt werden kann, müssen Sie dies vernünftig planen. Dies sind die Kosten für das Schreiben von robustem Code.

Mit Option 2 verschleiern Sie die Bedeutung der Ausnahmebedingungen in Ihrem Code vollständig. Sie sollten verschiedene Fehlerbedingungen nicht in einer einzigen generischen AppException reduzieren, es sei denn, sie müssen nie anders behandelt werden. Die Tatsache, dass Sie auf getCode() verzweigen, deutet auf eine andere Sache hin. Verwenden Sie daher unterschiedliche Ausnahmen für verschiedene Ausnahmen.

Der einzige wirkliche Vorteil, den ich bei Option 2 sehen kann, ist die saubere Behandlung verschiedener Ausnahmen mit demselben Codeblock. Dieser nette Blogbeitrag spricht über dieses Problem mit Java. Dennoch ist dies ein Problem von Stil und Korrektheit, und Korrektheit gewinnt.

    
mustpax 04.03.2009 07:00
quelle
0

Ich würde Option 2 unterstützen, wenn es wäre:

%Vor%

Es ist ein bisschen hässlicher Syntax, aber die Fähigkeit, den gleichen Code für mehrere Ausnahmen (dh Fälle in einer Zeile) auszuführen, ist viel besser. Das einzige, was mich irritieren würde, ist die Erzeugung einer eindeutigen ID, wenn eine Ausnahme gemacht wird, und das System könnte definitiv verbessert werden.

    
qpingu 04.03.2009 05:27
quelle
0
  1. Unnötig müssen Sie den Code kennen und Konstanten für die Ausnahme deklarieren, die bei Verwendung der Option 1 abstrakt sein könnte.

  2. Die zweite Option wird (wie ich vermute) auf traditionell (als Option 1) geändert, wenn nur eine bestimmte Ausnahme zu erfassen ist. Daher sehe ich dort Inkonsistenz.

Nrj 04.03.2009 05:36
quelle
0

Benutze beides.

Der erste für die meisten Ausnahmen in Ihrem Code.

Die Sekunde für diese sehr "spezifischen" Ausnahmen, die Sie erstellt haben.

Kämpfe nicht mit kleinen Dingen wie dieser.

BTW 1. ist besser.

    
OscarRyz 04.03.2009 06:26
quelle

Tags und Links