Perché la gestione delle eccezioni è dannosa?


89

Il linguaggio Go di Google non ha eccezioni come scelta di design e Linus della fama di Linux ha definito le eccezioni merda. Perché?


2
Il creatore di ZeroMQ scrive di come pensa che sia stato un errore scriverlo in C ++ (principalmente a causa della gestione degli errori) 250bpm.com/blog:4
serbaut

Go potrebbe non avere eccezioni, ma ha "panic" da cui puoi "recuperare" (mentre le istruzioni differite sono ancora eseguite) e che forniscono un flusso di controllo non locale ...
Kerrek SB

Ecco un bell'articolo lighterra.com/papers/exceptionsharmful (gestione delle eccezioni considerata dannosa)
masterxilo

Afaics, le eccezioni possono essere simulate in Go con boilerplate significativo , sebbene questo punto possa essere più significativo per il transpiling da uno zucchero di sintassi che per la scrittura manuale del boilerplate.
Shelby Moore III

Risposte:


81

Le eccezioni rendono davvero facile scrivere codice in cui un'eccezione generata interromperà le invarianti e lascerà gli oggetti in uno stato incoerente. Essenzialmente ti costringono a ricordare che la maggior parte delle affermazioni che fai può potenzialmente lanciare e gestirlo correttamente. Farlo può essere complicato e controintuitivo.

Considera qualcosa di simile come un semplice esempio:

class Frobber
{
    int m_NumberOfFrobs;
    FrobManager m_FrobManager;

public:
    void Frob()
    {
        m_NumberOfFrobs++;

        m_FrobManager.HandleFrob(new FrobObject());
    }
};

Supponendo che la FrobManagervolontà deletedel FrobObject, questo sembra ok, giusto? O forse no ... Immagina quindi se uno dei due FrobManager::HandleFrob()o operator newlancia un'eccezione. In questo esempio, l'incremento di m_NumberOfFrobsnon viene annullato. Pertanto, chiunque utilizzi questa istanza di Frobberavrà un oggetto potenzialmente danneggiato.

Questo esempio può sembrare stupido (ok, mi sono dovuto sforzare un po 'per costruirne uno :-)), ma la conclusione è che se un programmatore non pensa costantemente alle eccezioni e si assicura che ogni permutazione di stato venga annullata ogni volta che ci sono lanci, ti metti nei guai in questo modo.

Ad esempio, puoi pensarlo come pensi ai mutex. All'interno di una sezione critica, fai affidamento su diverse istruzioni per assicurarti che le strutture dati non siano danneggiate e che gli altri thread non possano vedere i tuoi valori intermedi. Se una qualsiasi di queste affermazioni non viene eseguita casualmente, finisci in un mondo di dolore. Ora togli i blocchi e la concorrenza e pensa a ciascun metodo in questo modo. Pensa a ogni metodo come una transazione di permutazioni sullo stato dell'oggetto, se vuoi. All'inizio della chiamata al metodo, l'oggetto dovrebbe essere in stato pulito e alla fine dovrebbe esserci anche uno stato pulito. Nel mezzo, la variabile foopotrebbe non essere coerente conbar, ma il tuo codice alla fine lo rettificherà. Ciò che significa eccezioni è che qualsiasi tua dichiarazione può interromperti in qualsiasi momento. Spetta a te in ogni singolo metodo farlo correttamente e tornare indietro quando ciò accade, o ordinare le tue operazioni in modo che i lanci non influenzino lo stato dell'oggetto. Se sbagli (ed è facile commettere questo tipo di errore), il chiamante finisce per vedere i tuoi valori intermedi.

Metodi come RAII, che i programmatori C ++ amano menzionare come la soluzione definitiva a questo problema, fanno molto per proteggersi da questo. Ma non sono una pallottola d'argento. Ti assicurerà di rilasciare risorse al momento del lancio, ma non ti libera dal dover pensare alla corruzione dello stato dell'oggetto e ai chiamanti che vedono valori intermedi. Quindi, per molte persone, è più facile a dirsi, in base allo stile di codifica, senza eccezioni . Se limiti il ​​tipo di codice che scrivi, è più difficile introdurre questi bug. Se non lo fai, è abbastanza facile commettere un errore.

Sono stati scritti interi libri sulla codifica sicura delle eccezioni in C ++. Molti esperti hanno sbagliato. Se è davvero così complesso e ha così tante sfumature, forse è un buon segno che devi ignorare quella caratteristica. :-)


