2009-12-03 12 views
6

Esiste uno standard di best practice o di settore per il lancio di eccezioni da un'API del toolkit?Definizione delle eccezioni che possono essere generate da un'API del toolkit

Se l'utente che sta affrontando i metodi cattura e termina Exception in una sorta di CustomException in modo che gli utenti debbano solo preoccuparsi di CustomException s che escono dall'API?

Oppure la convenzione è quella di far saltare le bolle?

Siamo preoccupati di poter documentare tutte le possibili eccezioni che i nostri metodi API potrebbero generare. (Ad esempio, se il nostro metodo API chiama Stream.Write() che genera 4 o 5 eccezioni, dovremmo documentare tutti quelli oltre alle altre eccezioni che altri metodi chiamati potrebbero generare.)

Stavamo pensando di fare qualcosa come questo:

public void customerFacingApiMethod(){ 
    try { 
     //api functionality goes here 
    } catch (Exception e) { 
     throw new CustomException(e); 
    } 
} 

risposta

13

a mio parere avere l'API gettando un solo tipo di eccezione è una cattiva idea. Una delle cose buone con diverse eccezioni è che puoi scegliere di catturare diversi tipi di eccezioni e gestirli in modo diverso. L'annullamento delle eccezioni in un unico tipo di eccezione rimuoverà tale funzionalità.

Utilizzare i tipi di eccezione forniti dal framework, laddove appropriato, e creare i propri tipi di eccezioni personalizzate per situazioni specifiche ove appropriato. E soprattutto, assicurati di documentare per ogni metodo quali eccezioni possono lanciare.

+1

+1 per non nascondere i dettagli delle eccezioni interne – Oded

+0

In linea di principio, siamo d'accordo. Ma cosa succede se una delle chiamate che stiamo apportando cambia un'eccezione che genera, ora la nostra documentazione non è sincronizzata. O se la loro documentazione non è corretta e c'è un'eccezione generata che non è documentata. –

+3

cosa succede se se cosa. È possibile che tu stesso a morte, il punto è che stai distruggendo la più grande caratteristica di eccezioni, che è che sono digitati. – Fred

1

Non mi piace. Se si avvolgono tutte le eccezioni in una CustomException, sarà difficile rilevare eccezioni specifiche senza effettuare ricerche all'interno dell'oggetto per InnerExcpetion (possibilmente livelli multipli profondi se la propria API utilizza anche altre API che fanno la stessa cosa). Se c'è una OutOfMemoryException, mi piacerebbe saperlo senza doverla cercare.

1

Non utilizzare la stessa eccezione per tutti.

È necessario che i diversi tipi di eccezione siano in grado di separare un caso da un altro. Per tutto ciò che lasceresti scorrere fino a quando un blocco generico di eccezioni del gestore di catch non sembrerebbe k, ma stai impedendo qualsiasi altro recupero di codice - azioni extra che operano su casi specifici.

È possibile eseguire il wrapping di una serie di eccezioni, se queste rientrano in uno scenario specifico che può essere gestito dal codice chiamante. Non dimenticare che alcune eccezioni di framework già comunicano bene la situazione.

1

Ciò che Fredrik Mork dice è molto vero. Mi piace anche aggiungere che è possibile documentare facilmente le eccezioni generate con commenti xml (e GhostDoc).

Quindi un utente API può cercare nella documentazione per vedere quali eccezioni possono essere lanciate. Tuttavia, c'è un rovescio della medaglia.

Se si dispone di una profonda stack all'interno del vostro API e soprattutto se la complessità ciclomatica diventa alto (cioè num di eventuali diramazioni) non è possibile recuperare tutte le possibili eccezioni che possono essere lanciate (forse dal runtime?)

Così Vorrei raccomandare di lanciare solo se qualcosa se il recupero non è possibile e solo gettare nel livello superiore della tua API, cioè non più profondo di 2 profondità. E prendi tutte le eccezioni che vengono gettate più in profondità nel tuo callstack e restituiscile come InnerException o qualcosa del genere.

3

Quando si generano eccezioni, assicurarsi che le eccezioni relative all'utente siano tutte pertinenti a ciò che l'utente ha effettivamente sbagliato rispetto al proprio toolkit. Ciò potrebbe significare catturare o unire diverse eccezioni del file system in una singola eccezione, ma non dovresti mai catturare Eccezione e lanciarne una nuova - ciò che in realtà non sta dicendo all'utente del toolkit cosa hanno fatto di sbagliato.

