Come documentare le eccezioni generate in c # /. Net


140

Attualmente sto scrivendo un piccolo framework che verrà utilizzato internamente da altri sviluppatori all'interno dell'azienda.

Voglio fornire buone informazioni su Intellisense, ma non sono sicuro di come documentare le eccezioni generate.

Nel seguente esempio:

public void MyMethod1()
{
    MyMethod2();

    // also may throw InvalidOperationException
}

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

    // also may throw DivideByZeroException
}

So che il markup per documentare le eccezioni è:

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

Quello che non capisco è come documentare le eccezioni generate dal codice chiamato da MyMethod1() ?

  • Devo documentare le eccezioni generate da MyMethod2()
  • Devo documentare le eccezioni generate da File.Open()?

Quale sarebbe il modo migliore per documentare possibili eccezioni?


4
So che questo non è esattamente quello che ti stavi chiedendo (e questa è una domanda davvero vecchia) ma Eric Lippert (sviluppatore principale del compilatore microsoft C # e dei team di progettazione) ha scritto un post sul blog sui 4 tipi di eccezioni che penso che ogni sviluppatore dovrei pensare mentre scrivo il codice di gestione delle eccezioni: blogs.msdn.com/b/ericlippert/archive/2008/09/10/…
javajavajavajavajava

@javajavajavajavajava Grazie per il link - sicuramente vale la pena leggere.
Arnold Zokas,

1
Penso che questa sia una domanda valida perché non è affatto ovvio come documentare correttamente le eccezioni in C # e le viste 50K dimostrano che non è nemmeno ovvio per molte persone. La seconda risposta più votata è molto utile in quanto mostra di usare xmldocs esistenti per documentare questo. Votazione per riaprire. Questa stretta ragione "basata sull'opinione" sta uccidendo molte domande di programmazione davvero molto utili.
Alexei,

Risposte:


110

Dovresti documentare ogni eccezione che potrebbe essere generata dal tuo codice, comprese quelle in tutti i metodi che potresti chiamare.

Se l'elenco diventa un po 'grande, potresti voler creare il tuo tipo di eccezione. Cattura tutti quelli che potresti incontrare nel tuo metodo, avvolgili nella tua eccezione e lancialo.

Un altro posto che potresti voler fare in questo modo è se il tuo metodo è sulla faccia della tua API. Proprio come una facciata semplifica più interfacce in un'unica interfaccia, l'API dovrebbe semplificare più eccezioni in un'unica eccezione. Semplifica l'utilizzo del codice per i chiamanti.


Per rispondere ad alcune delle preoccupazioni di Andrew (dai commenti), ci sono tre tipi di eccezioni: quelli di cui non si è a conoscenza, quelli di cui si conosce e di cui non si può fare nulla, e quelli di cui si conosce e possono fare qualcosa.

Quelli che non sai di voler lasciar andare. È il principale problema del fallimento rapido: è meglio che l'app si blocchi in modo anomalo piuttosto che entrare in uno stato in cui si potrebbe finire per corrompere i dati. Il crash ti dirà cosa è successo e perché, il che può aiutare a spostare quell'eccezione dall'elenco "quelli che non conosci".

Quelli che conosci e di cui non puoi fare nulla sono eccezioni come OutOfMemoryExceptions. In casi estremi potresti voler gestire eccezioni come questa, ma a meno che tu non abbia dei requisiti abbastanza notevoli, le tratti come la prima categoria: lasciali andare. Non si deve documentare queste eccezioni? Sembreresti piuttosto sciocco documentare OOM su ogni singolo metodo che rischia un nuovo oggetto.

Quelli che conosci e di cui puoi fare qualcosa sono quelli che dovresti documentare e racchiudere.

Puoi trovare altre linee guida sulla gestione delle eccezioni qui.


3
Devo ammettere che non sembra molto pratico. Non riesco a immaginare quante potenziali eccezioni possano essere generate da qualsiasi codice che posso chiamare, inoltre ci sono cose come OutOfMemoryException che non vorresti catturare e concludere.
Andrew Hare,

3
La tua risposta sarà buona, ma in realtà sono due risposte che si contraddicono a vicenda. "documenta ogni eccezione che potrebbe essere generata dal tuo codice" e "Quelli che conosci e di cui puoi fare qualcosa sono quelli che dovresti documentare".
Tymtam,

2
@Tymek: No. La prima metà ha risposto alla domanda "come devo documentare le eccezioni", la seconda parte ha sottolineato la risposta palesemente ovvia a "quali eccezioni dovrei documentare". Il primo non implica che tu documenti ogni eccezione che potrebbe eventualmente verificarsi. Alcune persone sono troppo letterali, il che ha richiesto la seconda metà.

5
@Tymek Penso che il tuo punto potrebbe essere che se puoi fare qualcosa al riguardo, perché non fare qualcosa al riguardo invece di ridisegnarlo e documentarlo? Potrebbe essere più veritiero dire "Quelli che sai che il codice client può fare qualcosa". Questo elimina la contraddizione, perché queste sono le eccezioni ideali per documentare.
mo.

Per quanto riguarda le eccezioni che si "lasciano andare", è sempre possibile individuarle a un livello inferiore che le registra o altro. Sai; semplicemente creando un modo intuitivo per far arrestare il programma.
Nyerguds,

96

È necessario utilizzare la documentazione XML standard .

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

Il valore nel farlo in questo modo è che stai fornendo la documentazione delle eccezioni note che possono verificarsi. Questa documentazione è disponibile in intellisense se si utilizza Visual Studio e può ricordare a te (o ad altri) in seguito le eccezioni che ci si può aspettare.

Si desidera specificare i tipi di eccezione specifici, poiché potrebbe essere possibile gestire un tipo di eccezione, mentre altri tipi sono il risultato di un problema grave e non possono essere corretti.


1
In che modo ciò aggiunge valore? Ad esempio, tutte queste eccezioni sono derivazioni del tipo di eccezione. Dalla mia esperienza non sarà pratico pensare ad ogni altro tipo di eccezione che potrebbe essere generata dalle altre API chiamate all'interno dei tuoi metodi. Il mio punto è che non dovremmo preoccuparci di alcuna eccezione generata da un metodo rispetto a quella che trasporta informazioni commerciali.
Illuminati,

7
@ShiranGinige la tua esperienza è sbagliata.
Grozz,

35

È possibile semplificare il processo di documentazione utilizzando diversi componenti aggiuntivi eccezionali. Uno di questi è GhostDoc , un componente aggiuntivo gratuito per Visual Studio che genera commenti XML-doc. Inoltre, se usi ReSharper , dai un'occhiata all'eccellente Plugin Agent Johnson per ReSharper, che aggiunge un'opzione per generare commenti XML per eccezioni generate.

Aggiornamento: sembra che Agen Johnson non sia disponibile per R # 8, checkout Eccezionale per ReSharper in alternativa ...

Passaggio 1: GhostDoc genera il commento XML (Ctrl-Shift-D), mentre il plug-in Agent Johnson per ReSharper suggerisce di documentare anche l'eccezione:

passo 1

Passaggio 2: utilizzare il tasto di scelta rapida di ReSharper (Alt-Invio) per aggiungere anche la documentazione relativa alle eccezioni:

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

Spero che aiuti :)


