Frage

Ich habe einen Code, der einem Dienstprogramm eine Benutzer-ID gibt, das dann eine E-Mail an diesen Benutzer sendet.

emailUtil.sendEmail(userId, "foo");

public void sendEmail(String userId, String message) throws MailException {
    /* ... logic that could throw a MailException */
}

MailException kann aus verschiedenen Gründen ausgelöst werden: Probleme mit der E-Mail-Adresse, Probleme mit der E-Mail-Vorlage usw.

Meine Frage ist diese:Erstellen Sie für jede dieser Ausnahmen einen neuen Ausnahmetyp und behandeln Sie sie dann einzeln, oder erstellen Sie eine MailException und speichern Sie dann etwas in der Ausnahme (etwas Computerlesbares, nicht den Beschreibungstext), das es uns ermöglicht, verschiedene Dinge zu tun? basierend auf dem, was tatsächlich passiert ist.

Bearbeiten: Zur Klarstellung: Die Ausnahmen gelten nicht für Protokolle und ähnliches, sondern beziehen sich darauf, wie der Code darauf reagiert.Um mit dem E-Mail-Beispiel fortzufahren, nehmen wir an, dass das Versenden von E-Mails möglicherweise fehlschlägt, weil Sie keine E-Mail-Adresse haben, oder weil Sie keine haben gültig E-Mail-Adresse eingeben, sonst könnte es fehlschlagen.usw.

Mein Code möchte auf jedes dieser Probleme unterschiedlich reagieren (hauptsächlich durch Ändern der an den Client zurückgegebenen Nachricht, aber auch durch die tatsächliche Logik).

Wäre es am besten, für jedes dieser Probleme eine Ausnahmeimplementierung oder eine übergeordnete Ausnahme zu haben, die etwas Internes enthält (z. B. eine Aufzählung), das es dem Code ermöglicht, zu unterscheiden, um welche Art von Problem es sich handelt?

War es hilfreich?

Lösung

Normalerweise beginne ich mit einer allgemeinen Ausnahme und unterteile sie nach Bedarf.Ich kann bei Bedarf immer die allgemeine Ausnahme (und damit alle untergeordneten Ausnahmen) abfangen, aber auch die spezifischen.

Ein Beispiel aus der Java-API ist IOException, das Unterklassen wie FileNotFoundException oder EOFException (und viele mehr) hat.

Auf diese Weise profitieren Sie von den Vorteilen beider, es gibt keine Throw-Klauseln wie:

throws SpecificException1, SpecificException2, SpecificException3 ...

Ein General

throws GeneralException

reicht.Wenn Sie jedoch auf besondere Umstände besonders reagieren möchten, können Sie jederzeit die spezifische Ausnahme abfangen.

Andere Tipps

In meinem Code stelle ich fest, dass die MEISTEN Ausnahmen bis zu einer UI-Ebene vordringen, wo sie von meinen Ausnahmehandlern abgefangen werden, die dem Benutzer lediglich eine Nachricht anzeigen (und in das Protokoll schreiben).Es handelt sich schließlich um eine unerwartete Ausnahme.

Manchmal möchte ich eine bestimmte Ausnahme abfangen (wie Sie es anscheinend tun möchten).Sie werden jedoch wahrscheinlich feststellen, dass dies eher selten vorkommt und darauf hindeutet, dass Ausnahmen zur Steuerung der Logik verwendet werden – was ineffizient (langsam) ist und oft missbilligt wird.

Wenn Sie also in Ihrem Beispiel eine spezielle Logik ausführen möchten, wenn der E-Mail-Server nicht konfiguriert ist, möchten Sie möglicherweise eine Methode zum emailUtil-Objekt hinzufügen wie:

öffentlicher bool isEmailConfigured()

...Rufen Sie das zuerst auf, anstatt nach einer bestimmten Ausnahme zu suchen.

Wenn eine Ausnahme auftritt, bedeutet das in Wirklichkeit, dass die Situation völlig unerwartet war und der Code damit nicht umgehen kann. Das Beste, was Sie tun können, ist, sie dem Benutzer zu melden (oder sie in ein Protokoll zu schreiben oder neu zu starten).

Was eine Ausnahmehierarchie im Vergleich zu Ausnahmen mit Fehlercodes angeht, mache ich normalerweise Letzteres.Es ist einfacher, neue Ausnahmen hinzuzufügen, wenn Sie nur eine neue Fehlerkonstante statt einer ganz neuen Klasse definieren müssen.Aber es spielt keine große Rolle, solange Sie versuchen, während Ihres gesamten Projekts konsistent zu sein.

