28 Stimmen

Ist die Behandlung von Ausnahmen ein guter Weg?

Wir kämpfen mit einer Richtlinie zur korrekten Behandlung von Ausnahmen in unserer Anwendung. Hier sind unsere Ziele für sie (zusammengefasst):

  • Behandeln Sie nur bestimmte Ausnahmen.
  • Behandeln Sie nur Ausnahmen, die Sie korrigieren können
  • Nur einmal anmelden.

Wir haben eine Lösung gefunden, die eine generische anwendungsspezifische Ausnahme beinhaltet und in einem Stück Code wie folgt funktioniert:

try {
  // Do whatever
}
catch(ArgumentNullException ane)
{
  // Handle, optinally log and continue
}
catch(AppSpecificException)
{
  // Rethrow, don't log, don't do anything else
  throw;
}
catch(Exception e)
{
  // Log, encapsulate (so that it won't be logged again) and throw
  Logger.Log("Really bad thing", e.Message, e);
  throw new AppSpecificException(e)
}

Alle Ausnahmen werden protokolliert und dann in eine AppSpecificException umgewandelt, damit sie nicht erneut protokolliert werden. Schließlich erreicht sie den Event-Handler der letzten Instanz, der sich mit ihr befasst, wenn es sein muss.

Ich habe nicht so viel Erfahrung mit Ausnahmebehandlungsmustern... Ist dies ein guter Weg, um unsere Ziele zu lösen? Hat es irgendwelche großen Nachteile oder große rote Warnungen?

Anmerkung: Einer der Nachteile dabei ist, dass man nach dem ersten Catch die Möglichkeit verliert, eine bestimmte Ausnahme zu behandeln (wenn man eine Methode aufruft, die eine andere Methode aufruft, und die zweite Methode eine Ausnahme auslöst, kann man sie nicht behandeln), aber ich habe festgestellt, dass ich das nie auf irgendeine Weise gemacht habe ... Ich behandle Ausnahmen nur mit einer Ebene der Tiefe ...

61voto

John Saunders Punkte 159011

Wenn Sie die Ausnahme zu nahe am Zeitpunkt des ersten Auslösens protokollieren, wird nicht der gesamte Stack-Trace aufgezeichnet.

Handgriff Ausnahmen zu beheben, und zwar so nah wie möglich an dem Zeitpunkt, an dem sie ausgelöst wurden. Sammeln Sie so schnell wie möglich Informationen über den Kontext, in dem sie ausgelöst wurden. Lassen Sie aber zu, dass sich Ausnahmen bis zu dem Punkt ausbreiten, an dem sie tatsächlich behandelt werden können. Die Protokollierung ist eine letzte Möglichkeit der Behandlung, daher sollte sie in den äußeren Schichten der Anwendungssubsysteme stattfinden.

Damit dürfte eine anwendungsspezifische Ausnahme, die als Markierung verwendet wird, um eine Ausnahme nicht zu protokollieren, die eigentlich nicht hätte abgefangen werden dürfen, überflüssig sein.

6voto

Justin Punkte 82143

Protokollieren Sie keine Ausnahme und werfen Sie sie dann erneut aus - es liegt in der Verantwortung des Aufrufers, die von Ihnen erzeugten Ausnahmen zu behandeln und zu protokollieren.

Fangen Sie eine Ausnahme nur auf, um sie zu behandeln (z. B. um sie zu protokollieren), oder fügen Sie kontextspezifische Informationen hinzu.

0voto

OverLex Punkte 2441

Dies ist ein recht gängiger Ansatz zur Lösung des Problems der Ausnahmebehandlung (von spezifischer zu weniger spezifisch).

Denken Sie daran, dass eine allgemeine ApplicationSpecific Exception, die alles abfängt, was in dieser Anwendung/Methode passiert, keine gute Idee ist, wenn Sie bestimmte Probleme abfangen wollen. Versuchen Sie eventuell, sie mit spezifischeren Ausnahmen zu erweitern.

Das Auslösen von Ausnahmen ist gut, besser ist es, die Methode so zu deklarieren, dass sie bestimmte Ausnahmen auslöst und der Aufrufer sie behandeln kann. Auf diese Weise müssen Sie weniger Code erstellen und Sie können einige Kontrollen zentralisieren.

0voto

lestival Punkte 71

Erste Option zur Lösung des Stack-Trace-Problems:

class AppSpecificException : ApplicationException
{
    public string SpecificTrace { get; private set; }
    public string SpecificMessage { get; private set; }

    public AppSpecificException(string message, Exception innerException)
    {
        SpecificMessage = message;
        SpecificTrace = innerException.StackTrace;
    }

}

Ich musste ein Beispiel schreiben, um die Frage zu verstehen und das Stacktrace-Problem zu überprüfen, das ist der Code für mich, achten Sie auf die button2_click-Methode, schließlich meine Textbox zeigen den Absturz String und die Stacktrace:

    private String internalValue;

    private void Operation1(String pField)
    {
        if (pField == null) throw new ArgumentNullException("pField");
        internalValue = pField;
    }

    private void Operation2(Object pField)
    {
        if (pField == null) throw new ArgumentNullException("pField");
        internalValue = Convert.ToInt32(pField).ToString();
    }

    private void Operation3(String pField)
    {
        if (pField == null) throw new ArgumentNullException("pField");
        internalValue = pField;
        Operation2(-1);
    }

    /// <exception cref="AppSpecificException"><c>AppSpecificException</c>.</exception>
    private void button1_Click(object sender, EventArgs e)
    {
        try
        {
            Operation1("One");
            Operation2("Two");
            Operation3("Three");
            MessageBox.Show(internalValue);
        }
        catch (ArgumentNullException ex)
        {
            textBoxException.Text = ex.Message + (char) 13 + (char) 10 + ex.StackTrace;
        }
        catch (AppSpecificException ex)
        {
            //textBoxException.Text = ex.Message + (char)13 + (char)10 + ex.StackTrace;
            throw;
        }
        catch (Exception ex)
        {
            textBoxException.Text = ex.Message + (char)13 + (char)10 + ex.StackTrace;                    
            throw new AppSpecificException("crash", ex);
        }

    }

    private void button2_Click(object sender, EventArgs e)
    {
        try
        {
            button1_Click(sender, e);
        }
        catch (AppSpecificException ex)
        {
            textBoxException.Text = ex.SpecificMessage + (char) 13 + (char) 10 + ex.SpecificTrace;
        }
    }

0voto

Brian Punkte 24901

Versuchen Sie zu vermeiden, eine neue Exception zu erzeugen und erneut auszulösen, da das Auslösen einer Exception den Stack-Trace an die Stelle setzt, an der die Exception ausgelöst wurde. Machen Sie einfach einen einfachen Wurf. Siehe Zu viel Wiederverwendung im Blog von Eric Lippert.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X