Sta usando le eccezioni al livello più alto di un programma considerato una cattiva pratica? [duplicare]

12

Ho visto programmi che usano questa strategia e ho anche visto post che considerano questa cattiva pratica. Tuttavia, i post che prendono in considerazione questa cattiva pratica sono stati scritti in C # o in qualche altro linguaggio di programmazione, in cui sono incorporati alcuni errori di gestione. Questa domanda riguarda il c ++. Inoltre, gli errori che sto affrontando sono errori che sono abbastanza fatali da forzare un programma allo spegnimento, non un generale "forse-ho-ho-mancato-qualcosa-errore". Con l'utilizzo di espressioni al massimo livello intendo questo in un senso un po 'trascurato. Può essere qualcosa di simile

int main(){
    try {
        //run
    } catch (fatalException){
        //handle error and shutdown
    }
}

o può essere qualcosa di simile ad esempio in un'applicazione grafica.

void runApplication(){
    try {
        //run
    } catch (fatalException){
        //handle error and shutdown
    }
}

L'alternativa a questo sarebbe gestire questo errore dove accade e tornare gerarchicamente dalle funzioni, uno alla volta, fino alla fine del programma. La ragione per cui riesco a vedere per la terminazione di errori fatali da un try-catch al livello più alto è che i motivi di questo tipo di errore possono essere diversi, ed è probabilmente abbastanza insolito (database corrotti, alcuni errori di memoria insufficiente, configurazione corrotta file, ecc ...). Gestire le eccezioni localmente e tornare dalle funzioni uno alla volta renderebbe il codice meno chiaro e richiederà molto sforzo per gestire problemi che non si verifichino.

Tuttavia, non sono sicuro che sia una buona pratica avviare il programma con try . Personalmente, penso che sia brutto, ma in qualche modo questa bruttezza riflette la bruttezza del problema stesso, quindi questo potrebbe non essere un motivo per non usarlo per questo caso.

Modifica Potrei aver frainteso il dupe post, ma non penso che questo risolva il problema. La domanda non riguarda il non prendere alcune eccezioni. Il punto è che nella maggior parte dei casi ci sono altre parti del codice che possono gestire l'eccezione più vicino al lancio in un modo abbastanza soddisfacente, ma al costo di dover passare attraverso la gerarchia verso l'alto e terminare. Tuttavia, dal momento che il programma avrebbe ancora bisogno di essere terminato, c'è in generale qualche motivo per coglierlo prima al livello più alto? Si può sostenere che ciò implica che i livelli inferiori non sono in grado di decidere come gestirlo. Ma in questo caso credo che non sia chiaro. Intendo "quale errore avrebbe l'autorità per determinare se un programma deve terminare?"

    
posta patrik 01.02.2016 - 08:29
fonte

2 risposte

22

I have a question regarding the use of exceptions at the highest level of a program.

I have seen programs using this strategy and I have also seen posts considering this bad practice.

However, the posts considering this bad practice have been written in c# or some other programming language, where there are some error handling built in.

This question is about the c++.

I principi di [Exceptured] Exception Handling sono in gran parte indipendenti dalla lingua.

Qualsiasi eccezione non gestita ucciderà il tuo programma. Ciò che vedete qui sono i gestori di eccezioni "backstop" che fanno poco più che registrare l'eccezione da qualche parte (in modo che sia possibile esaminarla in seguito) e mostrare all'utente un messaggio "Oops" grande e amichevole, invece del brutto sistema, generato uno.

The alternative to this would be to handle this error where it happens and hierarcially return from functions, one-by-one until the program is terminated.

Questa è una pessima idea.

Usa lo strumento giusto per il lavoro giusto.

  • Controllo del flusso - chiamata e ritorno regolari.
  • Cose eccezionali che causano il caos - Eccezioni.

Hai un'idea del motivo per cui lancia Eccezioni, ma penso che ti manchi la parte [di gran lunga] più importante che è dove e perché per catturarli (o "gestirli").

OK, quindi il database è danneggiato.
Hai appena crash il programma?
O lasci che l'utente, ad esempio, apra una copia di backup del database?
O aprire il programma è una modalità "diagnostica" per provare e risolvere il problema.

