Best practice per la gestione delle eccezioni in Java o C # [chiuso]


117

Sono bloccato a decidere come gestire le eccezioni nella mia applicazione.

Molto se i miei problemi con le eccezioni derivano da 1) accesso ai dati tramite un servizio remoto o 2) deserializzazione di un oggetto JSON. Sfortunatamente non posso garantire il successo per nessuna di queste attività (interruzione della connessione di rete, oggetto JSON non corretto che è fuori dal mio controllo).

Di conseguenza, se riscontro un'eccezione, la prendo semplicemente all'interno della funzione e restituisco FALSE al chiamante. La mia logica è che tutto ciò che interessa veramente al chiamante è se l'attività ha avuto successo, non perché non ha avuto successo.

Ecco un po 'di codice di esempio (in JAVA) di un metodo tipico)

public boolean doSomething(Object p_somthingToDoOn)
{
    boolean result = false;

    try{
        // if dirty object then clean
        doactualStuffOnObject(p_jsonObject);

        //assume success (no exception thrown)
        result = true;
    }
    catch(Exception Ex)
    {
        //don't care about exceptions
        Ex.printStackTrace();
    }
    return result;
}

Penso che questo approccio vada bene, ma sono davvero curioso di sapere quali sono le migliori pratiche per la gestione delle eccezioni (dovrei davvero bolla un'eccezione fino in fondo in uno stack di chiamate?).

In sintesi delle domande chiave:

  1. Va bene rilevare solo le eccezioni ma non pubblicizzarle o notificarle formalmente al sistema (tramite un registro o una notifica all'utente)?
  2. Quali sono le migliori pratiche per le eccezioni che non comportano tutto ciò che richiede un blocco try / catch?

Follow Up / Modifica

Grazie per tutto il feedback, ho trovato alcune eccellenti fonti sulla gestione delle eccezioni online:

Sembra che la gestione delle eccezioni sia una di quelle cose che variano in base al contesto. Ma soprattutto, si dovrebbe essere coerenti nel modo in cui gestiscono le eccezioni all'interno di un sistema.

Inoltre, fai attenzione al code-rot tramite troppi tentativi o catture o non dare ad un'eccezione il suo rispetto (un'eccezione sta avvertendo il sistema, cos'altro deve essere avvertito?).

Inoltre, questo è un bel commento di m3rLinEz .

Tendo ad essere d'accordo con Anders Hejlsberg e te sul fatto che alla maggior parte dei chiamanti interessa solo se l'operazione ha successo o meno.

Da questo commento emergono alcune domande su cui riflettere quando si tratta di eccezioni:

  • Qual è il punto che viene lanciata questa eccezione?
  • Come ha senso gestirlo?
  • Al chiamante interessa davvero l'eccezione o si preoccupa solo se la chiamata ha avuto successo?
  • Forzare un chiamante a gestire una potenziale eccezione è grazioso?
  • Stai rispettando gli idomi della lingua?
    • Hai davvero bisogno di restituire un flag di successo come booleano? Restituire booleano (o int) è più una mentalità C che Java (in Java gestiresti solo l'eccezione).
    • Segui i costrutti di gestione degli errori associati alla lingua :)!

Sebbene l'articolo della comunità Oracle sia in java, è un consiglio generico per una classe di linguaggi piuttosto ampia. Bell'articolo, proprio quello che stavo cercando.
Bunny Rabbit

Risposte:


61

Mi sembra strano che tu voglia catturare le eccezioni e trasformarle in codici di errore. Perché pensi che il chiamante preferirebbe i codici di errore rispetto alle eccezioni quando quest'ultima è l'impostazione predefinita sia in Java che in C #?

Per quanto riguarda le tue domande:

  1. Dovresti rilevare solo le eccezioni che puoi effettivamente gestire. Il solo rilevamento delle eccezioni non è la cosa giusta da fare nella maggior parte dei casi. Ci sono alcune eccezioni (ad esempio eccezioni di logging e marshalling tra thread) ma anche per quei casi dovresti generalmente rilanciare le eccezioni.
  2. Sicuramente non dovresti avere molte dichiarazioni try / catch nel tuo codice. Ancora una volta, l'idea è di catturare solo le eccezioni che puoi gestire. Puoi includere un gestore di eccezioni più in alto per trasformare qualsiasi eccezione non gestita in qualcosa di utile per l'utente finale, ma altrimenti non dovresti cercare di catturare ogni eccezione in ogni posto possibile.

Per quanto riguarda il motivo per cui qualcuno vorrebbe codici di errore invece di eccezioni ... Ho sempre pensato che fosse strano che HTTP utilizzi ancora codici di errore, anche se la mia applicazione sta generando un'eccezione. Perché HTTP non può permettermi di passare l'eccezione così com'è?
Trejkaz

il meglio che puoi fare è racchiudere i tuoi codici di errore in una monade
lindenrovio

@Trejkaz Non vuoi restituire i dettagli dell'eccezione agli utenti, perché questo è un rischio per la sicurezza. Questo è il motivo per cui i server HTML restituiscono codici di errore. È anche un problema di localizzazione restituire un messaggio di errore e probabilmente rende l'HTML più grande e più lento da restituire. Tutti questi sono i motivi per cui penso che i server HTML restituiscano codici di errore.
Didier A.

Penso che sia meglio dire: "Dovresti sopprimere solo le eccezioni che puoi effettivamente gestire".
Didier A.

@didibus Perché pensi che i problemi di sicurezza dovrebbero creare un inconveniente nello sviluppo? Non ho mai detto nulla sulla produzione. Per quanto riguarda la localizzazione dei messaggi di errore, l'intero sito web ha già quel problema e le persone sembrano farcela.
Trejkaz

25

Dipende dall'applicazione e dalla situazione. Se stai costruendo un componente di libreria, dovresti far apparire le eccezioni, sebbene dovrebbero essere incluse per essere contestuali con il tuo componente. Ad esempio, se stai creando un database Xml e diciamo che stai utilizzando il file system per archiviare i tuoi dati e stai utilizzando le autorizzazioni del file system per proteggere i dati. Non vorresti creare un'eccezione FileIOAccessDenied poiché perde la tua implementazione. Invece dovresti racchiudere l'eccezione e generare un errore AccessDenied. Ciò è particolarmente vero se distribuisci il componente a terzi.

E se va bene inghiottire le eccezioni. Dipende dal tuo sistema. Se la tua applicazione è in grado di gestire i casi di errore e non vi è alcun vantaggio nel notificare all'utente perché non è riuscito, vai avanti, anche se ti consiglio vivamente di registrare l'errore. Ho sempre trovato frustrante essere chiamato per aiutare a risolvere un problema e scoprire che stavano inghiottendo l'eccezione (o sostituendola e lanciarne una nuova invece senza impostare l'eccezione interna).

In generale utilizzo le seguenti regole:

  1. Nei miei componenti e librerie rilevo un'eccezione solo se intendo gestirla o fare qualcosa basato su di essa. O se desidero fornire ulteriori informazioni contestuali in un'eccezione.
  2. Uso un tentativo generale di cattura al punto di ingresso dell'applicazione o il livello più alto possibile. Se arriva un'eccezione, la registro e la lascio fallire. Idealmente le eccezioni non dovrebbero mai arrivare qui.

Trovo che il seguente codice sia un odore:

try
{
    //do something
}
catch(Exception)
{
   throw;
}

Un codice come questo non ha senso e non dovrebbe essere incluso.


@ Josh, buon punto sulla deglutizione delle eccezioni, ma credo che ci siano pochi casi in cui è accettabile semplicemente ingoiare le eccezioni. Nell'ultimo progetto il tuo snippet di codice era obbligatorio, puzzava. Registrarli tutti ha peggiorato le cose, Il mio consiglio, se non puoi gestire l'eccezione cerca di non ingoiarla.
smaclell

D'accordo come ho detto, tutto dipende dall'app e dal contesto specifico. Ci sono volte in cui ingoio eccezioni anche se è raro, e non riesco a ricordare l'ultima volta che l'ho fatto ;-) Probabilmente è stato quando stavo scrivendo il mio logger, e la scrittura sul log e il log secondario non è riuscito.
JoshBerke

