Frage

Ich habe den folgenden Code schon oft gesehen:

try
{
    ... // some code
}
catch (Exception ex)
{
    ... // Do something
    throw new CustomException(ex);

    // or
    // throw;

    // or
    // throw ex;
}

Können Sie bitte den Zweck des erneuten Auslösens einer Ausnahme erläutern?Folgt es einem Muster/Best Practice bei der Ausnahmebehandlung?(Ich habe irgendwo gelesen, dass es „Caller Inform“-Muster heißt?)

War es hilfreich?

Lösung

die gleiche Ausnahme Erneutes Auslösen ist nützlich, wenn Sie wollen, sagen wir, die Ausnahme einzuloggen, aber nicht damit umgehen.

Werfen Sie eine neue Ausnahme, die abgefangene Ausnahme wickelt für Abstraktion gut ist. zum Beispiel verwendet Ihre Bibliothek eine Drittanbieter-Bibliothek, die eine Ausnahme auslöst, dass die Kunden Ihrer Bibliothek nicht kennen sollten. In diesem Fall Sie es in einen Ausnahmetyp nativeren Ihre Bibliothek wickeln, und werfen, dass statt.

Andere Tipps

Eigentlich gibt es einen Unterschied zwischen

throw new CustomException(ex);

und

throw;

Die zweite wird die Stapelinformation erhalten.

Aber manchmal möchte man die Ausnahme mehr „freundlich“ zu Ihrer Anwendungsdomäne machen, anstatt dass die Database Ihre GUI erreichen, werden Sie Ihre benutzerdefinierte Ausnahme auslösen, die die ursprüngliche Ausnahme enthält.

Zum Beispiel:

try
{

}
catch (SqlException ex)
{
    switch  (ex.Number) {
        case 17:
        case 4060:
        case 18456:
           throw new InvalidDatabaseConnectionException("The database does not exists or cannot be reached using the supplied connection settings.", ex);
        case 547:
            throw new CouldNotDeleteException("There is a another object still using this object, therefore it cannot be deleted.", ex);
        default:
            throw new UnexpectedDatabaseErrorException("There was an unexpected error from the database.", ex);
    } 
}

Manchmal möchte man die Details der Implementierung eines Verfahrens verstecken oder verbessern die Ebene der Abstraktion eines Problems, so dass es sinnvoller für den Anrufer ein Verfahren. Um dies zu tun, können Sie die ursprüngliche Ausnahme abfangen und Ersatz eine benutzerdefinierte Ausnahme, die zur Erläuterung des Problems besser geeignet ist.

Nehmen Sie zum Beispiel ein Verfahren, das die gewünschten Benutzer Details aus einer Textdatei lädt. Das Verfahren geht davon aus, dass eine Textdatei mit der Benutzer-ID und dem Suffix „.data“ genannt existiert. Wenn diese Datei nicht tatsächlich existiert, macht es nicht viel Sinn, eine FileNotFoundException zu werfen, weil die Tatsache, dass jedes Details des Benutzers in einer Textdatei gespeichert werden, ist intern eine Implementierung Detail des Verfahrens. So könnte diese Methode anstelle wickelt die ursprüngliche Ausnahme in einer benutzerdefinierten Ausnahme mit einer erläuternden Mitteilung.

Im Gegensatz zu dem Code, der Sie gezeigt, beste Praxis ist, dass die ursprüngliche Ausnahme durch den Laden sie als die Innerexception-Eigenschaft der neuen Ausnahme gehalten werden soll. Dies bedeutet, dass ein Entwickler kann immer noch das zugrunde liegende Problem bei Bedarf analysieren.

Wenn Sie eine benutzerdefinierte Ausnahme erstellen, ist hier eine nützliche Checkliste:

• Finden Sie einen guten Namen, warum die Ausnahme ausgelöst wurde vermittelt und stellen Sie sicher, dass der Name mit dem Wort „Exception“ endet.

• Stellen Sie sicher, dass Sie den drei Standards Ausnahme Konstrukteuren implementieren.

• Stellen Sie sicher, dass Sie Ihre Ausnahme mit dem Attribut Serializable markieren.

• Stellen Sie sicher, dass Sie den Deserialisierungskonstruktor implementieren.

