Perché dovrei scrivere tutte le dichiarazioni all'interno di Try-Catch?


12

Il mio capo dell'azienda dice che devo scrivere tutto, cioè TUTTO il mio codice all'interno delle dichiarazioni Try-catch. Ora riesco a capire l'approccio "meglio prevenire che curare" qui, ma non è forse troppo sincero pensare che ci sarà un'eccezione quando le etichette saranno create, la posizione del modulo è impostata. ci sono stati casi in cui Eccezioni in operazioni così semplici.


4
Questo suona come un brusio delle stesse persone che affermano che tutto l' SQL dovrebbe essere scritto come stored procedure per migliorare le prestazioni.
spong

5
Preferiresti "Se il tuo codice crea un errore di runtime, sei licenziato". Il gioco del pollo è divertente finché non vedi il tuo avversario lanciare il volante e il pedale del freno fuori dal finestrino.
JeffO,

4
@Jeff O - In realtà credo che nello sviluppo del software l'avversario sia un treno merci.
Joris Timmermans,

5
L'espressione migliore che ho sentito per questo stile di gestione delle eccezioni è "Inchiodare il cadavere in posizione verticale", nel senso che lascia l'applicazione in uno stato inaspettato. Fail Fast, Fail Loudly è un approccio molto più moderno, quindi puoi effettivamente risolvere tutti i bug.
Brook,

2
L'oggetto della richiesta è irrilevante ... solo dire "il mio capo dell'azienda dice che dovrei codificare ..." è una grande bandiera rossa. È microgestione ... questo non è il suo lavoro.
JoelFan,

Risposte:


14

Il mio capo dell'azienda dice che devo scrivere tutto, cioè TUTTO il mio codice all'interno delle dichiarazioni Try-catch.

Bene, questo è un po 'esagerato e porta solo a un codice rumoroso. Quali sono i vantaggi di avere tutto il codice (ad esempio ogni metodo) scritto con un gestore try catch? Ti dice solo che c'è un errore da correggere nella maggior parte dei casi. Spesso, l'eccezione può e dovrebbe essere evitata in primo luogo.

Uno sguardo alla traccia dello stack è per lo più sufficiente per rivelare la causa nel codice, anche se il metodo di errore non esegue il catch stesso. Ci sono momenti in cui gli sviluppatori corrompono le tracce dello stack in eccezioni, ma questo è molto più spesso il caso in cui ci sono molti gestori di eccezioni. Come qualsiasi cosa: un po 'va bene, ma troppo è veleno.

La gestione delle eccezioni è davvero piuttosto semplice:

Eccezioni di cattura

  • ogni volta che hai bisogno di un'azione speciale come reazione all'eccezione
  • ogni volta che un'eccezione lascia il programma in uno stato incoerente se non gestita

Se ci pensate, allora c'è sempre solo un posto che è buono per gestire un'eccezione che si verifica. E quindi il gestore dovrebbe trovarsi in quel posto.

Molte eccezioni non dovrebbero nemmeno essere lanciate in primo luogo, quindi non costruire le tue strutture di controllo attorno alla gestione delle eccezioni, piuttosto cerca di evitare il possibile verificarsi di eccezioni quando e dove possibile.

Ricorda di schiantarti presto quando le cose vanno (irreparabilmente) sbagliate. Inserire tutto il codice nelle istruzioni try-catch è assurdo, ma non dimenticare di segnalare e registrare TUTTE le eccezioni.


+1 Non solo porta a un codice rumoroso, ma anche a prestazioni peggiori. Quando metti le dichiarazioni in un blocco try, il compilatore HotSpot non sarà in grado di applicare ottimizzazioni che altrimenti farebbe.
Oliver Weiler,

@Oliver Weiler: hai una citazione che spiega quali ottimizzazioni non compie il compilatore HotSpot nei blocchi try / catch?
Kaypro II,

16

ma non è troppo sincero pensare che ci sarà un'eccezione quando si creano le etichette, la posizione del modulo è impostata. ci sono stati casi in cui Eccezioni in operazioni così semplici.