Il codice serve a un punto: è possibile impostare un punto di interruzione al "lancio".
Rauhotz

3
Punto debole, puoi dire a VS di interrompere qualsiasi eccezione generata oppure puoi restringere il campo e scegliere un'eccezione specifica. In VS2008 è presente una voce di menu in fase di debug (sarà necessario personalizzare le barre degli strumenti per trovarla) Chiamate eccezioni
JoshBerke

L'esempio "odore di codice" ha un effetto collaterale definito, anche in quella forma semplice. Se // do somethinginclude try/finallyblocchi attorno al punto che genera, i finallyblocchi verranno eseguiti prima del catchblocco. Senza il try/catch, l'eccezione volerà fino in cima allo stack senza finallyche vengano eseguiti blocchi. Ciò consente al gestore di primo livello di decidere se eseguire o meno i finallyblocchi.
Daniel Earwicker,

9

Vorrei raccomandare un'altra buona fonte sull'argomento. È un'intervista con gli inventori di C # e Java, rispettivamente Anders Hejlsberg e James Gosling, sul tema dell'eccezione verificata di Java.

Fallimento ed eccezioni

Ci sono anche ottime risorse in fondo alla pagina.

Tendo ad essere d'accordo con Anders Hejlsberg e te sul fatto che alla maggior parte dei chiamanti interessa solo se l'operazione ha successo o meno.

