Frage

Soll ich fange Ausnahmen zur Protokollierung?

public foo(..)
{
   try
   {
     ...
   } catch (Exception ex) {
     Logger.Error(ex);
     throw;
   }
}

Wenn ich diese an der richtigen Stelle in jedem meiner Schichten (Data Access, Business und WebService) bedeutet dies die Ausnahme mehrmals angemeldet ist.

Ist es sinnvoll zu tun, wenn meine Schichten in separaten Projekten sind und nur die öffentlichen Schnittstellen try / catch in ihnen? Warum? Warum nicht? Gibt es einen anderen Ansatz, den ich verwenden könnte?

War es hilfreich?

Lösung

Auf jeden Fall nicht. Sie sollten den richtigen Platz zu behandeln die Ausnahme (tatsächlich etwas tun, wie Catch-and-not-rethrow) finden, und melden Sie es dann. Sie können und sollen den gesamten Stack-Trace natürlich sind, aber im Anschluss an Ihrem Vorschlag würde Wurf des Code mit Try-Catch-Blöcken.

Andere Tipps

Wenn Sie nicht die Ausnahme gehen zu ändern, sollten Sie nur auf der Ebene einzuloggen, wo Sie den Fehler behandeln gehen und es nicht erneut auslösen. Andernfalls wird Ihr Protokoll hat nur ein Bündel von „Rauschen“, 3 oder mehr von der gleichen Nachricht protokollierte, einmal auf jeder Ebene.

Meine beste Praxis ist:

  1. versuchen Nur / catch in öffentlichen Methoden (in der Regel, natürlich, wenn Sie für einen bestimmten Fehler sind Trapping würden Sie es überprüfen dort)
  2. log Nur in der UI-Ebene direkt vor den Fehler zu unterdrücken und Umleitung auf eine Fehlerseite / Form.

Die Faustregel ist, dass Sie nur eine Ausnahme fangen, wenn Sie tatsächlich etwas dagegen tun können. So an der Business oder Datenschicht, würden Sie nur die Ausnahme in Situation wie diese fangen:

            try
            {
                this.Persist(trans);
            }
            catch(Exception ex)
            {
                trans.Rollback();
                throw ex;
            }

My Business / Data Layer versucht, die Daten zu speichern - wenn eine Ausnahme erzeugt wird, werden alle Transaktionen zurückgerollt und die Ausnahme wird an die UI-Ebene gesendet

.

An der UI-Ebene können Sie einen gemeinsamen Exception-Handler implementieren:

Application.ThreadException + = new ThreadExceptionEventHandler (Application_ThreadException);

Welche dann kümmert sich um alle Ausnahmen. Es könnte die Ausnahme anmelden und dann eine benutzerfreundliche Antwort angezeigt werden:

    static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
    {
        LogException(e.Exception);
    }
    static void LogException(Exception ex)
    {
        YYYExceptionHandling.HandleException(ex,
            YYYExceptionHandling.ExceptionPolicyType.YYY_Policy,
            YYYExceptionHandling.ExceptionPriority.Medium,
            "An error has occurred, please contact Administrator");
    } 

In dem aktuellen UI-Code, können Sie einzelne Ausnahme ist fangen, wenn Sie etwas anderes tun will -. Wie eine andere freundliche Nachricht anzuzeigen oder den Bildschirm ändern, usw.

Auch nur als Erinnerung, versuchen immer Fehler zu behandeln - zum Beispiel Division durch 0 -. Eher als eine Ausnahme zu werfen

Es ist eine gute Übung ist es, Ausnahmen übersetzen . Sie log sie nicht nur. Wenn Sie den bestimmten Grund eine Ausnahme ausgelöst wurde wissen wollen, werfen spezifische Ausnahmen:

public void connect() throws ConnectionException {
   try {
       File conf = new File("blabla");
       ...
   } catch (FileNotFoundException ex) {
       LOGGER.error("log message", ex);
       throw new ConnectionException("The configuration file was not found", ex);
   }
}

Verwenden Sie Ihre eigenen Ausnahmen inbuild Ausnahme zu wickeln. Auf diese Weise können verschiedene zwischen bekannten und unbekannten Fehler, wenn Ausnahme zu kontrollieren. Dies ist nützlich, wenn Sie eine Methode, die andere Methoden aufruft, die wahrscheinlich excpetions reagieren auf erwartete und unerwartete Ausfälle

werfen

Sie Standardausnahmebehandlung Stile Nachschlag mögen, aber mein Verständnis ist dies:. Behandelt Ausnahmen auf der Ebene, wo Sie zusätzliche Details zur Ausnahme hinzufügen können, oder auf der Ebene, wo Sie die Ausnahme für den Anwender werden

in Ihrem Beispiel Sie nichts tun, um die Ausnahme, sondern fing, Protokollierung, und es erneut zu werfen .. warum nicht einfach mit einer try / catch auf höchstem Niveau zu fangen, anstatt innerhalb jeder Methode, wenn alles, was Sie tun, ist die Anmeldung es?

würde ich es nur in dieser Ebene behandeln, wenn Sie einige nützlichen Informationen zu der Ausnahme hinzufügen wollen, bevor sie wieder zu werfen - wickelt die Ausnahme in einer neuen Ausnahme erstellen Sie, dass nützliche Informationen über den niedrige Niveau Ausnahmetext hat, die in der Regel bedeutet, wenig jemand ohne einen Kontext ..

