Cosa significa non rilevare un'eccezione quando non possiamo gestirla? [duplicare]

7

Qualcuno può spiegare cosa significa esattamente Microsoft nella pagina sottoindicata quando dice:

"Do not catch an exception unless you can handle it and leave the application in a known state."

link

    
posta user1451111 30.08.2016 - 16:31
fonte

5 risposte

17
  • Significa catturare un'eccezione semplicemente scrivendo su un registro o peggio, non fare nulla, lascia l'app in uno stato sconosciuto.
  • Forse qualcosa che non dovrebbe essere nullo sarà, o qualcosa che avrebbe dovuto essere salvato non lo sarebbe.
  • Stai solo spazzando la terra sotto il tappeto.
  • Se intendi catturare un'eccezione fallo perché puoi fare qualcosa al riguardo così l'app può continuare la sua esecuzione in uno stato noto (e atteso).
  • Cattura un'eccezione quando puoi effettivamente fare qualcosa per il problema che l'ha provocata o almeno lasciare l'app in uno stato coerente.

Else ...

buttalo avanti ... qualcuno lo stack delle chiamate dovrà gestirlo.

Se nessuno lo stack chiamante lo gestisce, diventerà solo una bolla fino a raggiungere l'interfaccia utente, almeno l'utente saprà che c'è qualcosa di brutto.

Ma, come tutto in questo mondo di programmazione, ci sono delle eccezioni (nessun gioco di parole):

A volte in un blocco finally provi a chiudere una risorsa database che potrebbe o non potrebbe essere stata inizializzata. In quel caso c'è una probabilità di chiamare close () su un oggetto nullo. In tal caso, la cattura silenziosa di NullPointerException è OK. Non puoi gestirlo comunque. Anche se, come @ marco-borchert, il controllo di null sarebbe più pulito.

Un'altra possibile eccezione alla regola è, come sottolineato anche da @marco-borchert, per registrare l'errore e ripetere il lancio. Forse hai informazioni in questo ambito che non saranno disponibili nello stack delle chiamate e sarebbe interessante registrarti anche se non gestirai l'eccezione a quel livello.

    
risposta data 30.08.2016 - 16:39
fonte
4

Significa non sporcare il tuo codice con gestori di eccezioni. Significa anche non fare questo:

try
{
 //Your code here
}
catch (Exception exception)
{

}

Perché è così male? La cattura di qualsiasi eccezione non è auspicabile perché cosa succede se il sistema ti sta dando un'eccezione di sistema o un'eccezione di memoria insufficiente? Vuoi davvero che la tua applicazione continui quando il sistema ti dice che non c'è più memoria?!

Quindi, i gestori di eccezioni dovrebbero essere specifici e dovrebbero essere recuperabili. È sempre possibile avere un gestore di eccezioni di livello di applicazione generico di alto livello per registrare i casi in cui si è verificato qualcosa di inaspettato, piuttosto in crash dell'applicazione. Questo è fatto in modo che l'applicazione possa chiudersi con grazia. Ma a parte questo, mantieni i gestori di eccezioni al minimo e specifici per determinati scenari.

    
risposta data 30.08.2016 - 19:18
fonte
2

"Astronauts have a saying that, in space, there is no problem so bad you can't make it worse." - Chris Hatfeld

Quando rileviamo le eccezioni, abbiamo preso un percorso molto insolito attraverso il codice. In genere le chiamate di funzione entrano nella parte superiore del corpo della funzione e terminano alla fine del corpo o in un'istruzione speciale return . Quando si verifica un'eccezione, nessuna di queste due cose accade. Seguiamo invece un percorso completamente diverso attraverso il codice usando lo stack unwinding. In questo caso gli invarianti potrebbero cadere a pezzi.

Quando facciamo questo, è molto possibile avere effetti collaterali indesiderati perché abbiamo saltato oltre diversi livelli. Considerare questa funzione logica bancaria difettosa:

bool transfer(Account accountFrom, Account accountTo, int amount)
{
    try {
        accountFrom.debit(amount); // remove the specified amount from the account
    } catch (NotEnoughFunds ex) {
        return false; // we failed
    }
    accountTo.credit(amount);
    return true;
}