Bill Venners : Hai menzionato problemi di scalabilità e controllo delle versioni rispetto alle eccezioni controllate. Potresti chiarire cosa intendi con questi due problemi?

Anders Hejlsberg : Cominciamo con il controllo delle versioni, perché i problemi sono abbastanza facili da vedere lì. Diciamo che creo un metodo foo che dichiara che genera le eccezioni A, B e C.Nella versione due di foo, voglio aggiungere un mucchio di funzionalità, e ora foo potrebbe lanciare l'eccezione D.È un cambiamento radicale per me aggiungi D alla clausola throws di quel metodo, perché il chiamante esistente di quel metodo quasi certamente non gestirà quell'eccezione.

L'aggiunta di una nuova eccezione a una clausola throws in una nuova versione interrompe il codice client. È come aggiungere un metodo a un'interfaccia. Dopo aver pubblicato un'interfaccia, è immutabile per tutti gli scopi pratici, perché qualsiasi implementazione di essa potrebbe avere i metodi che si desidera aggiungere nella versione successiva. Quindi devi invece creare una nuova interfaccia. Allo stesso modo con le eccezioni, dovresti creare un metodo completamente nuovo chiamato foo2 che genera più eccezioni, oppure dovresti catturare l'eccezione D nel nuovo foo e trasformare la D in una A, B o C.

Bill Venners : Ma non stai comunque violando il loro codice in quel caso, anche in una lingua senza eccezioni controllate? Se la nuova versione di foo lancerà una nuova eccezione che i clienti dovrebbero pensare di gestire, il loro codice non è rotto solo dal fatto che non si aspettavano quell'eccezione quando hanno scritto il codice?

Anders Hejlsberg : No, perché in molti casi alle persone non interessa. Non gestiranno nessuna di queste eccezioni. C'è un gestore di eccezioni di livello inferiore attorno al loro ciclo di messaggi. Quel gestore aprirà solo una finestra di dialogo che dice cosa è andato storto e continua. I programmatori proteggono il loro codice scrivendo finalmente try è ovunque, quindi torneranno indietro correttamente se si verifica un'eccezione, ma in realtà non sono interessati a gestire le eccezioni.

