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?
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.
klar, beide Wege arbeiten; Option 2 wird lediglich durch die modernere Syntax ersetzt, die von Option 1 unterstützt wird.
Ich weiß nicht, ob ich einen Knockdown-Argument habe, aber die ersten Gedanken sind
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.
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.
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:
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
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.
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.
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.
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.
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.