So dokumentieren Sie ausgelöste Ausnahmen in c # /. Net

139

Ich schreibe derzeit ein kleines Framework, das intern von anderen Entwicklern im Unternehmen verwendet wird.

Ich möchte gute Intellisense-Informationen bereitstellen, bin mir jedoch nicht sicher, wie ausgelöste Ausnahmen dokumentiert werden sollen.

Im folgenden Beispiel:

public void MyMethod1()
{
    MyMethod2();

    // also may throw InvalidOperationException
}

public void MyMethod2()
{
    System.IO.File.Open(somepath...); // this may throw FileNotFoundException

    // also may throw DivideByZeroException
}

Ich weiß, dass das Markup für die Dokumentation von Ausnahmen lautet:

/// <exception cref="SomeException">when things go wrong.</exception>

Was ich nicht verstehe, ist, wie Ausnahmen dokumentiert werden, die durch den von aufgerufenen Code ausgelöst werdenMyMethod1() ?

  • Soll ich Ausnahmen dokumentieren, die von ausgelöst werden? MyMethod2()
  • Soll ich Ausnahmen dokumentieren, die von ausgelöst werden File.Open()?

Was wäre der beste Weg, um mögliche Ausnahmen zu dokumentieren?

Arnold Zokas
quelle
4
Ich weiß, dass dies nicht genau das ist, was Sie gefragt haben (und dies ist eine wirklich alte Frage), aber Eric Lippert (Hauptentwickler im Microsoft C # -Compiler und im Designteam) hat einen Blog-Beitrag über die 4 Arten von Ausnahmen geschrieben, von denen ich denke, dass jeder Entwickler sollte beim Schreiben von Ausnahmebehandlungscode darüber nachdenken
javajavajavajavajava
@javajavajavajavajava Danke für den Link - definitiv lesenswert.
Arnold Zokas
Ich denke, dies ist eine berechtigte Frage, da es überhaupt nicht offensichtlich ist, wie Ausnahmen in C # richtig dokumentiert werden sollen, und die 50K-Ansichten zeigen, dass dies auch für viele Leute nicht offensichtlich ist. Die zweithäufigste Antwort ist sehr hilfreich, da sie zeigt, dass vorhandene xmldocs verwendet werden, um dies zu dokumentieren. Abstimmung zur Wiedereröffnung. Dieser "meinungsbasierte" enge Grund tötet viele wirklich sehr nützliche Programmierfragen.
Alexei

Antworten:

110

Sie sollten jede Ausnahme dokumentieren, die von Ihrem Code ausgelöst wird, einschließlich derjenigen in Methoden, die Sie möglicherweise aufrufen.

Wenn die Liste etwas größer wird, möchten Sie möglicherweise Ihren eigenen Ausnahmetyp erstellen. Fangen Sie alle auf, auf die Sie in Ihrer Methode stoßen könnten, schließen Sie sie in Ihre Ausnahme ein und werfen Sie sie aus.

Ein anderer Ort, an dem Sie dies möglicherweise tun möchten, ist, wenn sich Ihre Methode auf der Vorderseite Ihrer API befindet. So wie eine Fassade mehrere Schnittstellen zu einer einzigen Schnittstelle vereinfacht, sollte Ihre API mehrere Ausnahmen zu einer einzigen Ausnahme vereinfachen. Erleichtert Anrufern die Verwendung Ihres Codes.


Um einige von Andrews Bedenken zu beantworten (aus den Kommentaren), gibt es drei Arten von Ausnahmen: Eine, von der Sie nichts wissen, die Sie kennen und gegen die Sie nichts tun können, und die, die Sie kennen und gegen die Sie etwas tun können.

Diejenigen, von denen Sie nichts wissen, wollen Sie loslassen. Es ist das Prinzip, schnell zu versagen - es ist besser, wenn Ihre App abstürzt, als in einen Zustand zu gelangen, in dem Sie möglicherweise Ihre Daten beschädigen. Der Absturz informiert Sie darüber, was passiert ist und warum. Dies kann dazu beitragen, diese Ausnahme aus der Liste "Diejenigen, von denen Sie nichts wissen" zu entfernen.

Diejenigen, die Sie kennen und gegen die Sie nichts tun können, sind Ausnahmen wie OutOfMemoryExceptions. In extremen Fällen möchten Sie vielleicht Ausnahmen wie diese behandeln, aber wenn Sie keine bemerkenswerten Anforderungen haben, behandeln Sie sie wie die erste Kategorie - lassen Sie sie los. Haben Sie haben auf diese Ausnahmen zu dokumentieren? Sie würden ziemlich dumm aussehen, OOMs für jede einzelne Methode zu dokumentieren, mit der ein Objekt neu erstellt wird.

Diejenigen, die Sie kennen und gegen die Sie etwas tun können, sollten Sie dokumentieren und verpacken.

Weitere Richtlinien zur Ausnahmebehandlung finden Sie hier.


quelle
3
Ich muss zugeben, das klingt nicht sehr praktisch. Ich kann mir nicht vorstellen, wie viele potenzielle Ausnahmen von einem von mir aufgerufenen Code ausgelöst werden können. Außerdem gibt es Dinge wie OutOfMemoryException, die Sie nicht abfangen und umschließen möchten.
Andrew Hare
3
Wird Ihre Antwort gut sein, aber es sind tatsächlich zwei Antworten, die sich widersprechen. "Dokumentieren Sie jede Ausnahme, die durch Ihren Code ausgelöst werden könnte" und "Diejenigen, die Sie kennen und gegen die Sie etwas tun können, sollten Sie dokumentieren".
Tymtam
2
@ Tymek: Nein. In der ersten Hälfte wurde die Frage "Wie soll ich Ausnahmen dokumentieren?" Beantwortet. Im zweiten Teil wurde die offensichtlich offensichtliche Antwort auf "Welche Ausnahmen soll ich dokumentieren?" Das erste bedeutet nicht, dass Sie jede Ausnahme dokumentieren, die möglicherweise jemals auftreten wird. Einige Leute sind zu wörtlich, was die zweite Hälfte erforderte.
5
@Tymek Ich denke, Ihr Punkt könnte sein, dass wenn Sie etwas dagegen tun können, warum nicht etwas dagegen tun, anstatt es neu zu werfen und zu dokumentieren? Es könnte wahrer sein zu sagen: "Diejenigen, von denen Sie wissen, dass der Client- Code etwas dagegen tun kann". Dies beseitigt den Widerspruch, da dies die idealen Ausnahmen für die Dokumentation sind.
mo.
Die Ausnahmen, die Sie loslassen, können Sie immer auf einer niedrigeren Ebene abfangen, die sie protokolliert, oder so. Wissen Sie; Nur eine benutzerfreundliche Methode, um das Programm zum Absturz zu bringen.
Nyerguds
96

Sie sollten die Standard-XML-Dokumentation verwenden .

/// <exception cref="InvalidOperationException">Why it's thrown.</exception>
/// <exception cref="FileNotFoundException">Why it's thrown.</exception>
/// <exception cref="DivideByZeroException">Why it's thrown.</exception>
public void MyMethod1()
{
    MyMethod2();
    // ... other stuff here
}

/// <exception cref="FileNotFoundException">Why it's thrown.</exception>
/// <exception cref="DivideByZeroException">Why it's thrown.</exception>
public void MyMethod2()
{
    System.IO.File.Open(somepath...);
}

/// <exception cref="FileNotFoundException">Why it's thrown.</exception>
public void MyMethod3()
{
    try
    {
        MyMethod2();
    }
    catch (DivideByZeroException ex)
    {
        Trace.Warning("We tried to divide by zero, but we can continue.");
    }
}

Der Wert auf diese Weise besteht darin, dass Sie die bekannten Ausnahmen dokumentieren, die auftreten können. Diese Dokumentation ist in Intellisense verfügbar, wenn Sie Visual Studio verwenden, und kann Sie (oder andere) später an die Ausnahmen erinnern, die Sie erwarten können.

Sie möchten die spezifischen Ausnahmetypen angeben, da Sie möglicherweise einen Ausnahmetyp behandeln können, während andere Typen das Ergebnis eines schwerwiegenden Problems sind und nicht korrigiert werden können.

Schüttelfrost42
quelle
1
Wie schafft das einen Mehrwert? Beispielsweise sind alle diese Ausnahmen Ableitungen vom Ausnahmetyp. Aus meiner Erfahrung wird es nicht praktisch sein, an jeden anderen Ausnahmetyp zu denken, der möglicherweise von den anderen APIs ausgelöst wird, die in Ihren Methoden aufgerufen werden. Mein Punkt ist, wir sollten uns keine Sorgen über Ausnahmen machen, die von einer Methode ausgelöst werden, als solche, die Geschäftsinformationen enthalten.
Illuminati
7
@ ShiranGinige deine Erfahrung ist falsch.
Grozz
35

Sie können Ihren Dokumentationsprozess vereinfachen, indem Sie mehrere großartige Add-Ins verwenden. Eines davon ist GhostDoc , ein kostenloses Add-In für Visual Studio, das XML-Doc-Kommentare generiert. Wenn Sie ReSharper verwenden , sehen Sie sich auch das hervorragende Agent Johnson Plugin für ReSharper an, das eine Option zum Generieren von XML-Kommentaren für ausgelöste Ausnahmen hinzufügt.

Update: Es scheint, dass Agen Johnson für R # 8 nicht verfügbar ist. Checkout Außergewöhnlich für ReSharper als Alternative ...

Schritt 1: GhostDoc generiert den XML-Kommentar (Strg-Umschalt-D), während das Agent Johnson-Plugin für ReSharper vorschlägt, die Ausnahme ebenfalls zu dokumentieren:

Schritt 1

Schritt 2: Verwenden Sie die Tastenkombination von ReSharper (Alt-Enter), um auch die Ausnahmedokumentation hinzuzufügen:

Schritt 2 http://i41.tinypic.com/osdhm

Hoffentlich hilft das :)