La clausola throws, almeno per come è implementata in Java, non ti obbliga necessariamente a gestire le eccezioni, ma se non le gestisci, ti obbliga a riconoscere con precisione quali eccezioni potrebbero passare. Richiede di catturare le eccezioni dichiarate o inserirle nella propria clausola throws. Per aggirare questo requisito, le persone fanno cose ridicole. Ad esempio, decorano ogni metodo con "genera eccezione". Questo sconfigge completamente la funzionalità e hai appena fatto scrivere al programmatore più gunk gobbledy. Questo non aiuta nessuno.

EDIT: Aggiunti ulteriori dettagli sulla conversione


Grazie per questo! Ho aggiornato la mia domanda con informazioni sulla tua risposta!
AtariPete

Sembra che il signor Hejlsberg stia giustificando la gestione delle eccezioni dei Pokemon. Uno degli enormi problemi con la progettazione delle eccezioni in Java e C # è che troppe informazioni sono codificate nel tipo di eccezione, mentre le informazioni dovrebbero essere archiviate in istanze di eccezione non sono disponibili in alcun modo coerente. Le eccezioni dovrebbero propagarsi nello stack di chiamate fino a quando tutte le condizioni anomale rappresentate in tal modo non sono state risolte; purtroppo, il tipo di eccezione - anche se riconosciuta - fa poco per indicare se una situazione è risolta. Se un'eccezione non viene riconosciuta ...
supercat

... la situazione è anche peggiore. Se il codice chiama FetchDatae genera un'eccezione di un tipo inaspettato, non ha modo di sapere se tale eccezione significa semplicemente che i dati non sono disponibili (nel qual caso la capacità del codice di cavarsela senza di esso lo "risolverebbe"), o se significa che la CPU è in fiamme e il sistema dovrebbe eseguire un "arresto di sicurezza" alla prima occasione. Sembra che il signor Hejlsberg stia suggerendo che il codice dovrebbe assumere il primo; forse questa è la migliore strategia possibile date le gerarchie di eccezioni esistenti, ma sembra comunque icky.
supercat

Sono d'accordo che i lanci Exceptin siano ridicoli, perché quasi tutto può generare un'eccezione, dovresti semplicemente presumere che ciò possa accadere. Ma quando specifichi eccezioni come i lanci A, B, C, è solo un'annotazione, per me dovrebbe essere usata come un blocco di commenti. È come dire, ehi cliente della mia funzione, ecco un suggerimento, forse vuoi occuparti di A, B, C, perché è probabile che questi errori si verifichino quando mi usi. Se aggiungi D in futuro, non è un grosso problema se non viene affrontato, ma è come aggiungere nuova documentazione, Oh a proposito, ora sarebbe anche utile catturare D.
Didier A.

8

Le eccezioni verificate sono una questione controversa in generale, e in Java in particolare (più avanti cercherò di trovare alcuni esempi per coloro che sono favorevoli e contrari).

Come regole pratiche, la gestione delle eccezioni dovrebbe essere qualcosa attorno a queste linee guida, in nessun ordine particolare:

  • Per motivi di manutenibilità, registra sempre le eccezioni in modo che quando inizi a vedere i bug, il registro ti aiuterà a indicarti il ​​punto in cui probabilmente è iniziato il bug. Non andartene mai printStackTrace()o cose del genere, è probabile che uno dei tuoi utenti alla fine ottenga una di quelle tracce dello stack e abbia esattamente zero conoscenze su cosa farne.
  • Cattura le eccezioni che puoi gestire, e solo quelle, e gestiscile , non limitarti a gettarle nella pila.
  • Cattura sempre una classe di eccezione specifica e generalmente non dovresti mai catturare il tipo Exception, è molto probabile che ingoierai eccezioni altrimenti importanti.
  • Mai (mai) prendere Errors !! , che significa: non prendere mai Throwables in quanto Errors sono sottoclassi di quest'ultima. Errorsono problemi che molto probabilmente non sarai mai in grado di gestire (ad esempio OutOfMemory, o altri problemi di JVM)