Ora questo è patologicamente negativo per quanto riguarda le app bancarie, ma vediamo qualche tentativo di individuare le eccezioni. Tuttavia, diciamo che accountTo.credit(amount) genera un NotImplementedException . Che succede ora? Ritiriamo lo stack e forse il livello sopra mostra un utile messaggio di log prima di continuare. Questo sarebbe dove si verifica il vero problema. L'eccezione che si è verificata ha invalidato un'ipotesi dell'applicazione bancaria: abbiamo addebitato un conto ma non ne abbiamo accreditato un altro. Se "lo gestiamo", allora questa ipotesi non è più valida da qui in avanti, e il programmatore probabilmente non ha mai tenuto conto di questo. Il accountFrom può essere controllato per spiegare dove sono andati questi soldi, o l'intero sistema potrebbe crollare mentre il sistema cerca di bilanciare un'equazione che ora non è bilanciabile.

Se si desidera rilevare un'eccezione, è necessario comprendere bene tale eccezione per riportare il sistema a uno stato in cui non sono state violate le invarianti. Nel migliore dei casi, il codice che hai chiamato lo fa per te, perché l'autore ha scritto il codice con le eccezioni in mente. Tuttavia, è molto comune che un autore sia eccezionalmente inconsapevole e tuttavia utilizza una libreria sotto il cofano che è sensibile all'eccezione. In questo caso, puoi intercettare l'eccezione della libreria sottostante e mantenere invariate le sue invarianti, ma non correggere gli invarianti del livello tra loro.

Se un invariante viene violato, ci sono pochissime cose che possiamo fare. In molti ambienti, è sufficiente uscire dall'applicazione con un errore dicendo "qualcuno ha fatto qualcosa che non pensavo fosse possibile ... ci fermiamo ora". In altri ambienti ci si aspetta che cauterizzi la ferita, isolando il danno che l'invariante può fare e asportando il danno in un modo che non rompa più invarianti. Ad esempio, potresti progettare un sistema attorno al sistema AppDomain di C #, dove i singoli componenti sono separati in AppDomain diversi e sono autorizzati a comunicare solo tramite i canali che controlli. Potresti essere in grado di progettare le regole di quei canali in modo tale che quando un thread in un dominio genera un'eccezione non gestita, puoi abbattere l'intero AppDomain (perché i suoi "invarianti" non sono più attendibili) e quindi utilizzare il tuo controllo sul canali di comunicazione per gestire gli effetti collaterali di quel dominio che vengono rimossi in un modo che preserva gli invarianti degli altri domini.

    
risposta data 31.08.2016 - 02:13
fonte
1

Anche se la citazione dice che il modo corretto di gestire le eccezioni è di lasciarli passare - quando si è al livello più alto, ad esempio se si sta creando il proprio thread e si ha un ciclo di primo livello, quasi vuoi sempre catturare tutte le eccezioni in modo che il tuo thread non si rompa e muoia.

O vuoi catturare tutte le eccezioni all'interno del ciclo in modo che possa continuare (almeno registrarle!) o vuoi catturarle al di fuori del ciclo, registrarle e fermare il thread. Questo è ciò che ti permette di ignorare per lo più le eccezioni in altre parti del tuo programma - sapendo che sarà gestito correttamente da qualche parte lungo la catena di chiamate.

Questo vale per i loop di thread, per il loop del sistema principale (se ne hai uno) e per tutti i gestori di eventi che non hanno già una gestione delle eccezioni predefinita che si adatta alle tue esigenze.

    
risposta data 31.08.2016 - 01:31
fonte
0

Quando c'è un'eccezione che non sai come gestire, o c'è qualcun altro che sa come gestirlo o meno. E l'eccezione accade o no.

Se non succede, prendere l'eccezione non fa differenza, ma è uno spreco di sforzi. Se succede e nessuno sa come gestirlo e lo si cattura, non ne ricava alcun beneficio - l'unico beneficio deriverebbe da qualcuno che capisce come gestirlo. Quindi, di nuovo, uno spreco di sforzi. E se c'è qualcuno che sa come gestirlo, prenderlo non aiuta ma potrebbe impedire a qualcuno di gestirlo correttamente.

C'è una situazione nessuna in cui è utile trovare un'eccezione che non sai come gestire.

    
risposta data 31.08.2016 - 12:13
fonte

Leggi altre domande sui tag