9
Risposta interessante, tuttavia non riflette nulla nella mia esperienza di programmazione. Quindi immagino sia specifico della cultura (forse più un problema in Java o C ++ che, ad esempio, Python) o specifico del dominio.
ddaa

39
Le eccezioni scritte in un linguaggio gestito utilizzando un pattern try-catch-latest non dovrebbero mai lasciare uno stato non valido se sono scritte correttamente; poiché è garantito che il blocco finalmente venga eseguito, gli oggetti possono essere deallocati lì. Il resto dovrebbe essere curato dalle variabili che escono dall'ambito e dalla garbage collection.
Robert Harvey,

7
@ddaa Il problema è sicuramente possibile in Python. Il risultato è in genere un bug difficile da riprodurre. Forse sei stato particolarmente meticoloso o fortunato. Ma poi, hai ragione sul fatto che è più un problema in C ++, dove il bug più comune del povero EH è una perdita di memoria. Ho cercato di sottolineare che le perdite non sono il problema più serio. @Robert GC mitigherà le perdite di memoria, ma non sono sicuro che il codice gestito ti libererà dall'errore del programmatore. In particolare, se qualcuno non sta prestando attenzione alla sicurezza delle eccezioni perché non pensa che sia un problema nella loro lingua, non è un grande segno.
asveikau

4
@lzprgmr ci sono sicuramente: le eccezioni ti permettono di gestire diff. tipi di errori a diff. posti nel codice. Affrontare un errore di connessione potrebbe richiedere una riconnessione, ma non nel mezzo di una funzione profondamente annidata. Vuoi farlo bolla al gestore delle connessioni o qualcosa del genere. Quindi gestire i valori di ritorno ti costringe a controllare gli errori su ogni singola chiamata e a crearli manualmente (nel caso di un errore di ripristino della connessione, ad es.). Inoltre, i valori di ritorno si accumulano nelle chiamate annidate: func3 può restituire -1, func2 chiama func3, restituisce -2 sui suoi errori, -1 per func3, ecc.
abourget

3
Stavo votando verso il basso, ma l'ho ribaltato perché questo è un motivo per cui le eccezioni sono disprezzate. Tuttavia, a mio parere, quasi tutti i metodi o parti di codice possono fallire. Non è possibile gestire ciascuna condizione di errore introducendo un valore di ritorno per essa. Perderai le informazioni sull'errore. Pensare di poter mantenere tutto ben sincronizzato controllando ogni singola istruzione ed eseguendo la pulizia porta a un codice molto contorto: rilevare un errore su più istruzioni e ripulire una o due risorse che non sono GC è molto più pulito.
Maarten Bodewes

50

Il motivo per cui Go non ha eccezioni è spiegato nelle domande frequenti sulla progettazione del linguaggio Go:

Le eccezioni sono una storia simile. Sono stati proposti numerosi progetti per le eccezioni, ma ciascuno aggiunge una complessità significativa al linguaggio e al tempo di esecuzione. Per loro stessa natura, le eccezioni abbracciano funzioni e forse anche goroutine; hanno implicazioni ad ampio raggio. C'è anche preoccupazione per l'effetto che avrebbero sulle biblioteche. Sono, per definizione, eccezionali ma l'esperienza con altri linguaggi che li supportano mostra che hanno un profondo effetto sulle specifiche della libreria e dell'interfaccia. Sarebbe bello trovare un design che permetta loro di essere davvero eccezionali senza incoraggiare errori comuni a trasformarsi in un flusso di controllo speciale che richiede a ogni programmatore di compensare.