Assolutamente si! C'è sempre un modo in cui le cose vanno male che non avevi previsto. E "dal cuore di pollo" è un'espressione ridicola da usare in questo contesto; lo sviluppo del software non consiste nel provare il tuo machismo ignorando potenziali problemi.

Qual è una domanda valida è se è utile rilevare le eccezioni nel punto in cui gli standard di codifica dicono che devono. La tua affermazione dice che devi avere un blocco try / catch attorno a ogni metodo metodo, e questo è davvero assurdo perché spesso non puoi fare immediatamente qualcosa di utile con un'eccezione, e questo è in realtà il punto intero delle eccezioni: che puoi scegliere di lasciarli propagare lo stack di chiamate da trattare nel punto appropriato.


13
Le mie app sanno meglio che generare eccezioni o avranno i battiti della loro vita. Una volta che pensano che tu abbia il cuore di pollo, si schiantano su di te.
JeffO,

@Michael Borgwardt: hehe, quindi mi hai sottovalutato. Hai annullato il voto su questa domanda e l'unico voto negativo è sul mio post. Sembra che tu abbia un serio problema con il tuo ego o la tua autostima. L'ho notato anche su altre domande. Sai, anche altri programmatori hanno buone risposte.
Falcon,

@Falcon: non ho votato minimamente su questa domanda. Non ho idea di cosa ti spinga a credere diversamente, ma se qualcuno ha un grave problema di ego, sei tu.
Michael Borgwardt,

@Michael Borwardt: Forse mi sbaglio. In tal caso mi scuso. Potrebbe essere questo il solo voto negativo sulla tua domanda che mi ha fatto pensare che tu abbia votato qui. Scusa.
Falcon,

8

Vorrei ribaltare il contrario. Sì, come regola generale la gestione delle eccezioni è una buona cosa, ma puoi effettivamente gestire ogni possibile eccezione in modo sensato nel punto in cui viene rilevata? A volte, in particolare se non stai scrivendo software mission-critical, è meglio semplicemente schiantarsi e bruciare in un modo controllato a metà strada quando le cose vanno terribilmente male.