Per quanto riguarda il tuo caso specifico, assicurati che qualsiasi client che chiama il tuo metodo riceva il valore di ritorno corretto. Se qualcosa fallisce, un metodo di ritorno booleano potrebbe restituire false, ma assicurati che i posti che chiami quel metodo siano in grado di gestirlo.


Le eccezioni controllate non sono un problema in C # perché non le ha.
cletus

3
Imho, a volte è utile rilevare errori: ricordo un'app Java che richiede molta memoria che ho scritto. Ho preso OutOfMemory-Ex e ho mostrato un messaggio all'utente che ha esaurito la memoria, che avrebbe dovuto chiudere altri programmi e gli ho detto come avviare la jvm con più spazio heap assegnato. Immagino sia stato d'aiuto.
Lena Schimmel

5

Dovresti cogliere solo le eccezioni che puoi affrontare. Ad esempio, se hai a che fare con la lettura su una rete e la connessione scade e ottieni un'eccezione, puoi riprovare. Tuttavia, se stai leggendo su una rete e ottieni un'eccezione IndexOutOfBounds, non puoi davvero gestirlo perché non (beh, in questo caso non saprai) cosa l'ha causato. Se stai per restituire false o -1 o null, assicurati che sia per eccezioni specifiche. Non voglio che una libreria che sto usando restituisca un falso su una lettura di rete quando l'eccezione generata è che l'heap ha esaurito la memoria.


3

Le eccezioni sono errori che non fanno parte della normale esecuzione del programma. A seconda di ciò che fa il tuo programma e dei suoi usi (es. Un elaboratore di testi rispetto a un monitor cardiaco) vorrai fare cose diverse quando incontri un'eccezione. Ho lavorato con codice che utilizza le eccezioni come parte della normale esecuzione ed è sicuramente un odore di codice.

Ex.

try
{
   sendMessage();

   if(message == success)
   {
       doStuff();
   }
   else if(message == failed)
   {
       throw;
   }
}
catch(Exception)
{
    logAndRecover();
}

Questo codice mi fa barf. IMO non dovresti recuperare dalle eccezioni a meno che non sia un programma critico. Se lanci eccezioni, stanno accadendo cose brutte.


2

Tutto quanto sopra sembra ragionevole e spesso il tuo posto di lavoro potrebbe avere una politica. Al nostro posto abbiamo definito i tipi di Eccezione: SystemException(deselezionata) e ApplicationException(selezionata).

Abbiamo convenuto che SystemExceptionè improbabile che siano recuperabili e che saranno gestiti una volta in cima. Per fornire ulteriore contesto, i nostri SystemExceptions sono exteneded per indicare dove si sono verificati, per esempio RepositoryException, ServiceEceptionecc

ApplicationExceptions potrebbe avere un significato commerciale come InsufficientFundsExceptione dovrebbe essere gestito dal codice client.

Senza un esempio concreto, è difficile commentare la tua implementazione, ma non userei mai codici di ritorno, sono un problema di manutenzione. Potresti ingoiare un'eccezione, ma devi decidere perché e registrare sempre l'evento e lo stacktrace. Infine, poiché il tuo metodo non ha altre elaborazioni, è abbastanza ridondante (tranne che per l'incapsulamento?), Quindi doactualStuffOnObject(p_jsonObject);potrebbe restituire un booleano!


1

Dopo un po 'di riflessione e guardando il tuo codice mi sembra che tu stia semplicemente rilanciando l'eccezione come booleano. Potresti semplicemente lasciare che il metodo passi questa eccezione (non devi nemmeno catturarla) e gestirla nel chiamante, poiché è lì che conta. Se l'eccezione indurrà il chiamante a ritentare questa funzione, il chiamante dovrebbe essere colui che intercetta l'eccezione.

A volte può accadere che l'eccezione che stai incontrando non abbia senso per il chiamante (cioè è un'eccezione di rete), nel qual caso dovresti racchiuderla in un'eccezione specifica del dominio.