Come i generici, le eccezioni rimangono una questione aperta.

In altre parole, non hanno ancora capito come supportare le eccezioni in Go in un modo che ritengono soddisfacente. Non stanno dicendo che le eccezioni siano negative di per sé ;

AGGIORNAMENTO - maggio 2012

I progettisti di Go sono ora scesi dalla recinzione. Le loro FAQ ora dicono questo:

Riteniamo che l'accoppiamento di eccezioni a una struttura di controllo, come nell'idioma try-catch-latest, si traduca in codice contorto. Inoltre tende a incoraggiare i programmatori a etichettare troppi errori ordinari, come la mancata apertura di un file, come eccezionali.

Go ha un approccio diverso. Per la semplice gestione degli errori, i resi multivalore di Go semplificano la segnalazione di un errore senza sovraccaricare il valore restituito. Un tipo di errore canonico, insieme alle altre funzionalità di Go, rende la gestione degli errori piacevole ma abbastanza diversa da quella delle altre lingue.

Go ha anche un paio di funzioni integrate per segnalare e recuperare da condizioni davvero eccezionali. Il meccanismo di ripristino viene eseguito solo come parte dello stato di una funzione che viene abbattuto dopo un errore, il che è sufficiente per gestire la catastrofe ma non richiede strutture di controllo aggiuntive e, se usato correttamente, può dare come risultato un codice di gestione degli errori pulito.

Per i dettagli, vedere l'articolo Rinvia, panico e ripristino.

Quindi la risposta breve è che possono farlo in modo diverso utilizzando il ritorno multivalore. (E comunque hanno una forma di gestione delle eccezioni.)


... e Linus della fama di Linux ha definito le eccezioni merda.

Se vuoi sapere perché Linus pensa che le eccezioni siano una schifezza, la cosa migliore è cercare i suoi scritti sull'argomento. L'unica cosa che ho rintracciato finora è questa citazione che è incorporata in un paio di e-mail su C ++ :

"L'intera faccenda della gestione delle eccezioni C ++ è fondamentalmente non funzionante. È particolarmente difettosa per i kernel."

Noterai che sta parlando di eccezioni C ++ in particolare e non di eccezioni in generale. (E C ++ eccezioni non hanno apparentemente alcuni problemi che li rendono difficile da usare correttamente.)

La mia conclusione è che Linus non ha definito le eccezioni (in generale) "schifo"!


30
Odio quando nascondono le informazioni inserendole nelle FAQ. :)
brian d foy

7
Nota che Linus inizia quell'email con "C ++ è un linguaggio orribile". e continua a lamentarsi di quanto odia sia il C ++ che le persone che scelgono di programmare in esso. Di conseguenza non credo che la sua opinione sulle eccezioni del C ++ possa essere considerata affidabile data la sua opinione un po 'distorta nei confronti del C ++.
Pharap

1
@ Hi-Angel - Come dice il testo che ho citato: "Per la semplice gestione degli errori, i resi multivalore di Go facilitano la segnalazione di un errore senza sovraccaricare il valore restituito." . Ecco come è correlato. Ad ogni modo, sto citando la logica dei designer Go. Se vuoi discutere, discuti con >> loro <<.
Stephen C

1
@ Hi-Angel - Non ho scritto quei paragrafi. Li ho semplicemente citati. Se hai un problema con loro, dovresti probabilmente parlarne con gli autori. In teoria avrei potuto fornire un tutorial sulla lingua Go come contesto. Ma per essere sinceri, le persone che non comprendono la terminologia di Go possono visitare il sito Web di Go per scoprire cosa significa tutto ciò.
Stephen C

