Domanda

Stiamo esaminando una delle eccezioni del sistema aziendale e abbiamo trovato un paio di cose interessanti.

La maggior parte dei blocchi di codice (se non tutti) si trovano all'interno di un blocco try / catch e all'interno del blocco catch viene lanciata una nuova BaseApplicationException - che sembra provenire dalle librerie Enterprise. Sono un po 'nei guai qui perché non vedo i vantaggi di farlo. (generare un'altra eccezione ogni volta che si verifica) Uno degli sviluppatori che ha utilizzato il sistema per un po 'ha detto che è perché quella classe è responsabile della pubblicazione dell'eccezione (invio di e-mail e cose del genere) ma non ne era troppo sicuro. Dopo aver passato un po 'di tempo a leggere il codice, sono abbastanza sicuro di dire che non fa altro che raccogliere informazioni sull'ambiente e pubblicarle.

La mia domanda è:  - È ragionevole racchiudere tutto il codice all'interno di provare i blocchi {} catch {} e lanciare una nuova eccezione? E se lo è, perché? Qual è il vantaggio?

La mia opinione personale è che sarebbe molto più facile usare un HttpModule, iscriversi all'evento Error dell'evento Application e fare ciò che è necessario all'interno del modulo. Se percorressimo questa strada, ci perderemmo qualcosa? Qualche inconveniente?

La tua opinione è molto apprezzata.

È stato utile?

Soluzione

Nonostante 1 catch (Exception ex) . Periodo 2 . Non è possibile gestire tutti i diversi tipi di errori che è possibile rilevare.

Non 3 non rileva mai un tipo derivato da Eccezione se non è possibile gestirlo o fornire informazioni aggiuntive (che verranno utilizzate dai successivi gestori delle eccezioni). La visualizzazione di un messaggio di errore è non uguale a gestione dell'errore.

Un paio di ragioni per questo, dalla cima della mia testa:

  • Catturare e ricrescere è costoso
  • Alla fine perderai la traccia dello stack
  • Avrai un basso rapporto segnale-rumore nel tuo codice

