Esiste una teoria delle gerarchie di eccezioni?


18

Conosco una dozzina di linguaggi di programmazione che hanno delle eccezioni in qualche modo, eppure sono venuto a testimoniare due tendenze "patologiche".

  1. Non sembra esserci un modello comune o una gerarchia di eccezioni. Ogni lingua fondamentalmente lancia la propria versione e, se le eccezioni lo rendono standard, i tipi di eccezioni che si trovano nello standard sarebbero piuttosto arbitrari (principalmente quelli che sono stati implementati durante la creazione di strumenti di linguaggio, come la lettura del codice sorgente da stringa o un'eccezione per richiamare il debugger o quella che si verifica quando non è possibile trovare il file, ecc.)

  2. Le eccezioni definite dalla lingua sono molto raramente riutilizzate dai programmi utente. Di solito ci sarebbero una o due eccezioni popolari ("non implementare" per esempio). Sebbene la maggior parte delle volte i programmatori creeranno le proprie eccezioni. (Confrontalo con, ad esempio, creando nuovi tipi numerici o nuovi tipi di raccolte).

Questa mi sembra una terribile omissione. Come mai nessuno sa che tipo di errori saranno necessari nei programmi utente? Speravo che ci fosse una sorta di bella gerarchia, simile a tipi numerici, raccolte, sistema di oggetti ecc.

Peggio ancora, Goolge e Wikipedia forniscono pochissimo aiuto in materia. Finora ho trovato solo un documento sull'eccezione funzionale che si apre in un passaggio:

Questo documento sostiene che la programmazione funzionale pigra non solo rende superfluo il meccanismo di gestione delle eccezioni incorporato, ma fornisce un potente strumento per lo sviluppo e la trasformazione di programmi che utilizzano eccezioni

(A Functional Theory of Exceptions, Mike Spivey, 1988)

Ma penso che le eccezioni siano buone. Non voglio trasformare i programmi che usano le eccezioni, al contrario, voglio rendere meno caotico l'uso delle eccezioni.

La domanda:

Esiste una teoria delle eccezioni? se è così, come è chiamato? Quali sono, se del caso, le pietre miliari che ne definiscono le basi?


le eccezioni sono un'invenzione piuttosto nuova, forse meno di ~ 20 anni, derivante in qualche modo dal "longjmp" di C. sono per lo più collegati a OOP. sembra che un uso / teoria / best practice ideali siano ancora in evoluzione. java ha uno dei modelli più elaborati. ci sono molti "antipattern" relativi alle eccezioni come notate. alcuni di questi sono collegati alla teoria del "calcolo tollerante ai guasti", che sembra anche un po 'agli inizi della sua infanzia.
vzn

Potresti considerare le eccezioni un sottoinsieme della teoria della continuazione. Vedi en.wikipedia.org/wiki/Continuation
jmite,

@jmite Eccezioni e continuazioni sono molto diverse. Le eccezioni si legano dinamicamente ai loro gestori, mentre le continuazioni lo fanno staticamente. In generale, le continuazioni da sole non possono essere utilizzate per implementare eccezioni, almeno in presenza di tipi, vedere ad esempio Eccezioni e continuazioni tipizzate non possono esprimersi reciprocamente .
Martin Berger,

"Le eccezioni definite dalla lingua sono molto raramente riutilizzate dai programmi utente." Questo è così vero! È molto raro definire eccezioni personalizzate. Ad esempio python e il suo stdlib definiscono qualcosa come 160 eccezioni. Le possibilità che l'eccezione a cui stai pensando non sia stata definita sono molto ridotte. Alcune (la maggior parte?) Di queste eccezioni non sono ampiamente note. Ad esempio, LookupErrorsarebbe perfetto per ogni contenitore personalizzato, ma molte persone non sanno nemmeno che esiste.
Bakuriu,

1
@jmite Un altro incontro che ho avuto con le eccezioni prima che questo argomento venisse dal libro Tipi e linguaggi di programmazione di Benjamin C. Pierce. Dove menziona errori nel contesto della definizione di un tipo di funzione. Vale a dire dal suo punto di vista, gli errori sono solo altri valori restituiti dalle funzioni (e insieme all'altro argomento formano un intero tipo, se mi è permesso dirlo).
wvxvw,

Risposte:


8

C'è un gran numero di pubblicazioni sulle eccezioni, con parecchie indagini teoriche. Ecco un elenco non strutturato e tutt'altro che completo con alcuni esempi. Mi dispiace, non ho tempo al momento per una risposta più mirata.

  • B. Randell, Struttura del sistema per la tolleranza agli errori del software.
  • JB Goodenough. Gestione delle eccezioni: problemi e notazione proposta.
  • JB Goodenough. Gestione delle eccezioni strutturata.
  • BG Ryder, ML Soffa, Influenze sul design della gestione delle eccezioni.
  • D. Teller, A. Spiwack, T. Varoquaux, Prendimi se puoi: Verso una gestione degli errori sicura, gerarchica, leggera, polimorfica ed efficiente in OCaml.
  • X. Leroy, F. Pessaux, Analisi basata sul tipo di eccezioni non rilevate.
  • R. Miller, A. Tripathi, Problemi con gestione delle eccezioni in sistemi orientati agli oggetti.
  • S. Drew, KJ Gough, J. Ledermann, Implementazione della gestione delle eccezioni zero-overhead.
  • B. Stroustrup, sicurezza delle eccezioni: concetti e tecniche.
  • D. Malayeri, J. Aldrich, Specifiche pratiche eccezionali.
  • H. Nakano, una formalizzazione costruttiva del meccanismo di cattura e lancio.
  • A. Nanevski, un calcolo modale per la gestione delle eccezioni.
  • P. de Groote, un semplice calcolo della gestione delle eccezioni.
  • H. Thielecke, Su eccezioni e continuazioni in presenza di stato.
  • JG Riecke, H. Thielecke, Eccezioni e continuazioni digitate non possono esprimersi reciprocamente.
  • M. van Dooren, E. Steegmans, che combina la robustezza delle eccezioni verificate con la flessibilità delle eccezioni non controllate mediante dichiarazioni di eccezione ancorate.
  • JA Vaughan, Un'interpretazione logica delle eccezioni in stile Java.
  • S. Marlow, S. Peyton Jones, A. Moran, Eccezioni asincrone a Haskell.
  • B. Jacobs, F. Piessens, Failbox: gestione eccezionalmente sicura.

Wow, grazie mille! Mi ci vorranno alcuni mesi (se non di più) per tornare con la risposta positiva :) Ora sono diviso tra pochi libri senza sapere da dove cominciare!
wvxvw,

2
Molti di questi articoli riguardano l'implementazione o la modellazione delle eccezioni nei linguaggi di programmazione e non come progettare una gerarchia di eccezioni. Potresti tagliare l'elenco fino ai documenti pertinenti?
Gilles 'SO- smetti di essere malvagio' il

@Gilles La domanda originale era un po 'poco chiara. Ritengo che ciò che conta come eccezioni appropriate dipenda principalmente dall'applicazione. L'unico vero problema teorico con le eccezioni è il compromesso tra (1) accoppiamento di moduli non correlati tramite eccezioni (questo è il motivo per cui nessun linguaggio dopo Java ha specifiche di eccezione obbligatorie), (2) dando all'utente di un modulo qualche indicazione su quali tipi di errori aspettarsi e (3) aiuto del compilatore con la gestione degli errori. Per quanto posso vedere, non è stata ancora trovata una soluzione davvero convincente a questo enigma.
Martin Berger,

6

Non so se esista o meno una teoria, ma potrebbe esserci una scienza sperimentale pragmatica emergente.

La migliore fonte che mi viene in mente è Bjarne Stroustrup, The Design and Evolution of C ++, Addison-Wesley, 1994 . Se ricordo bene (è un ottimo libro e la gente continua a prenderlo in prestito da me e non restituirlo, quindi al momento non ne ho una copia) c'è un capitolo sulle eccezioni. Il comitato C ++ sotto Stroustrup ha richiesto molte prove empiriche che una caratteristica proposta fosse necessaria prima che fossero disposti ad aggiungerla alla definizione del linguaggio. La pagina di Wikipedia sulle eccezioni ha la seguente citazione da quel libro:

Alla riunione del Palo Alto [C ++ standardization] del novembre 1991, abbiamo ascoltato un brillante riassunto degli argomenti per la semantica di terminazione supportati sia dall'esperienza personale che dai dati di Jim Mitchell (di Sun, precedentemente di Xerox PARC). Jim aveva usato la gestione delle eccezioni in una mezza dozzina di lingue per un periodo di 20 anni ed era uno dei primi fautori della semantica della ripresa come uno dei principali progettisti e implementatori del sistema Cedar / Mesa di Xerox. Il suo messaggio era che la terminazione è preferita alla ripresa; questa non è una questione di opinione, ma una questione di anni di esperienza. La ripresa è seducente, ma non valida. Ha sostenuto questa affermazione con l'esperienza di diversi sistemi operativi. L'esempio chiave è stato Cedar / Mesa: è stato scritto da persone che hanno gradito e usato la ripresa, ma dopo dieci anni di utilizzo, c'era solo un uso della ripresa nel sistema di mezzo milione di linee - e quella era un'indagine di contesto. Poiché la ripresa non era effettivamente necessaria per una tale indagine contestuale, la rimossero e trovarono un aumento significativo della velocità in quella parte del sistema. In tutti i casi in cui la ripresa era stata utilizzata, nel corso dei dieci anni era diventata un problema e un progetto più appropriato l'aveva sostituito. Fondamentalmente, ogni uso della ripresa aveva rappresentato un fallimento nel mantenere separati i livelli separati di astrazione. In tutti i casi in cui la ripresa era stata utilizzata, nel corso dei dieci anni era diventata un problema e un progetto più appropriato l'aveva sostituito. Fondamentalmente, ogni uso della ripresa aveva rappresentato un fallimento nel mantenere separati i livelli separati di astrazione. In tutti i casi in cui la ripresa era stata utilizzata, nel corso dei dieci anni era diventata un problema e un progetto più appropriato l'aveva sostituito. Fondamentalmente, ogni uso della ripresa aveva rappresentato un fallimento nel mantenere separati i livelli separati di astrazione.

In C ++ la vera vittoria è RAII , che semplifica molto la gestione della deallocazione delle risorse durante gli errori. (Non elimina la necessità di throwe try- catch, ma significa che non è necessario finally.)

Penso che la cosa che li ha convinti di aver bisogno di eccezioni siano i contenitori generici: il writer dei contenitori non sa nulla dei tipi di errori che gli oggetti contenuti potrebbero dover restituire (tanto meno come gestirli), ma il codice che ha inserito quegli oggetti nel Il contenitore deve sapere qual è l'interfaccia di quegli oggetti. Ma poiché non sappiamo nulla del tipo di errori che gli oggetti contenuti possono generare, non possiamo standardizzare i tipi di eccezione. (Controposizionalmente: se potessimo standardizzare i tipi di eccezione, non avremmo bisogno di eccezioni.)

L'altra cosa che le persone sembrano aver appreso negli anni è che le specifiche delle eccezioni sono difficili da inserire correttamente in una lingua. Vedere ad esempio questo: http://www.gotw.ca/publications/mill22.htm o questo: http://www.gotw.ca/gotw/082.htm . (E non è solo C ++, i programmatori Java hanno anche lunghi argomenti sulle loro esperienze con eccezioni controllate contro non controllate .)

Un po 'di storia delle eccezioni. L'articolo classico è: John B. Goodenough: "Gestione delle eccezioni: problemi e notazione proposta", Comun. ACM 18 (12): 683-696, 1975. Ma prima erano note eccezioni. Mesa li ebbe nel 1974 e forse anche io / PL. Ada aveva un meccanismo di eccezione prima del 1980. Credo che le eccezioni del C ++ siano state maggiormente influenzate dall'esperienza con il linguaggio di programmazione CLU di Barbara Liskov del 1976 circa. Barbara Liskov: "Una storia di CLU", in Storia dei linguaggi di programmazione --- II , Thomas J. Bergin, Jr. e Richard G. Gibson, Jr. (a cura di). pagine 471-510, ACM, 1996 .


Questo è interessante e dovrò cercare di più per rispondere meglio. Ma finora: so che c'è sempre un'obiezione molto forte di usare le eccezioni in C ++ (forse un aneddoto, ma con le convenzioni di codifica di Google utilizzate per vietare l'uso delle eccezioni). Le eccezioni verificate da Java sono certamente un esperimento unico e quindi interessante, ma la funzione ha guadagnato così tanti crediti negativi nel corso della sua storia ... la maggior parte delle persone semplicemente li ripropone in fase di esecuzione (anche se questo potrebbe essere solo correlato alla sintassi).
wvxvw,

Ho più familiarità con la classificazione delle eccezioni del Common Lisp, in cui hanno cercato di (anche se con scarso successo) dividerli in base al livello di minaccia che pongono al programma. ad es . serious-conditionvs. simple-conditionSto anche leggendo JL Austing, in cui classifica gli errori (non correlati alla programmazione) in gruppi in base al modo in cui il sistema non è riuscito a eseguire l'attività (ad es. Parti improprie utilizzate vs intenzioni non sincere). Che non è immediatamente applicabile alla programmazione, ma potrebbe essere dopo un certo perfezionamento.
wvxvw,

@Wandering Logic Ho aggiornato perché hai spiegato perché gli excpetios in C ++ sono sux e che l'inclusione educata delle funzionalità potrebbe distruggere il linguaggio.
Val

@wvxvw Le very strong objectioneccezioni contrarie in C ++ derivano da due fatti: non esiste un finallycostrutto e nessun altro usa eccezioni. Il primo problema aggrava anche il secondo. Cioè, quando non hai finally, non puoi chiudere la risorsa quando si verifica un'eccezione. Poiché nessuno utilizza le eccezioni, tutte le funzioni / API le evitano, è necessario investire molto per ricostruire l'intera infrastruttura C ++ tradizionale avvolgendo tutte le funzioni con le eccezioni per iniziare a trarne vantaggi nel codice. Ma la mancanza di finallyquesto approccio rende impossibile anche questo approccio.
Val

@wvxvw: le convenzioni di Google vietano il lancio di eccezioni oltre i confini del modulo (.so). Questo perché le eccezioni in C ++ utilizzano le informazioni sul tipo di runtime (RTTI) e Linux non ha fatto un buon lavoro nell'implementazione della tipizzazione di runtime. In Linux è possibile passare i tipi di runtime in modo affidabile tra i moduli solo se i moduli sono stati compilati con la stessa versione dello stesso compilatore e collegati alla versione identica di libstdc ++. In realtà questo è un rifiuto del C ++ in generale da parte della comunità Linux, non un rifiuto specifico delle eccezioni.
Wandering Logic,

3

Vorrei solo sottolineare che le eccezioni sono un caso di effetto computazionale . Altri effetti computazionali sono stato mutabile, I / O, non determinismo, continuazioni e molti altri. Quindi la tua domanda potrebbe essere posta più in generale: come formiamo gerarchie di effetti computazionali, come li organizziamo e perché abbiamo quelli che abbiamo e non altri, ecc.


1
Penso che questo sia completamente irrilevante. La domanda non è di modellare la nozione di eccezioni, ma di mapparla su errori - penso che il modo giusto di descriverla da una prospettiva PLT sarebbe una teoria delle gerarchie di eccezioni.
Gilles 'SO- smetti di essere malvagio' il

Hmm, hai ragione. Ho corretto la risposta per evidenziarlo, ma penso che non sia necessario eliminarlo. Cosa pensi?
Andrej Bauer,
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.