1
".. risulta in codice contorto" Molto tempo fa ho scritto un programma in C con molte operazioni sulle stringhe. Ogni metodo consisteva nell'allocazione della memoria e quindi nel controllare se l'allocazione era riuscita. Sembrava che la maggior parte del codice stesse solo controllando le allocazioni. Non è contorto? Il C ++ con le eccezioni è stato un grande salvataggio per me.
robsosno

29

Le eccezioni non sono male di per sé, ma se sai che succederanno spesso, possono essere costose in termini di prestazioni.

La regola pratica è che le eccezioni dovrebbero segnalare condizioni eccezionali e che non dovresti usarle per il controllo del flusso del programma.


9
@Robert: "non dovresti usarli per il controllo del flusso del programma", non ci ho pensato in questo modo, nuova prospettiva per me: P +1
okw

2
Dipende anche molto dalla lingua. È difficile evitare eccezioni se ad esempio stai programmando in Java.
Charles Salvia

2
@Charles: Penso che il punto sia che le eccezioni sono appropriate in situazioni che indicano un bug, un sistema mal configurato o input irragionevoli. La maggior parte delle eccezioni della libreria Java può essere evitata nel codice del "flusso di lavoro normale".
Artelius

6
non devono costare molto. ad esempio, puoi implementare un "tentativo" che costa zero tempo di esecuzione e fare in modo che "lancia" cerchi gestori di eccezioni in una tabella in base agli indirizzi del chiamante che vede nello stack ... direi che i motivi principali per non farlo le eccezioni all'uso non sono affatto correlate alle prestazioni.
asveikau

Riformulato; la domanda suggerisce chiaramente di usare le eccezioni in generale, o di non usare affatto le eccezioni (sono schifo o non sono nemmeno nella lingua). La tua risposta mostra solo perché le eccezioni sono dannose per le prestazioni quando vengono utilizzate per il flusso di controllo del programma.
Maarten Bodewes

26

Non sono d'accordo con "lanciare eccezioni solo in una situazione eccezionale". Sebbene sia generalmente vero, è fuorviante. Le eccezioni riguardano le condizioni di errore (errori di esecuzione).

Indipendentemente dalla lingua che utilizzi, prendi una copia delle Linee guida per la progettazione del framework : convenzioni, idiomi e modelli per le librerie .NET riutilizzabili (2a edizione). Il capitolo sul lancio di eccezioni è senza pari. Alcune citazioni dalla prima edizione (la seconda è al mio lavoro):

  • NON restituire codici di errore.
  • I codici di errore possono essere facilmente ignorati e spesso lo sono.
  • Le eccezioni sono il mezzo principale per segnalare errori nei framework.
  • Una buona regola pratica è che se un metodo non esegue ciò che suggerisce il nome, dovrebbe essere considerato un errore a livello di metodo, risultando in un'eccezione.
  • NON utilizzare eccezioni per il normale flusso di controllo, se possibile.

Ci sono pagine di note sui vantaggi delle eccezioni (coerenza API, scelta della posizione del codice di gestione degli errori, maggiore robustezza, ecc.) C'è una sezione sulle prestazioni che include diversi modelli (Tester-Doer, Try-Parse).

Le eccezioni e la gestione delle eccezioni non sono male. Come qualsiasi altra caratteristica, possono essere utilizzati in modo improprio.


3
Devo essere in disaccordo su questo. Non sono contrario alle eccezioni e quel libro è un must, tuttavia è orientato allo sviluppo .NET e C #.

3
So che questo è antico, volevo solo commentare che sembra che ci sarebbe un disaccordo generale sullo stile tra il tipo .NET e il tipo * nix. Tutte le librerie che ho usato come sviluppatore Linux utilizzano codici di ritorno e le guide di stile * nix che ho letto (come la mia azienda e quelle di Google per esempio) dicono semplicemente "non facciamo eccezioni". Pensa solo che sia interessante.
jarvisteve

