Se una lingua supporta intrinsecamente le eccezioni, è preferibile generare eccezioni e i client possono intercettare l'eccezione se non desiderano che ciò comporti un errore. In effetti, i client del tuo codice si aspettano eccezioni e si imbatteranno in molti bug perché non controlleranno i valori di ritorno.
Ci sono molti vantaggi nell'utilizzare le eccezioni se hai una scelta.
messaggi
Le eccezioni contengono messaggi di errore leggibili dall'utente che possono essere utilizzati dagli sviluppatori per il debug o persino visualizzati dagli utenti, se desiderato. Se il codice che consuma non è in grado di gestire l'eccezione, può sempre registrarlo in modo che gli sviluppatori possano esaminare i registri senza dover interrompere qualsiasi altra traccia per capire quale fosse il valore restituito e mapparlo in una tabella per capire quale fosse il vera eccezione.
Con i valori di ritorno, non è possibile fornire facilmente ulteriori informazioni. Alcune lingue supporteranno l'esecuzione di chiamate di metodo per ottenere l'ultimo messaggio di errore, quindi questa preoccupazione è un po 'attenuata, ma ciò richiede al chiamante di effettuare chiamate extra e talvolta richiede l'accesso a un "oggetto speciale" che contiene queste informazioni.
Nel caso di messaggi di eccezione, fornisco il maggior numero possibile di contesti, come:
Non è stato possibile recuperare una politica del nome "pippo" per l'utente "bar", a cui si fa riferimento nel profilo dell'utente.
Confronta questo con un codice di ritorno -85. Quale preferiresti?
Chiama stack
Le eccezioni di solito hanno anche stack di chiamate dettagliati che aiutano a eseguire il debug del codice sempre più velocemente e possono anche essere registrati dal codice chiamante se lo si desidera. Ciò consente agli sviluppatori di individuare il problema in genere sulla riga esatta, quindi è molto potente. Ancora una volta, confrontalo con un file di registro con valori di ritorno (come -85, 101, 0, ecc.), Quale preferiresti?
Fallito approccio di parte veloce
Se un metodo viene chiamato da qualche parte che fallisce, genererà un'eccezione. Il codice chiamante deve sopprimere esplicitamente l'eccezione o fallirà. Ho scoperto che questo è davvero sorprendente perché durante lo sviluppo e i test (e persino in produzione) il codice fallisce rapidamente, costringendo gli sviluppatori a risolverlo. Nel caso di valori di ritorno, se manca un controllo per un valore di ritorno, l'errore viene silenziosamente ignorato e il bug emerge in qualche posto inaspettato, di solito con un costo molto più alto per il debug e la correzione.
Eccezioni per il wrapping e il wrapping
Le eccezioni possono essere racchiuse in altre eccezioni e quindi scartate se necessario. Ad esempio, il tuo codice potrebbe lanciare ArgumentNullException
quale codice chiamante potrebbe essere racchiuso in a UnableToRetrievePolicyException
perché l'operazione non è riuscita nel codice chiamante. Mentre all'utente potrebbe essere mostrato un messaggio simile all'esempio che ho fornito sopra, alcuni codici diagnostici potrebbero scartare l'eccezione e scoprire che si ArgumentNullException
era verificato il problema, il che significa che si tratta di un errore di codifica nel codice del consumatore. Ciò potrebbe quindi generare un avviso in modo che lo sviluppatore possa correggere il codice. Tali scenari avanzati non sono facili da implementare con i valori di ritorno.
Semplicità del codice
Questo è un po 'più difficile da spiegare, ma ho imparato attraverso questa codifica sia con valori di ritorno che con eccezioni. Il codice che è stato scritto utilizzando i valori di ritorno di solito effettua una chiamata e quindi presenta una serie di controlli su quale sia il valore di ritorno. In alcuni casi, chiamerebbe un altro metodo e ora avrà un'altra serie di controlli per i valori restituiti da quel metodo. Con le eccezioni, la gestione delle eccezioni è molto più semplice nella maggior parte se non in tutti i casi. Hai i blocchi try / catch / finally, con il runtime che fa del suo meglio per eseguire il codice nei blocchi finally per la pulizia. Perfino i blocchi nidificati try / catch / finally sono relativamente più facili da seguire e mantenere rispetto ai nidificati if / else e i valori di ritorno associati da più metodi.
Conclusione
Se la piattaforma che stai usando supporta le eccezioni (specialmente Java o .NET), dovresti assolutamente supporre che non ci sia altro modo se non quello di lanciare eccezioni perché queste piattaforme hanno linee guida per lanciare eccezioni, e i tuoi clienti si aspetteranno così. Se stavo usando la tua libreria, non mi prenderò la briga di controllare i valori di ritorno perché mi aspetto che vengano generate eccezioni, ecco come sta il mondo in queste piattaforme.
Tuttavia, se fosse C ++, sarebbe un po 'più difficile determinare perché esiste già una base di codice di grandi dimensioni con codici di ritorno e un gran numero di sviluppatori è ottimizzato per restituire valori al contrario di eccezioni (ad esempio Windows è pieno di HRESULT) . Inoltre, in molte applicazioni, può anche essere un problema di prestazioni (o almeno percepito).
try
/catch
esiste. Inoltre, puoi mettere il tuotry
/catch
molto più in alto nello stack in una posizione più appropriata per gestirlo (consentendo una maggiore separazione dei problemi).