Cattura un errore?

1

Sta riscontrando un errore con try ... catch una procedura migliore rispetto alla rilevazione di un errore con analisi / controllo errori corretti? Ad esempio, rimuovendo da una lista vuota: circonda una clausola try catch considerata come un modo più efficiente di testare se l'elenco è vuoto in anticipo? O è lo stesso? Grazie.

P.S: Se una domanda simile è stata precedentemente posta sul forum, non esitare a segnalarla.

    
posta fabricemarcelin 10.04.2012 - 07:18
fonte

6 risposte

4

Non dovresti gestire il normale flusso di programma tramite Eccezioni. Le eccezioni dovrebbero essere gestite solo se si vuole fare qualcosa con esso. Se rimuovere un elemento di una lista vuota dovrebbe generare un'eccezione, dovresti lasciarlo. Se vuoi restituire una nuova lista vuota con questo metodo, dovresti farlo.

Non c'è 1 risposta assoluta su questo argomento, dovresti controllarlo per use-case.

Naturalmente, non fa mai male fare una programmazione difensiva e assicurarsi che gli utenti non vedano troppe eccezioni nell'uso dell'applicazione. Nell'esempio che hai citato, probabilmente eseguirò un controllo nullo e, a seconda del metodo, forse lancio una nuova ArgumentNullException. Un tentativo di cattura in questa situazione mi sembra un po '"sporco" secondo me, ma in uno scenario più ampio potrebbe avere più senso.

Indietro nei giorni in cui ho imparato a lanciare eccezioni è un'operazione costosa (collegamento casuale, controlla la parte inferiore della pagina) , quindi evitali se possibile.

Un'altra cosa che non mi piace davvero sugli errori di cattura è che, se non li riduci abbastanza, potresti potenzialmente rilevare un errore che non ha nulla a che fare con il pezzo di codice che vuoi veramente dai un'occhiata. Ad esempio, se la tua applicazione è a 6 strati e stai chiamando un metodo come:

try
{
  otherlayer.Method1();
}
catch(IOException ioEx)
{
  //DoSomething
}

È possibile che IOException catturi qualcosa che non ti aspetti all'inizio, quindi probabilmente lo gestirai male. (potrebbe accadere se qualcuno decide di cambiare gli altri livelli a tua insaputa).

In sintesi: Ti consiglio di non utilizzare molti blocchi di try...catch nel tuo codice, solo quando sono realmente necessari e aggiungono qualcosa di utile, o assicurati che il flusso del tuo programma continui a funzionare.

    
risposta data 10.04.2012 - 13:00
fonte
3

Quando verificare codice

standard cose come la rimozione da una lista vuota, ecc.

Quando usare Try ... Catch

  • accesso esterno alle reti
  • accesso esterno al file system
  • accesso esterno ai database
  • etc
risposta data 10.04.2012 - 18:47
fonte
3

Correggimi se ho sbagliato e modifico la mia risposta.

Ti stai chiedendo se l'aggiunta di una clausola if per il tuo codice sia un'opzione migliore rispetto a try .. catch .

Credo che un try .. catch sia migliore.

Ecco perché:

  • Puoi raggruppare facilmente il tuo tipo di errori in un unico tipo. Lasciatemi fare un esempio basato su Java. Posso usare un try .. catch per IOException . Questo è il tuo codice "Hey! Se hai problemi con quei ragazzi I / O, per favore fallo!". Nota che non ti importa di cosa sia l'errore I / O. Qualcuno ha già codificato molti problemi con I / O che non avresti mai immaginato e te lo ha dato come IOException . Stai riutilizzando il loro codice che coprirà molto più di quello che potresti credere sarebbe un problema di I / O. Benefici? Direi che il primo e il più grande ha una copertura molto più ampia di possibili errori.

  • Mantiene il tuo codice più leggibile. Immagina un tuo collega che legge il tuo codice. All'improvviso vede un mare di condizioni e inizia a chiedersi cosa diavolo è per. Se vede un IOException invece (questo è solo uno tra tutti!) Non ha bisogno di pensarci due volte: è un errore che stai cercando di cogliere. Riesce a comprendere facilmente le tue opinioni su ciò che dovrebbe fare il tuo programma e a riflettere su quale dovrebbe essere il problema nel caso in cui qualcosa vada storto . Non è necessario scrivere un enorme registro di commenti sul metodo per quanto riguarda le tue preoccupazioni su cosa potrebbe andare storto; è scritto lì, come eccezione. Semplice, pulito e leggibile.

  • Stai riutilizzando il codice. Ne ho parlato nel punto precedente, ma voglio sottolineare questo. Il riutilizzo . Riutilizzare il codice è un'ottima pratica. Le linee di prodotti software sono il miglior esempio di questo! Se c'è qualcosa già fatto per te, perché passare attraverso il problema di ricrearlo? Il codice riutilizzato è lì da un po ', utilizzato costantemente da molte persone. Molto probabilmente hanno già riscontrato tutti i possibili problemi a cui potresti pensare e li hanno incapsulati, ad esempio IOException . Questo principio in un certo senso sottolinea l'open source. Tutti lo vedono, tutti lo stanno usando, molto probabilmente verrà riparato presto. Potrei allungare l'analogia ma spero che tu abbia il punto principale!

  • È possibile propagare le eccezioni e semplificare la comprensione di ciò che è andato storto. Immagina una situazione in cui quel metodo rilevi un'eccezione (usiamo di nuovo IOException ). Lui non sa cosa farsene. Cosa fa? Racconta il metodo che lo ha chiamato e dici: "Ehi, non so come affrontarlo, ma non posso andare avanti così, per favore fai qualcosa!". Quindi il chiamante può fare lo stesso fino a quando non arriva al tuo metodo principale. Se a questo punto il metodo principale non si occupa dell'eccezione, il programma si bloccherà e scaricherà l'eccezione stacktrace (sto usando Java come esempio qui), quindi sai che quando qualcosa va storto che tipo di eccezione lo ha causato . Probabilmente ti sei già imbattuto in quel NullPointerException che ci urla sempre per fare qualcosa di sciocco! Abbastanza semplice, indica il suo nome che, assumendo un buon uso della semantica, dovrebbe essere auto esplicativo. Prova a immaginare di scrivere un messaggio per ogni condizione di errore: "C'è stato un errore nel mio array, c'era un problema con il mio I / O, ecc.". Questo non sarebbe scalabile in sistemi più grandi, giusto? Puoi quindi andare e aggiungere anche eccezioni più raffinate in modo da ottenere risultati migliori sul problema e gestirlo in modo appropriato. Si noti inoltre che propagando gli errori, non è necessario utilizzare un try .. catch su ogni singolo metodo che gestisce l'array. Basta farlo una volta sul primo metodo e lasciarlo propagare al chiamante che sa come gestirlo. Questa non è una regola, ma potrebbe essere utile a seconda della situazione. Si noti inoltre che alcuni metodi dovranno sapere cosa fare con gli errori, quindi in un certo senso si stanno concentrando tutte le decisioni in un unico posto. Potresti voler diffondere la tua gestione delle eccezioni per evitare troppi codici in un unico metodo!

  • Se gestisci l'eccezione, il tuo programma continua nonostante il problema; non si fermerà.