• benutzerdefinierte Ausnahme Eigenschaften hinzufügen, die Entwickler Ihre Ausnahme besser zu verstehen und zu handhaben könnte helfen.

• Wenn Sie benutzerdefinierte Eigenschaften hinzufügen, stellen Sie sicher, dass Sie bei der Implementierung und GetObjectData außer Kraft setzen Ihre benutzerdefinierten Eigenschaften serialisiert werden.

• Wenn Sie benutzerdefinierte Eigenschaften hinzufügen, die Message-Eigenschaft überschreiben, so dass Sie Ihre Eigenschaften zum Standardausnahmemeldung hinzufügen können.

• Denken Sie daran, die ursprüngliche Ausnahme mit der Innerexception-Eigenschaft der benutzerdefinierten Ausnahme befestigen.

Sie normalerweise fangen und wieder Wurf für einen von zwei Gründen, je nachdem, wo der Code sitzt architektonisch innerhalb einer Anwendung.

Im Kern einer Anwendung Sie in der Regel fangen und wieder wirft eine Ausnahme in etwas Sinnvolles zu übersetzen. Zum Beispiel, wenn Sie eine Datenzugriffsschicht gerade schreiben und mit benutzerdefinierten Fehlercodes mit SQL Server, können Sie SqlException in Dinge wie ObjectNotFoundException übersetzen. Dies ist nützlich, weil (a) es macht es einfacher für Anrufer bestimmte Arten von Ausnahme zu behandeln, und (b), weil sie Details der Implementierung dieser Schicht wie die Tatsache verhindert, sind Sie SQL Server für die Persistenz Verwendung in anderen Schichten undicht, die Damit können Sie die Dinge in Zukunft leichter ändern.

Bei Grenzen von Anwendungen ist es üblich, eine Ausnahme zu fangen und wieder werfen, ohne zu übersetzen, so dass Sie Details davon einloggen können, bei der Fehlersuche Unterstützung und Live-Probleme zu diagnostizieren. Im Idealfall möchten Sie Fehler irgendwo veröffentlichen, dass die Operations-Team leicht (zum Beispiel das Ereignisprotokoll) sowie irgendwo überwachen kann, die den Kontext gibt um, wo die Ausnahme für Entwickler in dem Steuerfluss passiert (in der Regel Tracing).

Ich kann aus folgenden Gründen denken:

  • Halten Sie den Satz von geworfen Ausnahmetypen festgelegt, als Teil der API, so dass die Anrufer nur über den festen Satz von Ausnahmen zu kümmern. In Java, Sie sind praktisch gezwungen, das zu tun, wegen des geprüften Ausnahmen Mechanismus.

  • einige Kontextinformationen Ausnahme hinzufügen. Zum Beispiel, statt den bloßen „Datensatz nicht gefunden“ im Stich gelassen von der DB passieren, können Sie es fangen und fügen Sie „... während der Verarbeitung um keine XXX, für das Produkt YYY suchen“.

  • einige Bereinigung tun -. Schließen von Dateien, Transaktionen Rollback, ein paar Griffe zu befreien

Im Allgemeinen geht es bei „etwas tun“ entweder darum, die Ausnahme besser zu erklären (z. B. sie in eine andere Ausnahme einzuschließen) oder Informationen über eine bestimmte Quelle zu verfolgen.

Eine andere Möglichkeit besteht darin, dass der Ausnahmetyp nicht genügend Informationen enthält, um zu wissen, ob eine Ausnahme abgefangen werden muss. In diesem Fall liefert das Abfangen und Untersuchen der Ausnahme weitere Informationen.

Das soll nicht heißen, dass die Methode aus rein guten Gründen verwendet wird. Oft wird sie verwendet, wenn ein Entwickler denkt, dass Tracing-Informationen zu einem späteren Zeitpunkt benötigt werden könnten. In diesem Fall erhalten Sie den Stil try {} Catch {throw;} überhaupt nicht hilfreich.

Ich denke, es hängt davon ab, was Sie versuchen, mit der Ausnahme, zu tun.

Ein guter Grund wäre, den Fehler zuerst in dem Fang protokollieren, und sie dann an den UI erbrechen eine freundliche Fehlermeldung mit der Option zu generieren einen „erweiterte / detaillierten“ Blick auf dem Fehler, um zu sehen, die enthalten der ursprüngliche Fehler.