3

È necessario seguire gli stessi concetti di .NET Framework. I tuoi utenti usano già il framework, quindi sanno come funziona e si aspettano determinati comportamenti.

  • Gettare un ArgumentException un'eccezione -derived se un argomento da parte del cliente non è valido (uso ArgumentNullException, ArgumentOutOfRangeException, ecc a seconda dei casi).
  • Lanciare un'eccezione IOException -derived per errori di I/O.

Etc ...

Nella documentazione, stato chiaramente i presupposti per la vostra API pubblica e precisarne le eccezioni che saranno gettati quando falliscono (come MSDN fa).

1

Ci sono due tipi di eccezioni da considerare (ignorando StackOverflowException, ecc, che non si può fare nulla comunque):

  1. Quelle che sono causati da problemi esterni (come file di IO), che devono essere gestiti
  2. Quelli che possono sempre essere evitati con un input correttamente convalidato.

Di solito è logico che le eccezioni di tipo IO siano passate allo stack di chiamate non modificato, poiché non c'è nulla che tu possa fare davvero a tale proposito. Eccezioni a ciò sarebbero errori anticipati per i quali si potrebbero fare tentativi, o chiedere all'utente cosa fare, se l'API funziona a livello di interfaccia grafica (che sarebbe piuttosto insolito).

Assicurati solo di documentare quali eccezioni di questo tipo possono essere generate dai tuoi metodi API.

Del secondo tipo (eccezioni che possono sempre essere prevenute), queste eccezioni possono essere generate dall'API su input non validi, ma non devono mai essere passati allo stack di chiamate dai livelli inferiori. L'input su qualsiasi cosa chiamata deve essere convalidato in modo che questi errori non si verifichino e, se per qualche ragione, possono verificarsi, allora queste eccezioni dovrebbero essere completate. In caso contrario, il codice che utilizza la tua API dovrà gestire eccezioni al livello di astrazione sbagliato.

E ancora una volta, assicurarsi di documentare quale tipo di input non genererà eccezioni e quali tipi di eccezioni aspettarsi se queste regole vengono interrotte.

In tutti i casi, generare eccezioni che hanno senso per l'utente della propria API, non la persona che programma l'API stessa.

1

Il problema con la cattura di System.Exception nel caso generale è che, così facendo, stai effettivamente dicendo "Non ho idea del perché questo non è riuscito, e va bene, perché so che posso continuare comunque !"

Questo è raro, se non mai, vero.

Avvolgere tutte le eccezioni in un unico tipo di eccezione personalizzato significa che i vostri utenti potranno semplicemente catturare quel tipo - che è quindi l'equivalente morale di intercettare System.Exception. Sebbene tu possa soddisfare alcune regole di policy/FXCop, in realtà stai ancora acquisendo System.Exception.

Per la vostra politica delle eccezioni, inizierei chiedendo questo: "Se non sapessi a cosa ha effettivamente parlato questa API, quale tipo di eccezione mi aspetterei di ottenere?" E ricorda che un metodo è una richiesta a un oggetto per fare qualcosa, e un'eccezione è il modo dell'oggetto di farti sapere che non è possibile, e perché.

0

Se si crea un unico tipo di eccezione da utilizzare in tutta l'API, il suo significato sarà vago per le applicazioni client che incontrano quel tipo di eccezione. Invece, considera la creazione di una gerarchia di classi di eccezioni per la tua API.

Per farlo, in primo luogo definire un abstract tipo di eccezione di base:

CustomException 

... e poi derivano tipi di eccezione più specifiche da esso. Per esempio:

CustomFooException 
CustomBarException 
CustomFizException 
CustomFuzException 

L'abstract tipo di base CustomException sarà mai gettati direttamente dal vostro API. Tuttavia, un client dell'API può rilevare il tipo di eccezione di base CustomException se non si cura di quale eccezione derivata specifica è stata generata dall'API.

Per ulteriori informazioni su l'idea di sviluppare una gerarchia classe di eccezione, vedi this answer e altre risposte a questa domanda: Why create custom exceptions in .NET?

vedere anche this answer che introduce l'idea di fare la classe base della gerarchia eccezione astratto.

Problemi correlati