2009-03-05 13 views
9

Recentemente ho dovuto sviluppare un modulo aggiuntivo per un servizio esistente sviluppato da un collega. Aveva messo un blocco try/catch nella funzione di lavoro principale per la cattura tutte le eccezioni unhadled che ribolliva a questo livello, li la registrazione con informazioni di stack trace ecc:Come implementare la gestione delle eccezioni di primo livello?

try 
{ 
    // do main work 
} 
catch(Exception ex) 
{ 
    // log exception info 
} 

Anche se questo rende il programma molto stabile (come in 'improbabile crash'), lo odio perché quando sto testando il mio codice, non vedo le eccezioni causate da esso. Naturalmente posso controllare il registro delle eccezioni e vedere se ci sono nuove voci, ma preferisco di gran lunga il feedback diretto di ottenere l'eccezione nel momento in cui viene lanciata (con il cursore sulla linea destra nel codice, per favore).

Ho rimosso questo livello superiore try/catch almeno mentre stavo ancora codificando e testando. Ma ora il mio compito è finito e devo decidere se rimetterlo per il rilascio, o no. Penso che dovrei farlo, perché rende il servizio più stabile, e il punto è che funziona in background senza bisogno di supervisione. D'altra parte ho letto che si dovrebbero chiamare solo eccezioni specifiche (come in IoException), non genericamente Exception.

Qual è il tuo parere su questo problema?

A proposito, il progetto è scritto in C#, ma sono anche interessato alle risposte per i linguaggi non .NET.

+0

Vedere anche http://stackoverflow.com/questions/576532/is-dying-is-awesome-preferred – Brian

risposta

10

Rimontarlo.

L'eccezione dovrebbe essere rilevante solo durante il test. Altrimenti non ha senso farla scoppiare all'utente.

La registrazione va bene.

Si può inoltre utilizzare il simbolo DEBUG definito da Visual Studio per i build di debug sotto forma di flag.

... 
    } catch(Exception e) { 
#if DEBUG 
      throw; 
#else 
      log as usual 
#endif 
    } 

Così la prossima volta che una modifica è necessaria la bandiera di debug deve essere impostata su true e l'eccezione pop-up.

+0

Hm, mi piace la bandiera del debug! – Treb

+0

Non dovrebbe usare "lancia" e non "lanciare e"? Altrimenti, la traccia dello stack viene cancellata (o qualcosa - non troppo sicuro). – strager

+0

@strager: Yup! L'esempio sopra mostrerà l'eccezione originale. Basta usare "lancia". –

2

Idealmente si desidera gestire un'eccezione il più vicino possibile a dove si è verificata, ma ciò non significa che un gestore di eccezioni globale sia una cattiva idea. Soprattutto per un servizio che deve rimanere in esecuzione a tutti i costi. Vorrei continuare quello che hai fatto. Disabilitarlo durante il debug ma lasciarlo in posizione per la produzione.

Ricordare che deve essere utilizzato come rete di sicurezza. Cerca ancora di cogliere tutte le eccezioni prima che si elevino così lontano.

4

In qualsiasi applicazione Java, è quasi sempre desidera definire un gestore di eccezioni per le eccezioni non gestite fanno con qualcosa di simile:

Thread.setDefaultUncaughtExceptionHandler(...); 

in cui l'oggetto che cattura queste eccezioni non gestite fanno avrà almeno il login al guasto in modo hai la possibilità di saperlo. Altrimenti, non vi è alcuna garanzia che ti venga persino notificato che un Thread ha avuto un'eccezione, non a meno che non sia il tuo thread principale.

Oltre a ciò, la maggior parte dei miei thread ha un try/catch dove prendo lo RunnableException (ma non lo Error) e lo registro ... alcuni Thread moriranno quando questo accadrà, altri lo registreranno e lo ignoreranno, altri mostreranno un reclamo all'utente e lasceranno decidere all'utente, a seconda delle esigenze dell'Applicazione.Questo try/catch si trova nella radice della Thread, nel metodo Runnable.run() o equivalente. Poiché try/catch è nella radice del Thread, non è necessario disabilitare a volte questa cattura.

Quando scrivo in C#, codice in modo simile. Ma tutto dipende dal bisogno dell'applicazione. L'eccezione è quella che corrompe i dati? Bene, allora non prenderlo e ignorarlo. Accedi SEMPRE, ma poi lascia morire l'applicazione. La maggior parte delle eccezioni non sono di questo tipo, comunque.

2

L'impulso a cogliere tutte le eccezioni e rendere il programma "stabile" è molto forte e l'idea sembra davvero allettante per tutti. Il problema, come lei sottolinea, è che questo è solo uno stratagemma e il programma potrebbe benissimo essere bug e peggio, senza indicazioni di guasti. Nessuno controlla regolarmente i registri.
Il mio consiglio sarebbe di provare a convincere l'altro sviluppatore a fare test approfonditi e quindi distribuirlo in produzione senza il problema.

+0

Capisco da dove vieni, ma c'è una grande classe di eccezioni in cui il tuo programma può essere eseguito in uno stato degradato, ma comunque eseguito, dove vuoi davvero eccezioni catch-and-log. La stabilità conta. Devi solo sapere dove NON PUOI fare questo. – Eddie

+0

@Eddie - È vero, quest'area è sempre molto dipendente dall'applicazione e dalle aspettative dell'utente. Vogliamo tutti fare applicazioni solide e performanti che non falliscono mai ma poi chiamate di realtà :). Niente batte estese test approfonditi, copertura del codice e beta con clienti reali per avere fiducia. –

1

Se si desidera visualizzare l'eccezione quando si verifica, in Visual Studio è possibile accedere al menu DEBUG, selezionare ECCEZIONI e indicare al debugger di interrompere non appena viene generata un'eccezione. Puoi anche scegliere quale tipo di Eccezioni. :)

+0

E come funziona quando il programma in questione è in esecuzione come servizio? – Treb

+2

Se caricate il servizio in memoria, quindi collegatelo, tutte queste cose funzionano come siete abituati. Se è remoto (come nel servizio si trova su un server da qualche parte), c'è qualcosa che devi installare sul server per consentire il debug remoto. Se è necessario eseguire questa operazione su STARTUP, è possibile aggiungere un "servizio fittizio" nel file eseguibile, avviare quello (che carica l'EXE in memoria), allegare al processo, quindi avviare l'altro servizio (con funzionalità complete di debug). Funziona BENE. –