Igal Tabachnik
quelle
Die tinypischen Verbindungen sind unterbrochen.
ANeves
11

Soweit ich weiß, besteht die Absicht der Verwendung des <exception> -Elements darin, es beim Dekorieren von Methoden zu verwenden, nicht von Ausnahmen:

/// <summary>Does something!</summary>
/// <exception cref="DidNothingException">Thrown if nothing is actually done.</exception>
public void DoSomething()
{
// There be logic here
}

Ausnahmen, die von anderen aufgerufenen Methoden ausgelöst werden können, sollten in diesen Methoden abgefangen, behandelt und dokumentiert werden. Ausnahmen, die möglicherweise von .NET ausgelöst werden könnten, oder Ausnahmen, die explizit von Ihrem eigenen Code ausgelöst werden, sollten dokumentiert werden.

Wenn Sie genauer sind, können Sie vielleicht Ihre eigenen benutzerdefinierten Ausnahmen abfangen und auslösen?

Daniel Schaffer
quelle
4

Teil des Vertrags für Ihre Methode sollte sein, zu überprüfen, ob die Voraussetzungen gültig sind, also:

public void MyMethod2()
{
    System.IO.File.Open(somepath...); // this may throw FileNotFoundException
}

wird

/// <exception cref="FileNotFoundException">Thrown when somepath isn't a real file.</exception>
public void MyMethod2()
{
    FileInfo fi = new FileInfo( somepath );
    if( !fi.Exists )
    {
        throw new FileNotFoundException("somepath doesn't exists")
    }
    // Maybe go on to check you have permissions to read from it.

    System.IO.File.Open(somepath...); // this may still throw FileNotFoundException though
}