Se non puoi essere sicuro al 100% di poter gestire ogni singola eccezione che potrebbe essere rilevata, probabilmente stai meglio scrivendo una sorta di gestore di eccezioni generale, avvolgendo il ciclo principale del programma in esso - l'esatta meccanica di come farlo ovviamente dipende dalla lingua in cui stai lavorando. Lì, registra quanti più dettagli possibile sull'eccezione, salva lo stato del programma (in un posto diverso da qualsiasi archivio di dati su cui l'utente sta attualmente lavorando - ricorda, a questo punto potrebbe essere tutto corrotto ), e così via. Quindi, ripeti l'eccezione e lascia che il sistema operativo la gestisca come ritiene opportuno. In questo gestore di eccezioni onnicomprensivo, prepararsi per un errore irreversibile. Quindi, quando il programma viene riavviato, controlla se questo stato è in qualche modo utile e ripristina ciò che può essere recuperato se lo è; e possibilmente offrire all'utente di inviarti una segnalazione di bug.


5
+1: non prendere mai un'eccezione se non puoi affrontarla immediatamente correttamente. (Ahimè, a volte devi intrappolarlo solo per lasciarlo vagare di nuovo ma taggato come un tipo diverso, come parte del coercing API: lo odio.)
Donal Fellows

6

Nel complesso, l'utilizzo di try / catch è deprecato, poiché il blocco catch è così costoso dal punto di vista delle risorse. L'utilizzo di Try / catch mi ricorda la gestione del rischio . La gestione dei rischi ha due dimensioni:

  1. La probabilità che si verifichi un rischio
  2. Il danno che può avere

Ora, se esci di casa, un piano che ti cade in testa da qualche parte mentre è così improbabile che accada (forse 0,001%), ma può ucciderti.

La gestione delle eccezioni è così. Try block non è costoso. Ma il blocco catch è davvero costoso, perché deve creare una tabella di stack stack e fare altre cose. Pertanto, nel prendere una decisione sui blocchi try / catch, dovresti considerare quante volte probabilmente colpisci il blocco catch. Se tra 10.000 usi, lo colpisci solo 1 volta, quindi utilizzalo. Ma se si tratta di un modulo e l'utente probabilmente non lo riempie correttamente per il 50% di volte, allora dovresti evitare di mettere in atto un blocco try / catch.

Nei luoghi in cui la probabilità di verificarsi di un'eccezione è elevata, si consiglia di utilizzare i if {} else {}blocchi per evitare il verificarsi di eccezioni. Ad esempio, dove si desidera dividere due numeri, anziché scrivere:

try
{
    int result = a/b;
}
catch (DivisionByZeroException ex)
{
    // Showing a message here, and logging of course.
}

dovresti scrivere:

if (b == 0)
{
    int result = a/b;
}
else
{
    // Showing a message to user to change the value of b, etc.
}

2
+1 per l'utilizzo di if / else per gestire "eccezioni" che sono fondamentalmente solo la logica dell'applicazione.
Morgan Herlocker,

Se è correlato all'utente, ricorda che i computer sono enormemente più veloci delle persone. Un'eccezione generata nel 50% degli invii di moduli è ancora probabile che accada solo poche volte al secondo anche con molti utenti.
Donal Fellows

1
Non sono d'accordo con te sull'evitamento di blocchi try / catch. Cercare costantemente di anticipare le eccezioni è soggetto a errori, costoso nel tempo degli sviluppatori e rende il codice più difficile da leggere. Un ciclo che genera un milione di eccezioni e le intercetta richiede 500 ms per essere eseguito sulla mia macchina (rispetto a 1 ms per un ciclo vuoto), che non è la differenza di prestazioni del mondo reale nel 99,99% dei casi (e tutto il codice dell'interfaccia utente). Dovresti usare le eccezioni, tranne nei casi in cui conosci la penalità delle prestazioni, perché rendono il tuo codice più affidabile e ti fanno supporre che il codice precedente sia stato eseguito correttamente.
Kaypro II,

@ cosmic.osmo, recuperi lo stacktrace o semplicemente lo catturi?

3

Dovresti usare try-catch quando appropriato, ma per favore oh, per favore, non catturare tutte le eccezioni e nemmeno registrarlo. A quel punto è odore di codice e lavoro scadente.


1
+1 per la registrazione. I programmi in natura sono scatole nere. Quando falliscono, un registro che dice "Ecco cosa è successo" fa molto per risolvere il problema. Ho riscontrato errori nei miei programmi che non sono stati segnalati e sono stati scoperti solo dopo averli trovati nel registro.
Andrew Neely,

2

Personalmente non sopporto le eccezioni, sono MOLTO, MOLTO, MOLTO difficili da gestire correttamente. E cercare di decifrare i dati corrotti è MOLTO, MOLTO, MOLTO difficile!

http://blogs.msdn.com/b/mgrier/archive/2004/02/18/75324.aspx

http://blogs.msdn.com/b/oldnewthing/archive/2004/04/22/118161.aspx

http://blogs.msdn.com/b/oldnewthing/archive/2005/01/14/352949.aspx

http://www.joelonsoftware.com/items/2003/10/13.html

Se non chiami tutte le funzioni come:

try
{
    TrivialFunction();
}
catch(TypeAException)
{
    //MaybeFix
}
catch(TypeBException)
{
    //MaybeFix
}
catch(TypeCException)
{
    //NO FIX - CORRUPT DATA
}
catch(TypeDException)
{
    //NO FIX - UNKNOWN STATE
}
catch(OutOfMemoryException)
{
    //Try to fix this one! Destructors might allocate on their own ;)
}
catch(Exception)
{
    //Nothing to see here, move on, everything is OK ;)
}

Non è possibile ripulire correttamente ogni punto di uscita. Le eccezioni sono DURE!

L'unica cosa positiva delle eccezioni è che se non le prendi, l'app si arresta in modo imprevisto.

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.