1
I framework dovrebbero trattare le eccezioni in modo diverso dalle applicazioni degli utenti finali. I framework non hanno un modo per gestire gli errori tranne il lancio di un'eccezione, le applicazioni consumer sì.
0x6C38

11

Dal punto di vista di golang, immagino che non avere la gestione delle eccezioni mantenga il processo di compilazione semplice e sicuro.

Dal punto di vista di Linus, capisco che il codice del kernel è TUTTO su casi d'angolo. Quindi ha senso rifiutare le eccezioni.

Le eccezioni hanno senso nel codice dove va bene rilasciare l'attività corrente sul pavimento e dove il codice caso comune ha più importanza della gestione degli errori. Ma richiedono la generazione di codice dal compilatore.

Ad esempio, vanno bene nella maggior parte del codice di alto livello rivolto agli utenti, come il codice dell'applicazione web e desktop.


Ma ciò che è vero per il codice del kernel è vero anche per processi server nativi a lunga esecuzione.
Lothar

11

Le eccezioni in sé e per sé non sono "cattive", è il modo in cui le eccezioni a volte vengono gestite che tende ad essere cattive. Esistono diverse linee guida che possono essere applicate quando si gestiscono le eccezioni per alleviare alcuni di questi problemi. Alcuni di questi includono (ma sicuramente non sono limitati a):

  1. Non utilizzare le eccezioni per controllare il flusso del programma, ovvero non fare affidamento sulle istruzioni "catch" per modificare il flusso della logica. Questo non solo tende a nascondere vari dettagli attorno alla logica, ma può portare a prestazioni scadenti.
  2. Non lanciare eccezioni dall'interno di una funzione quando uno "stato" restituito avrebbe più senso - genera eccezioni solo in una situazione eccezionale. La creazione di eccezioni è un'operazione costosa e ad alta intensità di prestazioni. Ad esempio, se chiami un metodo per aprire un file e quel file non esiste, genera un'eccezione "FileNotFound". Se chiami un metodo che determina se esiste un account cliente, restituisci un valore booleano, non restituire un'eccezione "CustomerNotFound".
  3. Quando si determina se gestire o meno un'eccezione, non utilizzare una clausola "try ... catch" a meno che non si possa fare qualcosa di utile con l'eccezione. Se non sei in grado di gestire l'eccezione, dovresti semplicemente lasciare che bolle in su nello stack di chiamate. Altrimenti, le eccezioni potrebbero essere "inghiottite" dal gestore e i dettagli andranno persi (a meno che non si rilanci l'eccezione).

2
Restituire lo stato è una cosa complicata. Ho visto fin troppo codice che ha un metodo GetCustomer che restituisce un'entità Customer in caso di successo o null in caso di fallimento. In più casi il codice chiamante non controllava mai il risultato, ma accedeva immediatamente al cliente. Ha funzionato per la maggior parte del tempo ...
TrueWill

3
Ma se GetCustomer genera un'eccezione invece di restituire null, il codice client deve comunque gestire l'eccezione. Che si tratti di verificare la presenza di null o di gestire le eccezioni, la responsabilità ricade sul codice client: se non fa le cose correttamente, prima o poi qualcosa esploderà.
Chris

1
@TrueWill Le lingue che supportano modelli / generici risolvono questo problema restituendo un Option<T>invece di nulloggi. Ad esempio, è stato appena introdotto in Java 8, prendendo spunto da Guava (e altri).
Maarten Bodewes

@owlstead Sì. Adoro la forse monade. È un buon modo se la tua lingua lo supporta e offre la corrispondenza dei modelli.
TrueWill

@owlstead Di nuovo, ciò che Chris ha detto è ancora valido per questo: l'utente deve ricordarsi di chiamare la funzione .orElse (defaultObject) o qualsiasi idioma deciso dalla lingua in questione. Alla fine della giornata sono i programmatori a essere il problema, piuttosto che il metodo di gestione degli errori.
Pharap

