Granularität von Ausnahmen

9

Ich bin in eine Debatte zwischen ein paar Freunden und mir geraten. Sie bevorzugen allgemeine Ausnahmen wie ClientErrorExceptionund ServerErrorExceptionmit Details als Ausnahmefelder, während ich es vorziehe, die Dinge spezifischer zu gestalten. Zum Beispiel könnte ich eine Handvoll Ausnahmen haben wie:

  • BadRequestException
  • AuthenticationFailureException
  • ProductNotFoundException

Jedes dieser Elemente basiert auf dem von der API zurückgegebenen Fehlercode.

Nach den Vorteilen von Ausnahmen erscheint dies Java idiomatisch. Die Meinung meiner Freunde ist jedoch nicht gerade ungewöhnlich.

Gibt es einen bevorzugten Weg in Bezug auf Code-Lesbarkeit und API-Benutzerfreundlichkeit oder kommt es wirklich nur auf die Präferenz an?


quelle
Die Seite, die Sie verlinkt haben, ist wahrscheinlich die beste endgültige Antwort, die wir bekommen können. Sie fragen wirklich nach einer Meinung. Ich kann mit meiner Erfahrung und Meinung antworten, aber das ist keine objektive Antwort.
Marstato
@ Marstato das ist fair. Ich denke, ich suche nach einer Rechtfertigung in meiner Position. Ich halte mich lieber an die Erwartungen der Leute in den Bibliotheken, die ich schreibe, als einem Leitfaden zu folgen, wenn dies bedeutet, dass meine Inhalte dadurch einfacher zu verwenden sind, wissen Sie?
Ich stimme absolut zu. Ich habe meine Ausnahmeklassen auch granular. Außerdem können Sie abstractmit den Getter-Methoden Ausnahmeklassen definieren und verallgemeinern und dann die granularen die allgemeinen erweitern lassen. ZB AuthenticationFaliureException extends ClientErrorException. Auf diese Weise kann jeder Benutzer auswählen, wie er mit den Ausnahmen umgehen möchte. Es funktioniert natürlich mehr. Beim Schreiben einer Anwendung (anstelle einer Bibliothek) ist dies meiner Meinung nach eine andere Situation. In diesem Fall würde ich die Ausnahmen der Einfachheit halber nicht detaillierter gestalten, als Sie sie benötigen.
Marstato
@marstato so implementiere ich es jetzt. Ich bin froh, dass du damit einverstanden bist. Ich werde die Frage über Nacht offen lassen, aber bitte konsolidieren Sie diese in einem Beitrag, damit ich Sie zumindest grün überprüfen kann

Antworten:

15

Der Hauptunterschied zwischen vielen verschiedenen Ausnahmeklassen und nur wenigen mit detaillierteren Informationen im Fehlertext (zum Beispiel) besteht darin, dass der aufrufende Code aufgrund vieler verschiedener Ausnahmeklassen unterschiedlich auf verschiedene Arten von Fehlern reagieren kann Nur wenige Klassen erleichtern es, alle Arten von Ausnahmen einheitlich zu behandeln.

Dies ist normalerweise ein Kompromiss. Es kann bis zu einem gewissen Grad durch Verwendung der Vererbung gemildert werden (eine allgemeine Basisausnahmeklasse für diejenigen Anrufer, die alles generisch abfangen und protokollieren möchten, und abgeleitete Ausnahmen von dieser Basisklasse für diejenigen Anrufer, die unterschiedliche Reaktionen benötigen), aber selbst das kann a erzeugen viel unnötige Komplexität, wenn Sie nicht vorsichtig sind und sich an das YAGNI-Prinzip halten. Die Leitfrage sollte also hier sein:

  • Erwarten Sie wirklich, dass der Aufrufer Ihres Codes unterschiedlich und mit unterschiedlichem Kontrollfluss auf diese unterschiedlichen Fehler reagiert?

Es gibt keine einheitliche Lösung für dieses Problem, keine "Best Practice", die Sie überall anwenden können. Die Antwort auf diese Frage hängt stark davon ab, welche Art von Software oder Komponente Sie entwerfen:

  • eine Anwendung, bei der Sie oder das Team die gesamte Codebasis unter Ihrer Kontrolle haben?

  • oder eine wiederverwendbare Komponente für Dritte, bei der Sie nicht alle potenziellen Anrufer kennen?

  • eine lange laufende Serveranwendung, bei der verschiedene Arten von Fehlern nicht sofort das gesamte System beschädigen sollten und möglicherweise verschiedene Arten der Fehlerminderung erfordern?

  • ein kurzlebiger Anwendungsprozess, bei dem es im Fehlerfall ausreicht, dem Benutzer eine Fehlermeldung anzuzeigen und den Prozess dann neu zu starten?

Je mehr Sie über die potenziellen Anrufer Ihrer Komponente wissen, desto besser können Sie sich für den richtigen Detaillierungsgrad für Ihre Ausnahmen entscheiden.

Doc Brown
quelle
3
"Erwarten Sie wirklich, dass der Aufrufer Ihres Codes unterschiedlich und mit unterschiedlichem Kontrollfluss auf diese unterschiedlichen Fehler reagiert?" Dies ist eine großartige Frage. Danke, ich werde mich daran erinnern.
Dies ist eine gute Antwort. Ich denke, ich möchte die Notwendigkeit, die Clientanwendung das Design für das Auslösen von Ausnahmen steuern zu lassen, nur noch weiter betonen. Selbst die Verallgemeinerungen, die Sie für sinnvoll halten, um sie in die Ausnahmehierarchie einzubauen, stimmen möglicherweise nicht mit der Art und Weise überein, in der Ihre Clientanwendung (wenn Sie sie nicht selbst schreiben) einen Handler verallgemeinern möchte. Wenn Sie mehr als eine Client-Anwendung mit unterschiedlichen Anforderungen haben, liegt es natürlich an Ihnen, diese auszugleichen.
Magicduncan
1

Die Antwort hängt davon ab, über welchen Grad der Fehlerberichterstattung wir sprechen.

Im Allgemeinen stimme ich Ihren Freunden zu, Sie sollten sie nicht detaillierter als nötig gestalten, um die Ursache des Problems zu vermitteln.

Wenn es eine allgemeine, bekannte Ausnahme für die Referenzierung von null gibt (NullReferenceException), sollten Sie keine eigene MyObjectIsNullException erstellen. Das würde den menschlichen Dolmetscher nur verwirren, eine zusätzliche Sache zu lernen, die nichts klarstellt.

Nur wenn Ihre Ausnahme so besonders ist, dass es keine vordefinierte gibt, die die Grundursache abdeckt, sollten Sie Ihre eigene erstellen.

Sie müssen hier jedoch nicht aufhören. Der häufig auftretende Fehler kann in einer Ihrer Komponenten auftreten, und Sie möchten möglicherweise mitteilen, dass in Ihrer Komponente ein Problem aufgetreten ist . Also nicht nur was schief gelaufen ist sondern auch wo. Dann wäre es angebracht, die erste Ausnahme in eine MyComponentException zu verpacken. Das gibt Ihnen das Beste aus beiden Welten.

Zuerst wird klar sein, dass Ihre Komponente in Schwierigkeiten geraten ist. Bei einem unteren Hebel liegt die spezifische Ursache in der inneren Ausnahme.

Martin Maat
quelle
Das ist fair. Sie schlagen also vor, keine neue Ausnahme zu erfinden, wenn bereits eine gute existiert?
@rec Ja, weil jeder die vordefinierten bereits kennt. Dafür sind sie da.
Martin Maat