Ein weiterer Ansatz ist ein „Wiederholungs“ -Ansatz, zB ein Fehlerzähler gehalten wird, und nach einer gewissen Menge an Wiederholungen, die die einzige Zeit ist, wird der Fehler, den Stapel gesendet (dies manchmal für den Datenbankzugriff erfolgt für Datenbank-Anrufe, Timeout, oder Web-Services über langsame Netzwerke Zugriff).

Es gibt eine Reihe von anderen Gründen, es zu tun though.

FYI, ist dies eine weitere Frage über jede Art von Wiederwurf: Leistungsüberlegungen für Ausnahmen

Werfen

Meine Frage konzentriert sich auf die „Warum“ wir wieder Ausnahmen werfen und seine Verwendung in der Anwendung der Ausnahmebehandlung Strategie.

Bis ich mit dem EntLib ExceptionBlock begann, war ich mit ihnen Fehler protokolliert, bevor sie zu werfen. Art böse, wenn Sie denken, dass ich sie an diesem Punkt betastet haben könnte, aber zu der Zeit war es besser, sie in UAT nastily hat fail (nach ihnen Anmeldung) statt decken einen Fluss auf Fehler.

Die Anwendung wird höchstwahrscheinlich diejenigen Wieder geworfen Ausnahmen höher den Call-Stack werden zu kontrollieren und so wieder zu werfen ermöglicht es ihnen, dass höher Handler sie gegebenenfalls abzufangen und zu verarbeiten. Es ist durchaus üblich für die Anwendung einen Top-Level-Exception-Handler zu haben, die protokolliert oder melden die Erwartungen.

Eine weitere Alternative ist, dass der Kodierer war faul und stattdessen nur den Satz von Ausnahmen fangen sie wollen sie alles gefangen zu handhaben sind und dann nur diejenigen wieder geworfen sie nicht wirklich umgehen kann.

Wie Rafal erwähnt, manchmal ist dies eine geprüfte Ausnahme auf eine ungeprüfte Ausnahme zu konvertieren getan, oder auf eine geprüfte Ausnahme, die für eine API besser geeignet ist. Es gibt hier ein Beispiel:

http://radio-weblogs.com/0122027 /stories/2003/04/01/JavasCheckedExceptionsWereAMistake.html

Wenn Sie auf Ausnahmen aus, als auf eine alternative Möglichkeit, ein Verfahren Ergebnis zu erhalten, dann wieder wirft eine Ausnahme ist wie Ihr Ergebnis in ein anderes Objekt gewickelt wird.

Und das ist ein üblicher Vorgang in einer nicht-außergewöhnlichen Welt. Normalerweise geschieht dies auf einer Grenze von zwei Anwendungsebenen - wenn eine Funktion von Schicht B eine Funktion aus Schicht C nennt, verwandelt C Ergebnis in B interne Form.

A -- calls --> B -- calls --> C

Wenn dies nicht der Fall, dann an der Schicht A die die Schicht nennt B wird es eine ganze Reihe von JDK Ausnahmen zu handhaben sein. : -)

Wie auch die akzeptierte Antwort weist darauf hin, Schicht A nicht einmal bewusst C die Ausnahme sein könnte.

Beispiel:

Schicht A , Servlet: ruft ein Bild und es ist Metainformationen
Layer B , JPEG-Bibliothek: sammelt verfügbar DCIM-Tags eine JPEG-Datei
analysieren Schicht C , ein einfaches DB: eine Klasse Lesestring Datensätze aus einer Random Access-Datei. Einige Bytes sind gebrochen, so dass es eine Ausnahme auslöst sagen.

"kann nicht UTF-8-String für record 'bibliographicCitation' lesen"

So A nicht die Bedeutung von 'bibliographicCitation' verstehen. So B sollte diese Ausnahme für A in TagsReadingException übersetzen, die die ursprünglichen einwickelt.

Der Hauptgrund der Wieder wirft Ausnahmen ist Call Stack unberührt zu lassen, so dass Sie vollständigeres Bild von dem, was geschieht, und ruft Folge.

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