Jak udokumentować zgłoszone wyjątki w języku C # / .net

139

Obecnie piszę mały framework, który będzie używany wewnętrznie przez innych programistów w firmie.

Chcę zapewnić dobre informacje Intellisense, ale nie jestem pewien, jak udokumentować zgłoszone wyjątki.

W poniższym przykładzie:

public void MyMethod1()
{
    MyMethod2();

    // also may throw InvalidOperationException
}

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

    // also may throw DivideByZeroException
}

Wiem, że znaczniki dokumentujące wyjątki to:

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

Nie rozumiem, jak dokumentować wyjątki wyrzucane przez kod wywoływany przez MyMethod1() ?

  • Czy powinienem dokumentować wyjątki zgłoszone przez MyMethod2()
  • Czy powinienem dokumentować wyjątki zgłoszone przez File.Open()?

Jaki byłby najlepszy sposób udokumentowania możliwych wyjątków?

Arnold Zokas
źródło
4
Wiem, że to nie jest dokładnie to, o co pytałeś (i jest to naprawdę stare pytanie), ale Eric Lippert (główny programista w zespołach kompilatorów i projektantów Microsoft C #) napisał post na blogu o 4 typach wyjątków, które moim zdaniem każdy programista o czym należy pomyśleć pisząc kod obsługi wyjątków: blogs.msdn.com/b/ericlippert/archive/2008/09/10/…
javajavajavajavajava
@javajavajavajavajava Dzięki za link - na pewno warto przeczytać.
Arnold Zokas
Myślę, że to ważne pytanie, ponieważ nie jest wcale oczywiste, jak poprawnie dokumentować wyjątki w C #, a widoki 50K pokazują, że nie jest to również oczywiste dla wielu ludzi. Druga najczęściej głosowana odpowiedź jest bardzo pomocna, ponieważ pokazuje, że używa istniejących xmldoców do udokumentowania tego. Głosowanie za ponownym otwarciem. Ten „oparty na opiniach” bliski powód zabija wiele naprawdę bardzo przydatnych pytań programistycznych.
Alexei

Odpowiedzi:

110

Powinieneś udokumentować każdy wyjątek, który może zostać wyrzucony przez twój kod, w tym te z wszelkich metod, które możesz wywołać.

Jeśli lista stanie się trochę duża, możesz chcieć utworzyć własny typ wyjątku. Złap wszystkie te, które możesz napotkać w swojej metodzie, zawiń je w wyjątek i wyrzuć to.

Innym miejscem, w którym możesz chcieć to zrobić w ten sposób, jest to, że Twoja metoda znajduje się w interfejsie API. Podobnie jak fasada upraszcza wiele interfejsów do jednego interfejsu, Twój interfejs API powinien uprościć wiele wyjątków do jednego wyjątku. Ułatwia korzystanie z Twojego kodu dzwoniącym.


Aby odpowiedzieć na niektóre obawy Andrzeja (z komentarzy), istnieją trzy rodzaje wyjątków: takie, o których nie wiesz, takie, o których wiesz i nie możesz nic zrobić, oraz takie, o których wiesz i możesz coś zrobić.

Te, o których nie wiesz, chcesz odpuścić. Jest to podstawa szybkiego niepowodzenia - lepiej, aby aplikacja uległa awarii, niż wejdź w stan, w którym możesz uszkodzić dane. Awaria powie Ci, co się stało i dlaczego, co może pomóc usunąć ten wyjątek z listy „tych, o których nie wiesz”.

Te, o których wiesz i nie możesz nic zrobić, to wyjątki, takie jak OutOfMemoryExceptions. W skrajnych przypadkach możesz chcieć obsłużyć takie wyjątki, ale jeśli nie masz jakichś dość niezwykłych wymagań, traktujesz je jak pierwszą kategorię - pozwól im odejść. Czy mają udokumentować te wyjątki? Wydawałbyś się całkiem głupi dokumentując OOM dla każdej metody, która powoduje nowy obiekt.

Te, o których wiesz i możesz coś zrobić, to te, które powinieneś dokumentować i pakować.

Więcej wskazówek dotyczących obsługi wyjątków można znaleźć tutaj.


źródło
3
Muszę przyznać, że nie brzmi to zbyt praktycznie. Nie mogę sobie wyobrazić, ile potencjalnych wyjątków może zostać wyrzuconych przez dowolny kod, który mogę wywołać, a ponadto są rzeczy takie jak OutOfMemoryException, których nie chcesz przechwytywać i zawijać.
Andrew Hare,
3
Czy twoja odpowiedź jest dobra, ale w rzeczywistości są to dwie odpowiedzi, które są ze sobą sprzeczne. „udokumentuj każdy wyjątek, który może zostać wyrzucony przez Twój kod” i „Te, o których wiesz i możesz coś zrobić, to te, które powinieneś dokumentować”.
tymtam
2
@Tymek: Nie. Pierwsza połowa odpowiadała na pytanie „jak dokumentować wyjątki”, druga część wskazywała na oczywistą odpowiedź na pytanie „jakie wyjątki powinienem udokumentować”. Pierwsza nie oznacza, że ​​dokumentujesz każdy wyjątek, który może kiedykolwiek wystąpić. Niektórzy ludzie są zbyt dosłowni, co wymagało drugiej połowy.
5
@Tymek Myślę, że twoim celem może być to, że jeśli możesz coś z tym zrobić, dlaczego nie zrobić czegoś z tym, zamiast powtórzyć to i udokumentować? Bardziej szczerym byłoby powiedzenie „Ci, o których wiesz, że kod klienta może coś z tym zrobić”. Eliminuje to sprzeczność, ponieważ są to idealne wyjątki do udokumentowania.
pon.
Jeśli chodzi o wyjątki, które „odpuszczasz”, zawsze możesz je złapać na jakimś niższym poziomie, który je rejestruje lub coś w tym stylu. Wiesz; po prostu tworząc przyjazny dla użytkownika sposób na awarię programu.
Nyerguds
96

Powinieneś użyć standardowej dokumentacji xml .

/// <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.");
    }
}