Se sai come gestire un'eccezione specifica (e reimpostare l'applicazione allo stato pre-errore), rilevala. (Ecco perché si chiama eccezione manipolazione .

Per gestire le eccezioni che non vengono rilevate, attendere gli eventi appropriati. Quando esegui WinForms, dovrai ascoltare System.AppDomain.CurrentDomain.UnhandledException e, se stai eseguendo Threading - System.Windows.Forms.Application .ThreadException. Per le app Web, esistono meccanismi simili ( System.Web.HttpApplication.Error ).

Per quanto riguarda il wrapping delle eccezioni del framework nell'applicazione (non) eccezioni specifiche (ad es. lancia la nuova MyBaseException (ex); ): assolutamente inutile e un cattivo odore. 4


Modifica

1 Mai è una parola molto dura, specialmente quando si tratta di ingegneria, come ha sottolineato @Chris nei commenti. Devo ammettere di essere alto sui principi quando ho scritto per la prima volta questa risposta.

2,3 Vedi 1 .

4 Se non porti nulla di nuovo sul tavolo, resto ancora qui. Se hai individuato Exception ex come parte di un metodo che sai che potrebbe non riuscire in molti modi, credo che l'attuale metodo dovrebbe rispecchiarlo nella sua firma. E come sai, le eccezioni non fanno parte della firma del metodo.

Altri suggerimenti

Se sto leggendo correttamente la domanda, direi che l'implementazione di un try / catch che intercetta le eccezioni (non menzionate - sta rilevando tutte le eccezioni o solo una specifica?) e genera un'eccezione diversa è generalmente una brutta cosa.

Svantaggi:

Almeno perderai le informazioni di traccia dello stack - lo stack che vedrai si estenderà solo al metodo in cui viene generata la nuova eccezione - potresti perdere alcune buone informazioni di debug qui.

Se stai rilevando un'eccezione, stai correndo il rischio di mascherare le eccezioni critiche, come OutOfMemory o StackOverflow con un'eccezione meno critica, lasciando così il processo in esecuzione, dove forse avrebbe dovuto essere abbattuto.

Possibili vantaggi:

In alcuni casi molto specifici potresti prendere un'eccezione che non ha molto valore di debug (come alcune eccezioni che ritornano da un database) e racchiudere un'eccezione che aggiunge più contesto, ad es. id dell'oggetto che hai a che fare con .

Tuttavia, in quasi tutti i casi si tratta di un cattivo odore e deve essere usato con cautela.

Generalmente dovresti prendere un'eccezione solo quando c'è qualcosa di realistico che puoi fare in quella posizione, ad esempio recuperare, tornare indietro, andare al piano B ecc. Se non c'è nulla che puoi fare al riguardo, lascia che passi su per la catena. Dovresti prendere e lanciare una nuova eccezione solo se ci sono dati specifici e utili disponibili in quella posizione che possono aumentare l'eccezione originale e quindi aiutare il debug.

Vengo dalla scuola di pensiero dove dovrebbero essere usati i blocchi try / catch e le eccezioni non devono essere riproposte. Se si sta eseguendo un codice che potrebbe essere un errore, è necessario gestirlo, registrarlo e restituire qualcosa. Il rilancio dell'eccezione serve solo a ripetere il log in un secondo momento nel ciclo di vita dell'applicazione.

Ecco un post interessante su come utilizzare un HttpModule per gestire le eccezioni: http://blogs.msdn.com/rahulso/archive/2008/07/13/how-to-use-httpmodules-to -troubleshoot-your-asp-net-application.aspx e http://blogs.msdn.com/rahulso/archive/2008/07/18 /asp-net-how-to-write-error-messages-into-a-text-file-using-a-simple-httpmodule.aspx

Scopri ELMAH . Fa quello di cui stai parlando. Ottimo.

Quando creo librerie provo sempre a fornire un numero ridotto di eccezioni che i chiamanti possono gestire. Ad esempio, pensa a un componente Repository che si connette a un database sql. Ci sono tonnellate di eccezioni, dalle eccezioni client sql alle eccezioni cast non valide, che in teoria possono essere lanciate. Molti di questi sono chiaramente documentati e possono essere contabilizzati in fase di compilazione. Quindi ne prendo il maggior numero possibile, li inserisco in un unico tipo di eccezione, dico RepositoryException e lascio che tale eccezione arrotoli lo stack di chiamate.

L'eccezione originale viene mantenuta, pertanto è possibile diagnosticare l'eccezione originale. Ma i miei chiamanti devono solo preoccuparsi di gestire un solo tipo di eccezione piuttosto che sporcare il loro codice con tonnellate di blocchi di cattura diversi.

Ci sono, ovviamente, alcuni problemi con questo. In particolare, se il chiamante è in grado di gestire alcune di queste eccezioni, deve eseguire il root in RepositoryException e quindi attivare il tipo di eccezione interna per gestirlo. È meno pulito di avere un singolo blocco catch per un singolo tipo di eccezione. Non penso che questo sia un grosso problema.

Sembra che l'eccezione generata non debba essere implementata come eccezione.

Direi comunque che, poiché questa BaseApplicationException è un'eccezione generale per tutti gli usi, sarebbe bene generare eccezioni più specifiche al contesto. Pertanto, quando si tenta di recuperare un'entità da un database, è possibile che si desideri un EntityNotFoundException. In questo modo durante il debug non è necessario cercare tra le eccezioni interne e impilare le tracce per trovare il vero problema. Se questo BAseApplicationException sta raccogliendo informazioni sull'eccezione (come tenere traccia dell'eccezione interna), questo non dovrebbe essere un problema.

Vorrei utilizzare HttpModule solo quando non riuscivo ad avvicinarmi a dove in realtà si verificano le eccezioni nel codice. Non vuoi davvero un evento HttModule OnError che è un'enorme istruzione switch a seconda delle informazioni di errore di BaseApplicationexception.

Per concludere, vale la pena lanciare diverse eccezioni quando puoi dare eccezioni più specifiche che ti diano subito la radice del problema.

Dalla mia esperienza, cattura l'eccezione, aggiungi l'errore all'oggetto Server (?). Ciò consentirà a .NET di fare tutto ciò che deve fare, quindi visualizzare la tua eccezione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top