9

Gli argomenti tipici sono che non c'è modo di dire quali eccezioni usciranno da un particolare pezzo di codice (a seconda della lingua) e che sono troppo simili a gotos, rendendo difficile tracciare mentalmente l'esecuzione.

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

Sicuramente non c'è consenso su questo tema. Direi che dal punto di vista di un programmatore C hard-core come Linus, le eccezioni sono decisamente una cattiva idea. Tuttavia, un tipico programmatore Java si trova in una situazione molto diversa.


1
Il codice C ha delle eccezioni, solo in un modo diverso. Devi racchiudere ogni chiamata a una funzione non banale in ifs, il che rende l'uso di quel linguaggio un mal di testa!
RCIX

1
C'è anche la setjmp/ longjmproba, che è piuttosto brutta.
Tim Sylvester

9
Vuoi davvero seguire il consiglio di un uomo che apprezza i programmatori di nastri adesivi e che non crede che i test unitari siano necessari? joelonsoftware.com/items/2009/09/23.html
TrueWill

4
Questo è un classico errore (o imbroglio) in una discussione in cui gli argomenti sull'argomento vengono sostituiti con riferimenti alla personalità. Questo di solito è un segno di degenerazione della discussione.
Petr Gladkikh

1
@PetrGladkikh La discussione è iniziata con l'OP che si riferiva all'opinione di Linus ... quell'imbroglio è noto come l'errore di appello all'autorità. La discussione può solo salire da lì, e non è un "imbroglio" rispondere alla domanda sul perché a Linus non piacciono le eccezioni riferendosi alla sua personalità.
Jim Balter

7

Le eccezioni non sono male. Si adattano bene al modello RAII di C ++, che è la cosa più elegante di C ++. Se hai già un sacco di codice che non è sicuro dalle eccezioni, allora sono cattivi in ​​quel contesto. Se stai scrivendo software di basso livello, come il sistema operativo Linux, allora sono pessimi. Se ti piace sporcare il tuo codice con una serie di controlli di ritorno degli errori, allora non sono utili. Se non si dispone di un piano per il controllo delle risorse quando viene generata un'eccezione (fornita dai distruttori C ++), allora sono cattivi.


7
RAII è utile anche senza eccezioni.
Mark Ransom

4
tuttavia, le eccezioni non sono utili senza RAII (o qualche altra gestione automatica delle risorse).
Greg Rogers,

+1 per indicare situazioni in cui le eccezioni non sono appropriate e che le eccezioni non sono intrinsecamente negative.
Pharap

4

Un ottimo caso d'uso per le eccezioni è quindi ...

Supponiamo che tu stia lavorando a un progetto e che ogni controller (circa 20 diversi principali) estenda un singolo controller di superclasse con un metodo di azione. Quindi ogni controller fa un sacco di cose diverse l'una dall'altra chiamando gli oggetti B, C, D in un caso e F, G, D in un altro. Le eccezioni vengono in soccorso qui in molti casi in cui c'erano tonnellate di codice di ritorno e OGNI controller lo gestiva in modo diverso. Ho distrutto tutto quel codice, ho lanciato l'eccezione corretta da "D", l'ho catturato nel metodo di azione del controller della superclasse e ora tutti i nostri controller sono coerenti. In precedenza D restituiva null per MULTIPLI diversi casi di errore di cui vogliamo informare l'utente finale ma che non abbiamo potuto e non l'ho fatto '

sì, dobbiamo preoccuparci di ogni livello e di eventuali ripuliture / perdite di risorse, ma in generale nessuno dei nostri controller aveva risorse per ripulire dopo.

grazie a dio abbiamo avuto delle eccezioni o sarei stato sottoposto a un enorme refactoring e avrei perso troppo tempo su qualcosa che dovrebbe essere un semplice problema di programmazione.