Se d'altra parte, l'eccezione segnala un errore irrecuperabile nel tuo programma (cioè il risultato finale di questa eccezione sarà la chiusura del programma), personalmente mi piace renderlo esplicito catturandolo e lanciando un'eccezione di runtime.


1

Se intendi utilizzare il modello di codice nel tuo esempio, chiamalo TryDoSomething e cattura solo eccezioni specifiche.

Considerare anche l' utilizzo di un filtro eccezioni durante la registrazione delle eccezioni per scopi diagnostici. VB ha il supporto della lingua per i filtri di eccezione. Il collegamento al blog di Greggm ha un'implementazione che può essere utilizzata da C #. I filtri di eccezione hanno proprietà migliori per il debug rispetto a catch e rethrow. In particolare, puoi registrare il problema nel filtro e lasciare che l'eccezione continui a propagarsi. Questo metodo consente a un debugger JIT (Just in Time) di collegare lo stack originale completo. Un rilancio taglia lo stack nel punto in cui è stato rilanciato.

I casi in cui TryXXXX ha senso sono quando si esegue il wrapping di una funzione di terze parti che genera casi che non sono veramente eccezionali o sono semplicemente difficili da testare senza chiamare la funzione. Un esempio potrebbe essere qualcosa di simile:

// throws NumberNotHexidecimalException
int ParseHexidecimal(string numberToParse); 

bool TryParseHexidecimal(string numberToParse, out int parsedInt)
{
     try
     {
         parsedInt = ParseHexidecimal(numberToParse);
         return true;
     }
     catch(NumberNotHexidecimalException ex)
     {
         parsedInt = 0;
         return false;
     }
     catch(Exception ex)
     {
         // Implement the error policy for unexpected exceptions:
         // log a callstack, assert if a debugger is attached etc.
         LogRetailAssert(ex);
         // rethrow the exception
         // The downside is that a JIT debugger will have the next
         // line as the place that threw the exception, rather than
         // the original location further down the stack.
         throw;
         // A better practice is to use an exception filter here.
         // see the link to Exception Filter Inject above
         // http://code.msdn.microsoft.com/ExceptionFilterInjct
     }
}

Che tu usi uno schema come TryXXX o meno è più una questione di stile. La questione di cogliere tutte le eccezioni e inghiottirle non è una questione di stile. Assicurati che le eccezioni inaspettate possano propagarsi!


Adoro il pattern TryXXX in .net.
JoshBerke

1

Suggerisco di prendere spunto dalla libreria standard per la lingua che stai utilizzando. Non posso parlare per C #, ma diamo un'occhiata a Java.

Ad esempio java.lang.reflect.Array ha un setmetodo statico :

static void set(Object array, int index, Object value);

Il modo C sarebbe

static int set(Object array, int index, Object value);

... con il valore restituito come indicatore di successo. Ma non sei più nel mondo C.

Una volta accettate le eccezioni, dovresti scoprire che rende il tuo codice più semplice e chiaro, spostando il codice di gestione degli errori lontano dalla logica di base. Cerca di avere molte affermazioni in un unico tryblocco.

Come altri hanno notato, dovresti essere il più specifico possibile nel tipo di eccezione che intercetti.


questo è un commento molto valido, sii rispettoso della lingua e di come tradizionalmente gestisce tali questioni. Non portare una mentalità C in un mondo Java.
AtariPete

0