Wartością robienia tego w ten sposób jest dostarczenie dokumentacji znanych wyjątków, które mogą wystąpić. Ta dokumentacja jest dostępna w trybie Intellisense, jeśli używasz programu Visual Studio i może później przypomnieć tobie (lub innym) o wyjątkach, których możesz się spodziewać.

Chcesz określić konkretne typy wyjątków, ponieważ możesz być w stanie obsłużyć jeden typ wyjątków, podczas gdy inne typy są wynikiem poważnego problemu i nie można ich naprawić.

dreszcze 42
źródło
1
W jaki sposób to dodaje wartości? Na przykład wszystkie te wyjątki są pochodnymi typu Wyjątek. Z mojego doświadczenia wynika, że ​​nie będzie praktyczne myślenie o każdym innym typie wyjątku, który może zostać wyrzucony z innych interfejsów API, które są wywoływane w ramach Twoich metod. Chodzi mi o to, że nie powinniśmy martwić się żadnym wyjątkiem, który jest wyrzucany z metody niż te, które zawierają jakiekolwiek informacje biznesowe.
Illuminati
7
@ShiranGinige Twoje doświadczenie jest złe.
Grozz
35

Możesz ułatwić sobie proces tworzenia dokumentacji, używając kilku świetnych dodatków. Jednym z nich jest GhostDoc , darmowy dodatek do programu Visual Studio, który generuje komentarze XML-doc. Ponadto, jeśli używasz ReSharper , spójrz na doskonałą wtyczkę Agent Johnson dla ReSharper, która dodaje opcję generowania komentarzy XML dla wyrzuconych wyjątków.

Aktualizacja: Wygląda na to, że Agen Johnson nie jest dostępny dla R # 8, sprawdź Wyjątkowy dla ReSharper jako alternatywa ...

Krok 1: GhostDoc generuje komentarz XML (Ctrl-Shift-D), a wtyczka Agent Johnson dla ReSharper sugeruje również udokumentowanie wyjątku:

krok 1

Krok 2: Użyj klawisza skrótu ReSharper (Alt-Enter), aby dodać również dokumentację wyjątku:

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

Mam nadzieję, że to pomoże :)

Igal Tabachnik
źródło
Linki tinypic są zepsute.
ANeves
11

Z tego co rozumiem, intencją użycia elementu <exception> jest użycie go przy dekorowaniu metod, a nie wyjątków:

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

Wyjątki, które mogą być generowane przez inne wywoływane metody, powinny być przechwytywane, obsługiwane i dokumentowane w tych metodach. Należy udokumentować wyjątki, które mogą być generowane przez platformę .NET, lub wyjątki jawnie zgłaszane przez Twój własny kod.

Jeśli chodzi o uzyskanie bardziej szczegółowych informacji, być może uda Ci się wyłapać i wrzucić własne niestandardowe wyjątki?

Daniel Schaffer
źródło
4

Częścią kontraktu dla twojej metody powinno być sprawdzenie, czy warunki wstępne są ważne, więc:

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

staje się

/// <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
}

Dzięki takiemu podejściu łatwiej jest udokumentować wszystkie wyjątki, które jawnie zgłaszasz, bez konieczności dokumentowania, że OutOfMemoryException może zostać wyrzucony itp.

Rowland Shaw
źródło
1
Nie jestem pewien, jaki jest sens tego czeku, jeśli zamierzasz po prostu zduplikować wyjątek, który i tak Openby wywołać (nie wspominając, jak zauważyłeś, że jest wyścig, a czek nie gwarantuje sukcesu Open). ,
matowy Enright
1
@MattEnright Zgoda, ale trochę wymyśliłem to, aby zilustrować ten punkt ...
Rowland Shaw,
1

Powinieneś udokumentować wszystkie wyjątki, które mogą zostać wyrzucone przez twoją metodę.

Aby ukryć szczegóły implementacji, spróbuję samodzielnie obsłużyć niektóre wyjątki z MyMethod2.

Możesz rozważyć ich odzyskanie, jeśli nie możesz obsłużyć lub rozwiązać wyjątku. Przeważnie zapakowane / opakowane w bardziej znaczący wyjątek dla dzwoniącego.

GvS
źródło
1

Rzeczywiście, jak już udzielono odpowiedzi, sposobem udokumentowania wyjątków jest użycie komentarzy XML.

Oprócz wtyczek można również użyć narzędzi do analizy statycznej, które można zintegrować z TFS, aby mieć pewność, że wyjątki są udokumentowane.

W poniższych linkach możesz zobaczyć, jak zbudować niestandardową regułę dla StyleCop, aby sprawdzić poprawność wyjątków generowanych przez twoje metody.

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

Pozdrowienia.


źródło
0

Dokumentuj oczekiwane wyjątki w swojej metodzie, w twoim przykładzie chciałbym poinformować użytkownika, że ​​ta metoda może zgłosić wyjątek nie znaleziono pliku.

Pamiętaj, że ma to na celu poinformowanie dzwoniącego o tym, czego może się spodziewać, aby mógł wybrać, jak sobie z tym poradzić.

Damien
źródło