Queste sono azioni che il tuo programma può eseguire - modi per "gestire" il tuo CorruptDatabaseException, ad esempio, se e quando accade.

Sì, le eccezioni sono eccezionali.

Non si aspettano che accada nel normale funzionamento ma, creando un'eccezione per un caso del genere, almeno hai pensato alla possibilità di esso accadendo e mettere una "risposta" in atto per affrontarlo. Potrebbe essere che l'azione sia solo "chiudere il programma (e dire all'utente perché)". In alcuni casi è tutto che puoi fare e, per questo, il catcher delle eccezioni di Backstop probabilmente lo farà.

The point is that there is in most cases are other parts of the code which can handle the exception closer the the throw in a fairly satisfactory way, but to the cost of having to step through the hierarchy to the top and terminate.

Ancora una volta, una parte cruciale di Exception Handling è che, avendo gestito con successo un'eccezione, il resto del programma deve essere in grado di continuare come se l'eccezione non fosse mai avvenuta . Se il tuo programma non può farlo, allora l'eccezione è che sta ancora succedendo , nel qual caso devi rilanciare la catena di chiamata finché qualcosa non può gestiscilo (anche se, alla fine, è solo per uccidere il programma).
Questo è il principio alla base del blocco "finalmente" visto in C #; codice "clean-up" in qualsiasi blocco try-catch che viene eseguito automaticamente mentre un'eccezione "lo attraversa", mentre sale attraverso lo stack delle chiamate, mentre viene gestito.

However, since the program would still need termination, are there in general any reason to catch earlier that on top level?

Se dovessi codificare qualcosa come ...

throw new KillProgramException(); 

... quindi no. L'intenzione è abbastanza chiara e non ti aspetteresti nulla nel tuo programma per cercare di gestirlo (eccetto, forse, il "backstop").

I mean what error would have the authority to determine if a program needs to terminate?

A seconda delle circostanze, potrebbe essere qualsiasi di loro!

In alcune sezioni di codice uber-critical, IndexOutOfRangeException potrebbe essere solo fatale come DatabaseCorruptException.

    
risposta data 01.02.2016 - 13:50
fonte
6

Chiaramente nella tua funzione main () non hai la possibilità di gestire l'eccezione in modo significativo. Se un'eccezione raggiunge main (), tutto quello che sai è che qualcosa è andato storto.

Ovviamente puoi decidere come vuoi gestire la situazione secondo cui "qualcosa è andato storto". Non è affatto una cattiva pratica. Ovviamente puoi decidere di gestirlo senza fare nulla (il che significa che il tuo programma si bloccherà). Potresti decidere di gestirlo informando l'utente che qualcosa è andato storto e quindi uscire. Che dipende dall'ambiente o meglio o peggio di un crash (in un'applicazione iOS, sarebbe considerato peggiore). Puoi decidere di gestirlo salvando ciò che può essere salvato e poi uscito; questo è qualcosa che deve essere fatto con molta attenzione perché sai che qualcosa è andato proprio male. Oppure puoi decidere di mantenere la tua app in esecuzione, che deve anche essere eseguita con molta attenzione perché sai che qualcosa è andato proprio male.

Riepilogo: non è una cattiva pratica. Dovrebbe essere una decisione consapevole, e cogliere l'errore a questo livello dovrebbe aggiungere qualcosa di valore. Prendere un punto che non fa nulla è ovviamente inutile, ma non fa alcun danno. Quindi potrebbe farmi chiedere "perché lo sviluppatore lo fa", ma non fa male.

Dovresti gestirlo prima: se un'eccezione è qualcosa che sai come gestire, ovviamente gestila. Se sai che un'eccezione può essere ignorata, ignorala. Se non sai come gestirlo, e non sai che può essere ignorato, o capire come gestirlo, o capire che puoi ignorarlo, o non prenderlo perché tale eccezione significa "qualcosa è andato storto". E se in realtà conosci non puoi gestire un'eccezione perché significa semplicemente "qualcosa è andato storto", quindi non prendi neanche quello.

    
risposta data 01.02.2016 - 11:28
fonte

Leggi altre domande sui tag