Se intendi rilevare un'eccezione e restituire false, dovrebbe essere un'eccezione molto specifica. Non lo fai, li prendi tutti e restituisci falsi. Se ricevo un'eccezione MyCarIsOnFireException, voglio saperlo subito! Il resto delle eccezioni potrebbe non interessarmi. Quindi dovresti avere uno stack di gestori di eccezioni che dicono "whoa whoa qualcosa non va qui" per alcune eccezioni (rilancia, o cattura e rilancia una nuova eccezione che spiega meglio cosa è successo) e restituisce falso per gli altri.

Se questo è un prodotto che lancerai, dovresti registrare quelle eccezioni da qualche parte, ti aiuterà a mettere a punto le cose in futuro.

Modifica: per quanto riguarda la questione di avvolgere tutto in una prova / cattura, penso che la risposta sia sì. Le eccezioni dovrebbero essere così rare nel codice che il codice nel blocco catch viene eseguito così raramente da non raggiungere affatto le prestazioni. Un'eccezione dovrebbe essere uno stato in cui la tua macchina a stati si è rotta e non sa cosa fare. Almeno rilancia un'eccezione che spiega cosa stava succedendo in quel momento e contiene l'eccezione catturata al suo interno. "Eccezione nel metodo doSomeStuff ()" non è molto utile per chi deve capire perché si è rotto mentre sei in vacanza (o in un nuovo lavoro).


Non dimenticare che anche la configurazione di un blocco di eccezioni costa ...
devstuff

0

La mia strategia:

Se la funzione originale restituiva void, la cambio per restituire bool . Se si è verificata un'eccezione / errore, restituisce falso , se tutto è andato bene restituisce vero .

Se la funzione deve restituire qualcosa, quando si verifica un'eccezione / errore restituisce null , altrimenti l'elemento restituibile.

Invece di bool, potrebbe essere restituita una stringa contenente la descrizione dell'errore.

In ogni caso prima di restituire qualsiasi cosa registrare l'errore.


0

Alcune ottime risposte qui. Vorrei aggiungere che se ti ritrovi con qualcosa come hai pubblicato, almeno stampa più della traccia dello stack. Dì cosa stavi facendo in quel momento ed Es. GetMessage (), per dare allo sviluppatore una possibilità di combattere.


sono completamente d'accordo. Ho eseguito solo Ex.printStackTrace (); come esempio di qualcosa che stavo facendo nella cattura (cioè non rilanciando).
AtariPete

0

I blocchi try / catch formano un secondo set di logica incorporata nel primo set (principale), in quanto tali sono un ottimo modo per eliminare il codice spaghetti illeggibile e difficile da eseguire il debug.

Tuttavia, usati ragionevolmente fanno miracoli in termini di leggibilità, ma dovresti semplicemente seguire due semplici regole:

  • usarli (con parsimonia) a basso livello per rilevare i problemi di gestione delle librerie e trasmetterli nuovamente al flusso logico principale. La maggior parte della gestione degli errori che vogliamo, dovrebbe provenire dal codice stesso, come parte dei dati stessi. Perché fare condizioni speciali, se i dati di ritorno non sono speciali?

  • utilizzare un unico grande gestore al livello superiore per gestire alcune o tutte le condizioni strane che si verificano nel codice che non sono catturate a un livello basso. Fare qualcosa di utile con gli errori (log, riavvii, ripristini, ecc.).

Oltre a questi due tipi di gestione degli errori, tutto il resto del codice nel mezzo dovrebbe essere libero e privo di codice try / catch e oggetti di errore. In questo modo, funziona in modo semplice e come previsto, indipendentemente da dove lo usi o cosa ne fai.

Paolo.


0

Potrei essere un po 'in ritardo con la risposta, ma la gestione degli errori è qualcosa che possiamo sempre cambiare ed evolvere nel tempo. Se vuoi leggere qualcosa di più su questo argomento ho scritto un post nel mio nuovo blog a riguardo. http://taoofdevelopment.wordpress.com

Buona codifica.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.