1
+1 Facilmente uno dei migliori argomenti per usare le eccezioni che ho letto. Avrebbero potuto usare esempi più dettagliati (cioè un diagramma UML, qualche pseudocodice o un codice effettivo) ma il punto su come fare in modo che le sottoclassi funzionino in modo coerente è buono. Inoltre, il fatto che le tue prove siano aneddotiche mostra che le eccezioni sono utili in situazioni reali e l'utilità è lo scopo principale di qualsiasi caratteristica del linguaggio.
Pharap

proprio come aggiunta, se sei in scala, puoi invece restituire Try [ResponseType] che rappresenta un'eccezione o una risposta effettiva. È quindi possibile seguire lo stesso schema a cui eludo sopra senza eccezioni effettive diverse da quelle che sono state messe nella prova. Quindi è come se ogni metodo che hai restituisce 1 + n tipi di risposta che penso siano necessari. Tuttavia, in scala restituiamo Future [risposta] che funziona in modo molto simile al Try ma può aiutare con una programmazione più asincrona.
Dean Hiller

2

Teoricamente sono davvero pessimi. Nel perfetto mondo matematico non puoi ottenere situazioni eccezionali. Guarda i linguaggi funzionali, non hanno effetti collaterali, quindi praticamente non hanno fonte per situazioni non eccezionali.

Ma la realtà è un'altra storia. Abbiamo sempre situazioni "inaspettate". Ecco perché abbiamo bisogno di eccezioni.

Penso che possiamo pensare alle eccezioni come allo zucchero di sintassi per ExceptionSituationObserver. Ricevi solo notifiche di eccezioni. Niente di più.

Con Go, penso che introdurranno qualcosa che affronterà situazioni "inaspettate". Posso immaginare che cercheranno di farlo sembrare meno distruttivo come eccezioni e più come logica dell'applicazione. Ma questa è solo una mia ipotesi.


2
"Guarda i linguaggi funzionali, non hanno effetti collaterali, quindi praticamente non hanno fonte per situazioni non eccezionali". Questa è un'esagerazione grossolana.
Stephen C

3
Cos'è il 5/0 in matematica? Arcsin (200)? Sqrt (-1)? La matematica ha un sacco di situazioni eccezionali.
Robert Fraser

3
Queste non sono situazioni opzionali ... semplicemente non hanno alcun significato ... e per questo potrebbero essere implementate come eccezioni ... ma potrebbero anche essere implementate come vialazioni di precondizioni .. quindi dipende dall'implementazione tecnica.
Mike Chaliy

3
@MikeChaliy - Mi dispiace, ma questo è solo sofisma. Puoi applicare questo tipo di ragionamento per dire che NON ci sono situazioni di eccezione in niente, MAI. In realtà, le espressioni matematiche che non hanno significato (o che non hanno un valore definito) SONO eccezionali. Ciò non significa che debbano essere risolti lanciando e catturando eccezioni ... ma se non lo fai hai bisogno di valori speciali (come Inf e Nan) o di operazioni che restituiscono più valori. In breve, questi casi richiedono un tipo di trattamento speciale.
Stephen C

1
I computer sono macchine a stati. Non è un mondo di matematica perfetto.
Arunav Sanyal

1

Il paradigma di gestione delle eccezioni di C ++, che costituisce una base parziale per quello di Java e, a sua volta .net, introduce alcuni buoni concetti, ma presenta anche alcune gravi limitazioni. Una delle principali intenzioni di progettazione della gestione delle eccezioni è quella di consentire ai metodi di garantire che soddisfino le loro condizioni successive o di generare un'eccezione, e anche di garantire che avvenga qualsiasi pulizia che deve avvenire prima che un metodo possa uscire. Sfortunatamente, i paradigmi di gestione delle eccezioni di C ++, Java e .net non riescono a fornire alcun mezzo valido per gestire la situazione in cui fattori imprevisti impediscono l'esecuzione della pulizia prevista. Questo a sua volta significa che si deve rischiare che tutto si arresti bruscamente se accade qualcosa di inaspettato (l'approccio C ++ alla gestione di un'eccezione si verifica durante lo svolgimento dello stack),