Manchmal müssen Sie Daten protokollieren, die nicht verfügbar ist, wo die Ausnahme behandelt wird. In diesem Fall ist es angebracht, nur um zu protokollieren, dass die Informationen, um aus.

Zum Beispiel (Java Pseudo-Code):

public void methodWithDynamicallyGeneratedSQL() throws SQLException {
    String sql = ...; // Generate some SQL
    try {
        ... // Try running the query
    }
    catch (SQLException ex) {
        // Don't bother to log the stack trace, that will
        // be printed when the exception is handled for real
        logger.error(ex.toString()+"For SQL: '"+sql+"'");
        throw ex;  // Handle the exception long after the SQL is gone
    }
}

Dies ist ähnlich (meine Terminologie) auf rückwirkende Anmeldung, in dem Sie ein Protokoll der Ereignisse puffer, aber sie nicht schreiben, wenn es ein Triggerereignis ist, wie zum Beispiel eine Ausnahme ausgelöst wird.

Wenn Sie erforderlich sind alle Ausnahmen zu protokollieren, dann ist es eine fantastische Idee. Das heißt, ohne einen anderen Grund, alle Ausnahmen Anmeldung ist nicht so eine gute Idee ist.

Sie können auf höchstem Niveau protokollieren wollen, die in der Regel Code Ihrer Benutzeroberfläche oder Web-Service ist. mehrfach Protokollierung ist eine Art von Abfall. Außerdem möchten Sie die ganze Geschichte wissen, wenn Sie im Protokoll suchen.

In einem unserer Anwendungen, die alle unsere Seiten werden von einem Basepage Objekt abgeleitet, und diese Aufgabe übernimmt die Ausnahmebehandlung und Fehlerprotokollierung.

Wenn das ist das einzige, was sie tut, ich denke, ist besser, die try / catch die aus diesen Klassen zu entfernen und lassen Sie die Ausnahme von der Klasse erhoben werden, die für den Umgang mit ihnen verantwortlich ist. Auf diese Weise erhalten Sie nur ein Protokoll pro Ausnahme Ihnen freiere Protokolle geben und auch können Sie die Stacktrace melden Sie sich so wie Sie es sonst von verpassen, wo die Ausnahme entstanden war.

Meine Methode ist es, die Ausnahmen nur in der Prozedur zu protokollieren. Die ‚echten‘ Handler sozusagen. Andernfalls wird das Protokoll sehr schwer zu lesen und den Code weniger strukturiert.

Es hängt von der Ausnahme: Wenn das sollte eigentlich nicht passieren, ich würde es auf jeden Fall anmelden. Auf der anderen Art und Weise: Wenn Sie diese Ausnahme erwarten sollten Sie über das Design der Anwendung denken

.

So oder so: Sie sollten zumindest versuchen, die Ausnahme Sie erneut auslösen möchten, angeben, fangen oder log

.
public foo(..)
{
   try
   {
     ...
   }
   catch (NullReferenceException ex) {
     DoSmth(e);
   }
   catch (ArgumentExcetion ex) {
     DoSmth(e);
   }
   catch (Exception ex) {
     DoSmth(e);
   }
}

Sie wollen an einem Tier-Grenze protokollieren. Zum Beispiel kann, wenn Sie Ihr Business-Tier auf einer physisch getrennte Maschine in einer n-Tier-Anwendung eingesetzt wird, dann macht es Sinn, zu protokollieren und die Fehler auf diese Weise zu werfen.

Auf diese Weise haben Sie ein Protokoll der Ausnahmen auf dem Server und müssen nicht um Client-Maschinen gehen Stossen, um herauszufinden, was passiert ist.

Ich benutze dieses Muster in Geschäftsebenen-Anwendungen, das Remoting oder ASMX Web-Service nutzen. Mit WCF können Sie abfangen und eine Ausnahme log ein IErrorHandler an Ihren Channel (ein anderes Thema ganz) mit - so brauchen Sie nicht die try / catch / throw Muster

.

Sie müssen eine Strategie entwickeln, Ausnahmen für die Handhabung. Ich habe nicht den Fang und rethrow empfehlen. Neben den überflüssigen Protokolleinträge es der Code schwerer zu lesen macht. Betrachten Sie in das Protokoll im Konstruktor für die Ausnahme zu schreiben. Diese behält sich das try / catch Ausnahmen, die Sie von wiederherstellen möchten; wodurch der Code leichter zu lesen. Um mit unerwarteten oder nicht behebbare Ausnahmen, können Sie einen try / catch in der Nähe der äußersten Schicht des Programms wollen Diagnoseinformationen protokollieren.

BTW, wenn dies C ++ Ihr catch-Block eine Kopie des Ausnahmeobjekts schafft, die eine potentielle Quelle für zusätzliche Probleme sein kann. Versuchen Sie einen Verweis auf den Ausnahmetyp zu kontrollieren:

  catch (const Exception& ex) { ... }

Diese Software Engineering Radio-Podcast ist eine sehr gute Referenz für best Practices in der Fehlerbehandlung. Es gibt tatsächlich zwei Vorträge.

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