@Chris.Lively

Sie wissen, dass Sie in Ihrer Ausnahme eine Nachricht oder sogar die „Statuscodes“ übergeben können.Sie erfinden hier das Rad neu.

Ich habe festgestellt, dass Sie eine gut benannte Ausnahme erstellen müssen, die einen gemeinsamen Basistyp unterordnet, wenn CODE auf der Grundlage der zurückgegebenen Ausnahme entscheiden muss, was zu tun ist.Die übermittelte Botschaft sollte als „nur für menschliche Augen“ betrachtet werden und zu fragil, um Entscheidungen zu treffen.Lassen Sie den Compiler die Arbeit machen!

Wenn Sie dies über einen Mechanismus, der geprüfte Ausnahmen nicht kennt, an eine höhere Ebene weiterleiten müssen, können Sie es in eine geeignete benannte Unterklasse von RuntimeException (MailDomainException) einschließen, die hoch aufgeholt werden kann, und auf die ursprüngliche Ursache wird reagiert.

Es hängt davon ab, was Ihre Anwendung tut.Möglicherweise möchten Sie in solchen Fällen einzelne Ausnahmen auslösen

  • Die Anwendung ist hochverfügbar
  • Besonders wichtig ist der E-Mail-Versand
  • Der Umfang der Anwendung ist gering und das Versenden von E-Mails macht einen großen Teil davon aus
  • Die Anwendung wird auf einer Remote-Site bereitgestellt und Sie erhalten nur Protokolle zum Debuggen
  • Sie können einige Teilmengen der in der mailException gekapselten Ausnahmen wiederherstellen, andere jedoch nicht

In den meisten Fällen würde ich sagen, protokollieren Sie einfach den Text der Ausnahme und verschwenden Sie nicht Ihre Zeit damit, bereits ziemlich detaillierte Ausnahmen zu granularisieren.

Ich denke, eine Kombination der oben genannten Punkte wird Ihnen das beste Ergebnis liefern.

Je nach Problem können Sie unterschiedliche Ausnahmen auslösen.z.B.Fehlende E-Mail-Adresse = ArgumentException.

Dann kann man aber im UI-Layer den Ausnahmetyp und ggf. die Meldung prüfen und dem Benutzer dann eine entsprechende Meldung anzeigen.Ich persönlich neige dazu, dem Benutzer nur dann eine Informationsmeldung anzuzeigen, wenn eine bestimmte Art von Ausnahme ausgelöst wird (UserException in meiner App).Natürlich sollten Sie die Benutzereingaben so weit wie möglich weiter oben im Stapel bereinigen und überprüfen, um sicherzustellen, dass Ausnahmen durch wirklich unwahrscheinliche Szenarien generiert werden, und nicht als Filter für fehlerhafte E-Mails, die leicht mit einem regulären Ausdruck überprüft werden können.

Ich würde mir auch keine Sorgen über die Auswirkungen auf die Leistung machen, die das Abfangen einer Ausnahme aufgrund von Benutzereingaben mit sich bringt.Leistungsprobleme durch Ausnahmen treten nur dann auf, wenn sie ausgelöst und in einer Schleife oder ähnlichem gefangen werden.

Anstatt Ausnahmen zu verwenden, neige ich dazu, eine Liste von Statusobjekten von Methoden zurückzugeben, bei deren Ausführung möglicherweise Probleme auftreten.Die Statusobjekte enthalten eine Schweregradaufzählung (Information, Warnung, Fehler usw.), einen Statusobjektnamen wie „E-Mail-Adresse“ und eine vom Benutzer lesbare Meldung wie „Schlecht formatierte E-Mail-Adresse“.

Der aufrufende Code würde dann entscheiden, welche Filter auf die Benutzeroberfläche übertragen werden und welche selbst behandelt werden sollen.

Persönlich denke ich, dass Ausnahmen ausschließlich dann gelten, wenn Sie keine normale Codelösung implementieren können.Die Leistungseinbußen und Handhabungseinschränkungen sind mir einfach etwas zu viel.

Ein weiterer Grund für die Verwendung einer Liste von Statusobjekten besteht darin, dass die Identifizierung mehrerer Fehler (z. B. während der Validierung) VIEL einfacher ist.Schließlich können Sie nur eine Ausnahme auslösen, die behandelt werden muss, bevor Sie fortfahren können.