I collegamenti tinypic sono interrotti.
ANeves

11

Da quello che ho capito, l'intenzione di usare l'elemento <exception> è di usarlo quando si decorano i metodi, non le eccezioni:

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

Le eccezioni che possono essere generate da altri metodi chiamati devono essere rilevate, gestite e documentate in tali metodi. Le eccezioni che potrebbero essere generate da .NET o le eccezioni esplicitamente generate dal proprio codice devono essere documentate.

Per quanto riguarda qualcosa di più specifico, forse puoi catturare e lanciare le tue eccezioni personalizzate?


4

Parte del contratto per il tuo metodo dovrebbe essere quello di verificare che le condizioni preliminari siano valide, quindi:

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

diventa

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

Con questo approccio, è più semplice documentare tutte le eccezioni che si generano in modo esplicito senza dover documentare anche che OutOfMemoryException potrebbe essere lanciato a, ecc.


1
Non sei sicuro di quale sia il punto di tale controllo se hai intenzione di duplicare l'eccezione che la Openchiamata genererebbe comunque (per non parlare, come noti, che c'è una gara e il controllo non garantisce il successo di Open) .. .
Matt Enright

1
@MattEnright Concesso, ma l'ho reso un po 'inventato per illustrare il punto ...
Rowland Shaw,

1

Dovresti documentare tutte le eccezioni che potrebbero essere generate dal tuo metodo.

Per nascondere i dettagli di implementazione, proverei a gestire alcune eccezioni da MyMethod2.

Potresti considerare di modificarli, se non riesci a gestire o risolvere l'eccezione. Principalmente impacchettato / avvolto in un'eccezione più significativa per il chiamante.


1

In effetti, come è già stato risposto, il modo per documentare le eccezioni è usare i commenti XML.

Oltre ai plug-in, è anche possibile utilizzare strumenti di analisi statica che possono essere integrati con TFS per essere sicuri di avere documentate le eccezioni.

Nei link sottostanti puoi vedere come creare una regola personalizzata per StyleCop per convalidare le eccezioni generate dai tuoi metodi che sono state documentate.

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

Saluti.


0

Documenta le eccezioni previste nel tuo metodo, nel tuo esempio vorrei far sapere all'utente che quel metodo può generare un file non trovato.

Ricorda che è per informare il chiamante di cosa aspettarsi in modo che possano scegliere come gestirlo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.