Mit diesem Ansatz ist es einfacher, alle Ausnahmen zu dokumentieren, die Sie explizit auslösen, ohne auch dokumentieren zu müssen, dass a OutOfMemoryException möglicherweise ausgelöst wird usw.

Rowland Shaw
quelle
1
Ich bin mir nicht sicher, wozu diese Prüfung gut ist, wenn Sie nur die Ausnahme duplizieren, die der OpenAnruf sowieso auslösen würde (ganz zu schweigen davon, dass es ein Rennen gibt und die Prüfung keinen Erfolg garantiert Open). .
Matt Enright
1
@ MattEnright Zugegeben, aber ich habe dies ein wenig erfunden, um den Punkt zu veranschaulichen ...
Rowland Shaw
1

Sie sollten alle Ausnahmen dokumentieren, die möglicherweise von Ihrer Methode ausgelöst werden könnten.

Um die Implementierungsdetails auszublenden, würde ich versuchen, einige Ausnahmen von MyMethod2 selbst zu behandeln.

Sie könnten in Betracht ziehen, sie erneut zu speichern, wenn Sie die Ausnahme nicht behandeln oder lösen können. Meistens verpackt / verpackt in einer aussagekräftigeren Ausnahme für den Anrufer.

GvS
quelle
1

Wie bereits beantwortet, werden XML-Kommentare zur Dokumentation der Ausnahmen verwendet.

Zusätzlich zu den Plugins können Sie auch statische Analysetools verwenden, die in TFS integriert werden können, um sicherzustellen, dass die Ausnahmen dokumentiert sind.

Unter den folgenden Links können Sie sehen, wie Sie eine benutzerdefinierte Regel für StyleCop erstellen, um zu überprüfen, ob die von Ihren Methoden ausgelösten Ausnahmen dokumentiert werden.

http://www.josefcobonnin.com/post/2009/01/11/Xml-Documentation-Comments-Exceptions-I.aspx http://www.josefcobonnin.com/post/2009/01/15/Xml-Documentation -Kommentare-Ausnahmen-II.aspx

Grüße.


quelle
0

Dokumentieren Sie erwartete Ausnahmen in Ihrer Methode. In Ihrem Beispiel würde ich den Benutzer wissen lassen, dass diese Methode eine Datei auslösen kann, bei der keine Ausnahme gefunden wurde.

Denken Sie daran, dass Sie den Anrufer darüber informieren müssen, was ihn erwartet, damit er entscheiden kann, wie er damit umgehen soll.

Damien
quelle