Utilizzo efficiente del blocco try / catch?

20

I blocchi di cattura devono essere utilizzati per scrivere la logica, ad esempio gestire il controllo del flusso ecc.? O solo per lanciare eccezioni? Ha effetto sull'efficienza o sulla manutenibilità del codice?

Quali sono gli effetti collaterali (se ce ne sono) della logica di scrittura nel blocco catch?

Modifica

Ho visto una classe Java SDK in cui hanno scritto la logica all'interno del blocco catch. Ad esempio (snippet tratto dalla classe java.lang.Integer ):

        try {
            result = Integer.valueOf(nm.substring(index), radix);
            result = negative ? new Integer(-result.intValue()) : result;
        } catch (NumberFormatException e) {
            String constant = negative ? new String("-" + nm.substring(index))
                                       : nm.substring(index);
            result = Integer.valueOf(constant, radix);
        }

EDIT2 :

Stavo passando per un tutorial dove lo considerano un vantaggio della logica di scrittura di casi eccezionali all'interno delle eccezioni:

Exceptions enable you to write the main flow of your code and to deal with the exceptional cases elsewhere.

Qualche indicazione specifica su quando scrivere la logica nel blocco catch e quando no?

    
posta HashimR 25.04.2012 - 14:00
fonte

6 risposte

44

L'esempio che citi è dovuto alla scarsa progettazione dell'API (non esiste un modo pulito per verificare se una stringa è un numero intero valido eccetto il tentativo di analizzarlo e di rilevare l'eccezione).

A livello tecnico, throw e try / catch sono costrutti del flusso di controllo che ti consentono di saltare lo stack delle chiamate, niente di più e niente di meno. Saltare in cima allo stack di chiamate collega implicitamente codice che non è ravvicinato nell'origine, che è non valido per la gestibilità . Quindi dovrebbe essere usato solo quando è necessario farlo e le alternative sono anche peggio. Il caso ampiamente accettato in cui le alternative sono peggiori è la gestione degli errori (codici di ritorno speciali che devono essere controllati e passati manualmente ogni livello dello stack di chiamate).

Se hai un caso in cui le alternative sono peggiori (e le hai considerate tutte attentamente), allora direi che usa throw e try / catch per il controllo del flusso è bene. Il dogma non è un buon sostituto per il giudizio.

    
risposta data 25.04.2012 - 14:23
fonte
9

Questo è qualcosa che tende a dipendere dal linguaggio e dal paradigma.

Gran parte del mio lavoro è svolto in Java (e talvolta in C ++). La tendenza è di usare eccezioni solo per condizioni eccezionali. Ci sono alcune domande su Stack Overflow sul sovraccarico delle prestazioni delle eccezioni in Java , e come puoi vedere, non è esattamente trascurabile. Ci sono anche altre preoccupazioni, come la leggibilità e la manutenibilità del codice. Se utilizzate correttamente, le eccezioni possono delegare la gestione degli errori ai componenti appropriati.

Tuttavia, in Python, l'idea che sia più facile chiedere perdono di quanto il permesso regni. Nella comunità Python, questo è noto come EAFP , che è in contrasto con il "look before you leap" ( LBYL ) approccio nei linguaggi in stile C.

    
risposta data 25.04.2012 - 14:16
fonte
9

Questo non è il modo migliore di pensare ai blocchi try / catch. Il modo di pensare ai blocchi try / catch è questo: è successo un errore, dove è il posto migliore per trattare questo specifico fallimento. Potrebbe trattarsi della riga successiva del codice, potrebbe essere di venti livelli nella catena di chiamate. Ovunque sia, è lì che dovrebbe essere.

Che cosa fa il blocco catch dipende dall'errore e da cosa puoi fare al riguardo. A volte può essere semplicemente ignorato (mancata eliminazione di un file scratch senza dati importati), a volte verrà usato per impostare un valore di ritorno delle funzioni su true o false (metodo int parse di java), a volte uscirai dal programma . Tutto ciò dipende dall'errore.

La parte importante da capire è: blocco catch == So come gestirlo.

    
risposta data 25.04.2012 - 17:15
fonte
6

I blocchi di cattura dovrebbero essere usati solo per gestire le eccezioni, nient'altro e mai e poi mai per il controllo del flusso. In qualsiasi situazione in cui si desidera utilizzare le eccezioni per gestire il flusso, sarebbe meglio controllare le condizioni preliminari.

Gestire il flusso con le eccezioni è lento e semanticamente scorretto.

    
risposta data 25.04.2012 - 14:03
fonte
5

Should catch blocks be used for writing logic i.e. handle flow control etc? Or just for throwing exceptions? Does it effect efficiency or maintainability of code?

In primo luogo, dimenticare l'idea che "le eccezioni dovrebbero essere utilizzate per condizioni eccezionali". Smettila anche di preoccuparti dell'efficienza, finché non hai codice che funziona in modo inaccettabile e hai misurato per sapere dove si trova il problema.

Il codice è più facile da capire quando le azioni seguono in una sequenza semplice, senza condizionali. Le eccezioni migliorano la manutenibilità rimuovendo il controllo degli errori dal flusso normale. Non importa se l'esecuzione segue il flusso normale il 99,9% delle volte o il 50% delle volte o il 20% delle volte.

Genera un'eccezione quando una funzione non è in grado di restituire un valore, quando una procedura non è in grado di completare l'azione prevista o quando un costruttore non è in grado di produrre un oggetto utilizzabile. Ciò consente ai programmatori di assumere che una funzione restituisca sempre un risultato utilizzabile, una procedura completa sempre l'azione richiesta, un oggetto costruito è sempre in uno stato utilizzabile.

Il problema più grande che vedo con il codice di gestione delle eccezioni è che i programmatori scrivono i blocchi try / catch quando non dovrebbero. Ad esempio, nella maggior parte delle applicazioni Web, se una richiesta di database genera un'eccezione, non è possibile eseguire nulla nel controller. Una clausola di cattura generica al più alto livello è sufficiente. Quindi il codice del controller può tranquillamente ignorare la possibilità che il disco si sia arrestato in modo anomalo o che il database sia offline o altro.

    
risposta data 25.04.2012 - 15:42
fonte
1

I blocchi di cattura non dovrebbero essere usati per scrivere la logica del codice. Dovrebbero essere usati solo per errori di gestione. Un esempio è (1) ripulire tutte le risorse allocate, (2) stampare un messaggio utile e (3) uscire con garbo.

È vero che le eccezioni possono essere sfruttate e causare effetti goto indesiderati. Ma questo non li rende inutili. Quando utilizzato correttamente , possono migliorare molti aspetti del tuo codice.

    
risposta data 25.04.2012 - 19:14
fonte

Leggi altre domande sui tag