risposta data 10.04.2012 - 08:04
fonte
1

Gran parte di ciò che aiuta la gestione delle eccezioni sono i sistemi più grandi. In particolare, il codice che rileva un errore può trovarsi a diversi livelli (e scritto interamente separatamente) dal codice che sa come reagire a quell'errore.

Per un esempio tipico, prendiamo in considerazione il codice per l'apertura di un file nascosto in alcune librerie. Giusto per semplicità, supponiamo che stia aprendo un file per la registrazione. Se il registro non può essere aperto, quel codice libreria non (e soprattutto non dovrebbe) sapere cosa fare. Dovrebbe certamente rilevare il problema, ma non ha idea se (per esempio) vuoi inviare una email, visualizzare un MessageBox o NSAlert, ecc. Lanciare un'eccezione, è il codice che lo usa per prendere la decisione su come il problema viene comunicato all'utente.

Per quanto riguarda l'utilizzo di un'istruzione if e, ad esempio, del valore restituito, si verifica un problema simile. Se seguiamo questo percorso, ogni livello dalla libreria in cui è aperto il file, fino al punto in cui mostriamo qualcosa all'utente, deve collaborare nel controllare il codice di errore e trasmetterlo fino a un livello superiore se qualcosa non può gestire se stesso. Sfortunatamente, nella maggior parte dei casi, è più facile fare la cosa sbagliata (effettuare la chiamata senza nemmeno controllare il valore di ritorno) rispetto a quella giusta. Solo per i sorrisi, diciamo che ci sono sei livelli di codice tra il punto in cui viene rilevato il problema e dove il problema deve essere comunicato all'utente. Supponiamo inoltre che il 90% del programmatore stia facendo la cosa giusta ad ogni livello. In tal caso, otteniamo .9 6 = .53, o solo il 53% di possibilità che l'errore venga effettivamente gestito correttamente. Anche con (secondo me) pratiche di codifica al di sopra della media (penso che il 70-80% sia probabilmente più vicino alla media) le probabilità che venga gestita correttamente sono appena migliori di 50:50.

Al contrario, con le eccezioni, il codice ai livelli intermedi non deve fare qualsiasi cosa perché l'eccezione possa essere trasmessa fino a dove può essere gestita (beh, a meno che tu non stia usando Java controllate le eccezioni, ma se lo fai, ti meriti tutti i problemi che ottieni). Le eccezioni si propagano di default invece di essere "mangiate" di default. Possiamo semplificare tutti gli strati intermedi di codice perché la cosa giusta accade per impostazione predefinita.

    
risposta data 10.04.2012 - 08:21
fonte
1

Risposta semplice: non utilizzare try-catch per le situazioni in cui è possibile verificare la condizione di errore nel codice.

Try-catch non dovrebbe essere usato per controllare il flusso del programma.

Vedi Escludi eccezioni - è focalizzato su C # ma è applicabile alla gestione delle eccezioni in tutte le lingue.

    
risposta data 16.04.2012 - 09:06
fonte
0

Is catching an error with try ... catch a better practice than catching an error with proper analysis/error check?

Nel 99,9% dei casi, il codice più breve e semplice è il migliore.

For instance, removing from an empty list...

Se stai tentando di rimuovere un elemento specifico da un elenco, l'elemento è lì o no lì. Non c'è niente di speciale in una lista vuota. Il controllo di una lista vuota è ridondante, proprio come questa dichiarazione if è ridondante:

if (n > 0) {
  for (int i = 0; i < n; ++i) ...

Se verifichi la presenza dell'elemento, duplichi il lavoro che sta per essere eseguito con la chiamata "rimuovi". Non farlo Se la funzione di libreria genera quando l'elemento non è presente, vai avanti e usa try-catch. Prendi in considerazione l'estrazione di una nuova funzione try_remove che restituisce true quando l'elemento è stato rimosso e falso altrimenti.

    
risposta data 10.04.2012 - 22:06
fonte

Leggi altre domande sui tag