Anche se la gestione delle eccezioni sarebbe generalmente buona, non è irragionevole considerare inaccettabile un paradigma di gestione delle eccezioni che non fornisce un buon mezzo per gestire i problemi che si verificano durante la pulizia dopo altri problemi. Questo non vuol dire che un framework non possa essere progettato con un paradigma di gestione delle eccezioni che possa garantire un comportamento ragionevole anche in scenari di più guasti, ma nessuno dei linguaggi o framework principali può ancora farlo.


1

Non ho letto tutte le altre risposte, quindi questa potrebbe essere già stata menzionata, ma una critica è che causano l'interruzione dei programmi in lunghe catene, rendendo difficile rintracciare gli errori durante il debug del codice. Ad esempio, se Foo () chiama Bar () che chiama Wah () che chiama ToString (), quindi inserire accidentalmente i dati sbagliati in ToString () finisce per apparire come un errore in Foo (), una funzione quasi completamente non correlata.


0
  • L'eccezione che non viene gestita è generalmente negativa.
  • L'eccezione gestita male è negativa (ovviamente).
  • La "bontà / cattiveria" della gestione delle eccezioni dipende dal contesto / ambito e dall'adeguatezza, e non per il gusto di farlo.

0

Ok, risposta noiosa qui. Immagino che dipenda davvero dalla lingua. Dove un'eccezione può lasciare indietro le risorse allocate, dovrebbero essere evitate. Nei linguaggi di scripting semplicemente abbandonano o saltano in eccesso parti del flusso dell'applicazione. Questo è di per sé antipatico, ma sfuggire a errori quasi fatali con eccezioni è un'idea accettabile.

Per la segnalazione degli errori generalmente preferisco i segnali di errore. Tutto dipende dall'API, dal caso d'uso e dalla gravità o se la registrazione è sufficiente. Inoltre sto cercando di ridefinire il comportamento e throw Phonebooks()invece. L'idea è che le "eccezioni" sono spesso vicoli ciechi, ma una "rubrica" ​​contiene informazioni utili sul ripristino degli errori o percorsi di esecuzione alternativi. (Non ho ancora trovato un buon caso d'uso, ma continua a provare.)


0

Per me la questione è molto semplice. Molti programmatori utilizzano il gestore delle eccezioni in modo inappropriato. Più risorse linguistiche sono migliori. Essere in grado di gestire le eccezioni è positivo. Un esempio di cattivo uso è un valore che deve essere un intero non essere verificato, o un altro input che può dividere e non essere controllato per la divisione di zero ... la gestione delle eccezioni può essere un modo semplice per evitare più lavoro e pensieri, il programmatore potrebbe voler fare una scorciatoia sporca e applicare una gestione delle eccezioni ... L'affermazione: "un codice professionale NON fallisce MAI" potrebbe essere illusoria, se alcuni dei problemi elaborati dall'algoritmo sono incerti per sua natura. Forse nelle situazioni sconosciute per natura è bene entrare in gioco il gestore delle eccezioni. Le buone pratiche di programmazione sono oggetto di dibattito.


Il problema non è (o non dovrebbe essere) se il codice può fallire: un problema più grande è la misura in cui, se il codice fallisce, ci si preoccupa dei particolari. Se si prova a caricare un documento e uno dei metodi di "lettura dei dati" fallisce, spesso non ci si interessa di quale, poiché l'effetto è lo stesso a prescindere: il documento non può essere caricato. Concettualmente, la gestione delle eccezioni dovrebbe essere utile per questo. Il problema è che i paradigmi di gestione delle eccezioni di .NET e Java non forniscono alcun modo carino per distinguere le eccezioni "noiose" che dovrebbero essere raggruppate da quelle che non dovrebbero.
supercat
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.