Stellen Sie sich vor, ein Benutzer sendet eine E-Mail mit einer fehlerhaften Zieladresse und einer Sprache, die Sie blockieren.Lösen Sie die fehlerhafte E-Mail-Ausnahme aus und lösen dann, nachdem das Problem behoben und erneut übermittelt wurde, eine Ausnahme wegen fehlerhafter Sprache aus?Aus Sicht der Benutzererfahrung ist es besser, alle auf einmal zu behandeln.

AKTUALISIEREN: Antworten kombinieren

@Jonathan:Mein Punkt war, dass ich die Aktion bewerten kann, in diesem Fall das Senden einer E-Mail, und mehrere Fehlergründe zurücksenden kann.Zum Beispiel „ungültige E-Mail-Adresse“, „leerer Nachrichtentitel“ usw.

Mit einer Ausnahme können Sie sich darauf beschränken, nur das eine Problem durchzusickern und den Benutzer dann um eine erneute Einreichung zu bitten, woraufhin er von einem zweiten Problem erfährt.Das ist wirklich schlechtes UI-Design.

Das Rad neu erfinden..möglicherweise.Allerdings sollten die meisten Anwendungen die gesamte Transaktion analysieren, um dem Benutzer die bestmöglichen Informationen zu liefern.Stellen Sie sich vor, Ihr Compiler stoppte beim ersten Fehler.Anschließend beheben Sie den Fehler und klicken erneut auf „Kompilieren“, nur um den Vorgang wegen eines anderen Fehlers erneut anzuhalten.Was für eine Nervensäge.Für mich ist das genau das Problem beim Auslösen von Ausnahmen und daher der Grund, warum ich gesagt habe, einen anderen Mechanismus zu verwenden.

Ich neige dazu, weniger Ausnahmetypen zu haben, obwohl dies nicht wirklich die OO-Methode ist.Stattdessen füge ich meinen benutzerdefinierten Ausnahmen eine Enumeration hinzu, die die Ausnahme klassifiziert.Meistens habe ich eine benutzerdefinierte Basisausnahme, die einige Mitglieder festhält, die in abgeleiteten Ausnahmetypen überschrieben oder angepasst werden können.

Vor ein paar Monaten habe ich gebloggt über die Idee, Ausnahmen zu internationalisieren.Es enthält einige der oben genannten Ideen.

Während Sie die Codeausführung anhand der Ausnahme unterscheiden können, spielt es keine Rolle, ob sie durch den „Catch-ExceptionType-Hierarchiemodus“ oder durch „if(...) else...Exception-Codemodus“ erfolgt.

Aber wenn Sie Software entwickeln, die von anderen Leuten verwendet wird, wie zum Beispiel eine Bibliothek, denke ich, dass es nützlich ist, Ihre eigenen Ausnahmetypen zu erstellen, um den anderen Leuten mitzuteilen, dass Ihre Software andere Ausnahmen als die normalen auslösen kann, und sie besser abfangen und lösen Sie sie.

Wenn ich eine Bibliothek verwende und deren Methoden einfach eine „Ausnahme“ auslösen, frage ich mich immer:Was kann diese Ausnahme verursachen? Wie muss mein Programm reagieren? Wenn es ein Javadoc gibt, wird vielleicht die Ursache erklärt, aber manchmal gibt es kein Javadoc oder die Ausnahme wird nicht erklärt.Zu viel Overhead kann mit einem WellChossenExceptionTypeName vermieden werden

Es hängt davon ab, ob der Code, der die Ausnahme abfängt, zwischen Ausnahmen unterscheiden muss oder ob Sie Ausnahmen nur verwenden, um zu einer Fehlerseite zu gelangen.Wenn Sie zwischen einer NullReference-Ausnahme und Ihrer benutzerdefinierten MailException weiter oben im Aufrufstapel unterscheiden müssen, nehmen Sie sich die Zeit und schreiben Sie sie.Meistens verwenden Programmierer Ausnahmen jedoch nur als Auffanglösung, um einen Fehler auf der Webseite auszulösen.In diesem Fall verschwenden Sie nur Ihre Mühe damit, eine neue Ausnahme zu schreiben.

Ich würde einfach vorbeigehen

throw new exception("WhatCausedIt")

Wenn Sie Ihre Ausnahmen behandeln möchten, können Sie anstelle von „WhatCausedIt“ einen Code übergeben und dann mit einer switch-Anweisung auf die unterschiedlichen Antworten reagieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top