2009-02-07 20 views
19

Si consideri questo scenario: Ho un'app a 3 livelli, quando l'utente fa clic sul pulsante il gestore di eventi button chiama un metodo in biz layer che esegue qualsiasi cosa con i dati forniti dal gestore di eventi del pulsante e quindi passa quei dati al livello di accesso ai dati che li invia al database di back-end. La domanda è dove mettere la cattura prova? Nel livello dati, nel livello biz, nel livello di presentazione o magari metterlo in giro tutti? Qual è la migliore strategia per rappresentare la gestione delle eccezioni come in questo scenario?Dove mettere try catch

risposta

5

sicuramente mettere un tentativo di cattura più vicino all'utente - perché in quella posizione è possibile tradurlo in qualcosa di significativo per il tuo utente.

I tentativi di cattura più approfonditi potrebbero essere necessari solo se si intende fare qualcosa con essi, ad esempio gestire l'eccezione o eventualmente registrare e riscrivere l'eccezione.

39

Seguiamo

Non intercettare le eccezioni, se non sai cosa fare con esso.

Non gestiamo mai eccezioni che non possiamo gestire o di default. Si fa ribollire e lo gestiamo a livello di applicazione.

Supponiamo che se è possibile impostare un valore predefinito per un oggetto businesss, è possibile gestirlo nel livello aziendale.

+1

Sì, prendi l'eccezione in cui sei in grado di gestirlo. Se non sai cosa fare con esso, non prenderlo. (E a volte, "prenderlo e ignorarlo" potrebbe essere la cosa valida da fare con esso, quindi fallo.) – jalf

+0

@Ramesh: Bella risposta +1 –

0

Dipende solo da dove si vuole effettivamente fare qualcosa al riguardo. Generalmente lo prendo nel livello aziendale, quindi lo registro e possibilmente invoco qualche funzione ui per visualizzare un messaggio all'utente.

Considero cosa fare degli errori una regola aziendale. Dovrebbe essere separato dal livello dati o dal livello ui.

0

La risposta generale sarebbe: prendere in qualsiasi momento è possibile gestire ciò che viene lanciato. Cioè, la decisione è abbastanza semplice. Ad esempio, cattura le eccezioni che si presentano durante la creazione di un oggetto di cui hai bisogno.

+0

Sono d'accordo con la prima parte della risposta ma non con l'esempio, se la creazione di un oggetto fallisce, non sai automaticamente come gestirlo. –

+0

Sì, certo. Se non puoi gestirlo, fallo propagare. –

2

Probabilmente la cosa migliore è utilizzare il comando try catch in tutti i layer, ma catturare silenziosamente solo le eccezioni nel livello dell'interfaccia utente. Nei livelli di accesso ai dati e ai dati, dovresti probabilmente rilevare l'eccezione e registrare le informazioni, prima di rilanciare ad es.

try 
{ 
    //do something 
} 
catch(Exception ex) 
{ 
    LogFile.WriteLine(ex.ToString()); 
    throw; 
} 

Nota: non scrivere:

throw ex; 

in quanto questo sarà chiaro tutte le informazioni di stack utile dal eccezione.

+0

@mrdresser: Perché dovresti registrare l'eccezione in ogni livello e non registrarla una volta per tutte dove gestiamo l'eccezione/se non è mai stata gestita nel livello dell'interfaccia utente? stack trace darebbe sempre l'intera informazione – Ramesh

+0

sono con Ramesh su quello. La cattura per il solo gusto del logging è allettante ... ma è solo un sacco di lavoro impegnativo che non è necessario e che si può evitare in tutta sicurezza. –

+0

Inoltre, se lo si registra in ogni livello, è possibile avere più voci di registro per la stessa eccezione. –

0

Provare/catturare sempre al livello superiore o al livello del controller.

0

UI è solo per la presentazione. Non si individuano eccezioni lì, perché capire cosa fare con esso significa logica. Questo appartiene ai livelli business o controller. Nel peggiore dei casi, viene rilevata l'eccezione e viene mappata a un messaggio di errore appropriato e di facile utilizzo che viene quindi inviato alla presentazione per la visualizzazione.

1

Metti il ​​try-catch nel punto in cui sei sicuro di non inghiottire l'eccezione. Se si riesce a garantire la coerenza, è possibile che i blocchi di try-catch multipli nei vari livelli siano corretti.

Ad esempio, è possibile mettere un try-catch nel livello di accesso ai dati per assicurarsi di pulire correttamente le connessioni.Ma dato che non puoi fare molto di più, probabilmente dovresti rilanciare l'eccezione.

Passando al livello aziendale, è possibile inserire try-catch su più operazioni del database che si desidera procedere in modo atomico. In questo caso, potrebbe essere necessario eseguire il rollback di tutto o mettere le cose in uno stato coerente, registrare l'eccezione da qualche parte. La deglutizione o il ripensamento dovrebbero essere decisi caso per caso.

Il livello di presentazione deve sempre rilevare tutte le eccezioni, che si tratti di un'applicazione Web, di uno script in esecuzione in un browser o di un'applicazione rich client. Potresti non essere in grado di comprendere completamente l'eccezione, ma almeno puoi assicurarti che la tua applicazione non muoia di fronte a un utente.

Naturalmente, è solo un consiglio. YMMV. :)

+0

Direi che se sei preoccupato di pulire le connessioni nel tuo DAL che dovresti usare i blocchi Try-Finally (o usando i blocchi) non Try-Catch. Non è necessario specificare un blocco Catch se si sta per rilanciare l'eccezione senza gestirla. –

+0

Oh sì. Le mie scuse, voglio dire provare finalmente, ma non ho notato. :( –

0

Quando ho un'architettura multistrato come questa (che è molto), ho spesso un tentativo/cattura in più di un livello. Ad esempio, un try/catch nel livello di persistenza che cattura una SQLException, fa ciò che il livello di persistenza deve fare (ad esempio, come notificare un amministratore, quindi genera una nuova eccezione che ha senso per un codice che chiama il livello di persistenza . Un esempio potrebbe essere PersistenceException. Il livello successivo non interessa a chi deve essere notificato di riavviare il database, ma si preoccupa che non possa salvare lo stato dell'utente, quindi potrebbe intercettare PersistenceException e dire all'utente che il suo nuovo numero di telefono non era " t memorizzato nel database.

3

Il mantra di gestione delle eccezioni è: "Lancia presto, cattura tardi". Vuoi catturare le eccezioni all'ultimo momento possibile, ma vuoi lanciarle immediatamente (non eseguire un ulteriore mucchio di elaborazione dopo aver determinato che qualcosa non va e quindi lanciare un'eccezione). Se non riesci a "gestire" l'eccezione, allora non prenderla.

Nella maggior parte dei casi, provare ... Infine, i blocchi dovrebbero essere molto più comuni nel codice rispetto a Try ... Catch.

-1

Si desidera solo utilizzare try catches per gestire il codice non gestito. Un esempio è che ho un oggetto COM con cui sto comunicando e non voglio che rimanga aperto e crei una perdita di memoria. L'altra alternativa accettabile consiste nel rilevare gli errori sugli eventi nel database prima di consentire l'eccezione per continuare.

Non si vuole mai utilizzare try catches per gestire situazioni in cui non si è sicuri che il codice funzionerà e si desidera un piano di backup.

Quindi, dove ti lascia quando esplodono le app, utilizza le pagine di errore personalizzate per indicare che si è verificato un problema nelle tue app Web e che i client di spessore analizzano il codice nei thread di lavoro in modo da non far saltare il thread principale se falliscono. In bocca al lupo!