Gibt es eine Theorie der Ausnahmehierarchien?

18

Ich kenne ein Dutzend Programmiersprachen, die in gewisser Weise Ausnahmen haben, aber ich habe zwei "pathologische" Tendenzen beobachtet.

  1. Es scheint kein gemeinsames Muster oder eine Hierarchie von Ausnahmen zu geben. Jede Sprache rollt im Grunde genommen ihre eigene Version, und wenn die Ausnahmen es in den Standard schaffen, dann sind die Arten von Ausnahmen, die man im Standard findet, eher willkürlich (meistens jene, die beim Erstellen von Sprachwerkzeugen wie dem Lesen von Quellcode aus implementiert wurden) Zeichenfolge oder eine Ausnahme zum Aufrufen des Debuggers oder eine Ausnahme, die auftritt, wenn die Datei nicht gefunden werden kann usw.)

  2. Von der Sprache definierte Ausnahmen werden von Anwenderprogrammen sehr selten wiederverwendet. Normalerweise gibt es ein oder zwei beliebte Ausnahmen (zum Beispiel "nicht implementieren"). In den meisten Fällen erstellen Programmierer jedoch eigene Ausnahmen. (Vergleichen Sie dies beispielsweise damit, neue numerische Typen oder neue Sammlungstypen zu erstellen.)

Das scheint mir eine schreckliche Unterlassung zu sein. Wie kommt es, dass niemand weiß, welche Arten von Fehlern in Benutzerprogrammen benötigt werden? Ich hatte gehofft, dass es eine Art nette Hierarchie gibt, ähnlich wie bei numerischen Typen, Sammlungen, Objektsystemen usw.

Schlimmer noch, Goolge und Wikipedia bieten nur sehr wenig Hilfe zu diesem Thema. Bisher habe ich nur einen Artikel über funktionale Ausnahmen gefunden, der in einer Passage eröffnet wird:

In diesem Artikel wird argumentiert, dass eine verzögerte funktionale Programmierung nicht nur den eingebauten Mechanismus zur Ausnahmebehandlung überflüssig macht, sondern auch ein leistungsstarkes Werkzeug zum Entwickeln und Transformieren von Programmen bereitstellt, die Ausnahmen verwenden

(Eine funktionale Theorie der Ausnahmen, Mike Spivey, 1988)

Aber ich denke, dass Ausnahmen gut sind. Ich möchte keine Programme transformieren, die Ausnahmen verwenden, im Gegenteil, ich möchte die Verwendung von Ausnahmen weniger chaotisch machen.

Die Frage:

Gibt es eine Theorie der Ausnahmen? Wenn ja, wie heißt es? Was sind die Eckpfeiler, die die Grundlage dafür darstellen?

wvxvw
quelle
Ausnahmen sind eine ziemlich neue Erfindung, die vielleicht weniger als 20 Jahre alt ist und sich etwas aus Cs "longjmp" ergibt. Sie sind meist mit OOP verbunden. Es scheint, dass eine ideale Nutzung / Theorie / Best Practices noch in der Entwicklung ist. Java hat eines der aufwändigeren Modelle. Wie Sie bemerken, gibt es viele "Antimuster", die sich auf Ausnahmen beziehen. Ein Teil davon hängt mit der Theorie des "fehlertoleranten Rechnens" zusammen, die insgesamt ebenfalls in den Kinderschuhen steckt.
vzn
Sie könnten Ausnahmen als Teilmenge der Fortsetzungstheorie betrachten. Siehe en.wikipedia.org/wiki/Continuation
jmite
@jmite Ausnahmen und Fortsetzungen sind sehr unterschiedlich. Ausnahmen werden dynamisch an ihre Handler gebunden, Fortsetzungen dagegen statisch. Im Allgemeinen können Fortsetzungen allein nicht zum Implementieren von Ausnahmen verwendet werden, zumindest bei Vorhandensein von Typen, siehe z. B. Typisierte Ausnahmen und Fortsetzungen können sich nicht mit Makros ausdrücken .
Martin Berger
"Von der Sprache definierte Ausnahmen werden von Benutzerprogrammen sehr selten wiederverwendet." Das ist so wahr! Das Definieren benutzerdefinierter Ausnahmen ist sehr selten erforderlich. Zum Beispiel definieren Python und seine Stdlib so etwas wie 160 Ausnahmen. Die Wahrscheinlichkeit, dass die Ausnahme, über die Sie nachdenken, dort nicht definiert wurde, ist sehr gering. Einige (die meisten?) Dieser Ausnahmen sind nicht allgemein bekannt. Zum Beispiel LookupErrorwäre das vollkommen in Ordnung für jeden benutzerdefinierten Container, aber ich viele Leute wissen nicht einmal, dass es existiert.
Bakuriu
1
@jmite Eine weitere Begegnung mit Ausnahmen vor diesem Thema fand ich in Benjamin C. Pierces Buch Types and Programming Languages. Wo er Fehler im Zusammenhang mit der Definition eines Funktionstyps erwähnt. Dh von seinem Standpunkt aus , Fehler sind nur noch ein weiteren Wert zurück von Funktionen (und zusammen mit dem anderen Argumente sie eine ganze Art bilden, wenn ich darf , so sagen).
wvxvw

Antworten:

8

Es gibt eine große Anzahl von Veröffentlichungen zu Ausnahmen, mit einigen theoretischen Untersuchungen. Hier ist eine unstrukturierte und alles andere als vollständige Liste mit einigen Beispielen. Entschuldigung, ich habe im Moment keine Zeit für eine gezielte Antwort.

  • B. Randell, Systemstruktur für Softwarefehlertoleranz.
  • JB Goodenough. Ausnahmebehandlung: Probleme und eine vorgeschlagene Notation.
  • JB Goodenough. Strukturierte Ausnahmebehandlung.
  • BG Ryder, ML Soffa, Einflüsse auf das Design der Ausnahmebehandlung.
  • D. Teller, A. Spiwack, T. Varoquaux, Fangen Sie mich an, wenn Sie können: Hin zu typsicherem, hierarchischem, leichtgewichtigem, polymorphem und effizientem Fehlermanagement in OCaml.
  • X. Leroy, F. Pessaux, Typbasierte Analyse nicht erfasster Ausnahmen.
  • R. Miller, A. Tripathi, Probleme mit der Ausnahmebehandlung in objektorientierten Systemen.
  • S. Drew, KJ Gough, J. Ledermann, Implementierung von Zero-Overhead-Ausnahmebehandlung.
  • B. Stroustrup, Ausnahmesicherheit: Konzepte und Techniken.
  • D. Malayeri, J. Aldrich, Practical Exception Specifications.
  • H. Nakano, Eine konstruktive Formalisierung des Fang- und Wurfmechanismus.
  • A. Nanevski, Ein modaler Kalkül für die Ausnahmebehandlung.
  • P. de Groote, Eine einfache Berechnung der Ausnahmebehandlung.
  • H. Thielecke, Ausnahmen und Fortsetzung in Staatsanwesenheit.
  • JG Riecke, H. Thielecke, typisierte Ausnahmen und Fortsetzungen können sich nicht mit Makros ausdrücken.
  • M. van Dooren, E. Steegmans, Kombination der Robustheit geprüfter Ausnahmen mit der Flexibilität ungeprüfter Ausnahmen mithilfe verankerter Ausnahmedeklarationen.
  • JA Vaughan, Eine logische Interpretation von Java-Ausnahmen.
  • S. Marlow, S. Peyton Jones, A. Moran, Asynchrone Ausnahmen in Haskell.
  • B. Jacobs, F. Piessens, Failboxes: Nachweislich sichere Ausnahmebehandlung.
Martin Berger
quelle
Wow, vielen Dank! Ich brauche ein paar Monate (wenn nicht mehr), um mit der positiven Antwort zurückzukommen :) Jetzt bin ich zwischen ein paar Büchern hin- und hergerissen, ohne zu wissen, wo ich anfangen soll!
wvxvw
2
In vielen dieser Artikel geht es um das Implementieren oder Modellieren von Ausnahmen in Programmiersprachen und nicht um das Entwerfen von Ausnahmehierarchien. Könnten Sie die Liste auf die relevanten Papiere reduzieren?
Gilles 'SO- hör auf böse zu sein'
@Gilles Die ursprüngliche Frage war etwas unklar. Ich bin der Meinung, dass was als angemessene Ausnahmen gilt, hauptsächlich von der Anwendung abhängt. Das einzige wirkliche theoretische Problem bei Ausnahmen ist der Kompromiss zwischen (1) dem Koppeln nicht verwandter Module durch Ausnahmen (aus diesem Grund hat keine Sprache nach Java verbindliche Ausnahmespezifikationen) und (2) dem Benutzer eines Moduls einen Hinweis darauf zu geben, welche Arten von Fehlern zu erwarten sind und (3) Hilfe des Compilers bei der Fehlerbehandlung. Soweit ich sehen kann, wurde noch keine wirklich überzeugende Lösung für dieses Rätsel gefunden.
Martin Berger
6

Ich weiß nicht, ob es eine Theorie gibt oder nicht, aber es kann eine aufkommende pragmatische experimentelle Wissenschaft geben.

Die beste Quelle, an die ich denken kann, ist Bjarne Stroustrup, Das Design und die Entwicklung von C ++, Addison-Wesley, 1994 . Wenn ich mich richtig erinnere (es ist ein sehr gutes Buch und die Leute leihen es mir aus und geben es nicht zurück, so dass ich im Moment keine Kopie habe), gibt es ein Kapitel über Ausnahmen. Das C ++ - Komitee unter Stroustrup benötigte viele empirische Beweise dafür, dass ein vorgeschlagenes Feature notwendig war, bevor es zur Sprachdefinition hinzugefügt werden konnte. Die Wikipedia-Seite über Ausnahmen enthält das folgende Zitat aus diesem Buch:

Auf dem Palo Alto [C ++ - Standardisierung] -Treffen im November 1991 hörten wir eine brillante Zusammenfassung der Argumente für die Terminierungssemantik, die sowohl auf persönlichen Erfahrungen als auch auf Daten von Jim Mitchell (von Sun, ehemals Xerox PARC) beruhte. Jim hatte über einen Zeitraum von 20 Jahren die Ausnahmebehandlung in einem halben Dutzend Sprachen verwendet und war als einer der Hauptentwickler und Implementierer des Cedar / Mesa-Systems von Xerox ein Befürworter der Wiederaufnahmesemantik. Seine Botschaft war, dass die Kündigung der Wiederaufnahme vorgezogen wird. Dies ist keine Ansichtssache, sondern eine Frage jahrelanger Erfahrung. Die Wiederaufnahme ist verführerisch, aber nicht gültig. Er untermauerte diese Aussage mit Erfahrungen aus mehreren Betriebssystemen. Das Schlüsselbeispiel war Cedar / Mesa: Es wurde von Leuten geschrieben, die die Wiederaufnahme mochten und benutzten, aber nach zehn Jahren des Gebrauchs, es gab nur noch eine Verwendung der Wiederaufnahme im halben-Millionen-Linien-System - und das war eine Kontextuntersuchung. Da eine Wiederaufnahme für eine solche Kontextabfrage eigentlich nicht erforderlich war, wurde sie entfernt und in diesem Teil des Systems eine signifikante Geschwindigkeitssteigerung festgestellt. In jedem Fall, in dem eine Wiederaufnahme verwendet worden war, war sie über die zehn Jahre zu einem Problem geworden, und ein geeigneteres Design hatte sie ersetzt. Grundsätzlich war jede Verwendung der Wiederaufnahme ein Versagen, getrennte Abstraktionsebenen disjunkt zu halten. In jedem Fall, in dem eine Wiederaufnahme verwendet worden war, war sie über die zehn Jahre zu einem Problem geworden, und ein geeigneteres Design hatte sie ersetzt. Grundsätzlich war jede Verwendung der Wiederaufnahme ein Misserfolg, getrennte Abstraktionsebenen disjunkt zu halten. In jedem Fall, in dem eine Wiederaufnahme verwendet worden war, war sie über die zehn Jahre zu einem Problem geworden, und ein geeigneteres Design hatte sie ersetzt. Grundsätzlich war jede Verwendung der Wiederaufnahme ein Misserfolg, getrennte Abstraktionsebenen disjunkt zu halten.

In C ++ ist RAII der eigentliche Gewinn , wodurch die Freigabe von Ressourcen bei Fehlern erheblich vereinfacht wird. (Es beseitigt nicht die Notwendigkeit für throwund try- catch, aber es bedeutet, dass Sie nicht brauchen finally.)

Ich denke, die Sache, die sie davon überzeugt hat, dass sie Ausnahmen brauchten, sind generische Container: Der Container-Schreiber weiß nichts über die Arten von Fehlern, die die enthaltenen Objekte zurückgeben müssen (und erst recht nicht, wie sie behandelt werden), sondern über den Code, der diese Objekte in den Container eingefügt hat Der Container muss etwas über die Schnittstelle dieser Objekte wissen. Da wir jedoch nicht wissen, welche Arten von Fehlern die enthaltenen Objekte auslösen können, können wir keine Standardisierung für Ausnahmetypen vornehmen. (Umgekehrt: Wenn wir Ausnahmetypen standardisieren könnten, bräuchten wir keine Ausnahmen.)

Das andere, was die Leute anscheinend über die Jahre gelernt haben, ist, dass es schwierig ist, Ausnahmespezifikationen korrekt in eine Sprache zu setzen. Siehe zum Beispiel diese: http://www.gotw.ca/publications/mill22.htm , oder diese: http://www.gotw.ca/gotw/082.htm . (Und es ist nicht nur C ++, Java-Programmierer haben auch lange Auseinandersetzungen über ihre Erfahrungen mit geprüften und nicht geprüften Ausnahmen .)

Ein wenig über die Geschichte der Ausnahmen. Der klassische Artikel lautet: John B. Goodenough: "Ausnahmebehandlung: Probleme und eine vorgeschlagene Notation", Commun. ACM 18 (12): 683-696, 1975. Vorher waren jedoch Ausnahmen bekannt. Mesa hatte sie ungefähr 1974, und PL / I könnte sie auch gehabt haben. Ada hatte vor 1980 einen Ausnahmemechanismus. Ich glaube, dass die Ausnahmen von C ++ am meisten von der Erfahrung mit Barbara Liskovs CLU-Programmiersprache ab 1976 beeinflusst wurden. Barbara Liskov: "Eine Geschichte der CLU" in Geschichte der Programmiersprachen --- II , Thomas J. Bergin Jr. und Richard G. Gibson Jr. (Hrsg.). S. 471–510, ACM, 1996 .

Wandering Logic
quelle
Das ist interessant und ich muss mehr recherchieren, um besser zu antworten. Aber bis jetzt: Ich weiß, dass es einen sehr starken Einwand gibt, Ausnahmen in C ++ jemals zu verwenden (vielleicht eine Anekdote, aber iirc Google-Codierungskonventionen, die verwendet wurden, um die Verwendung von Ausnahmen zu verbieten). Von Java geprüfte Ausnahmen sind sicherlich ein einzigartiges und daher interessantes Experiment, aber das Feature hat im Laufe seiner Geschichte so viele schlechte Credits verdient ... die meisten Leute werfen sie einfach zur Laufzeit um (obwohl dies nur mit der Syntax zu tun haben mag).
wvxvw
Ich bin eher mit der Common-Lisp-Klassifizierung von Ausnahmen vertraut, bei der versucht wurde, sie (obwohl mit geringem Erfolg) nach dem Grad der Bedrohung aufzuteilen, die sie für das Programm darstellen. zB serious-conditionvs simple-condition. Ich lese jetzt auch JL Austing, wo er Fehler (die nicht mit der Programmierung zusammenhängen) in Gruppen einordnet, basierend darauf, wie das System die Aufgabe nicht ausgeführt hat (z. B. falsche Teile, die verwendet wurden, gegen unaufrichtige Absichten). Was nicht sofort auf die Programmierung zutrifft, sondern nach einiger Verfeinerung sein könnte.
wvxvw
@Wandering Logic Ich habe Upvodiert, weil Sie erklärt haben, warum C ++ - Excpetios sux sind und das gezielte Einbeziehen von Features die Sprache zerstören könnte.
Val
@wvxvw Die very strong objectiongegen Ausnahmen in C ++ beruht auf zwei Tatsachen: Es gibt kein finallyKonstrukt und niemand anderes verwendet Ausnahmen. Das erste Problem verschlimmert auch das zweite. Das heißt, wenn Sie keine haben finally, können Sie die Ressource nicht schließen, wenn eine Ausnahme auftritt. Da niemand Ausnahmen verwendet, die von allen Funktionen / APIs vermieden werden, müssen Sie die gesamte traditionelle C ++ - Infrastruktur, in die alle Funktionen mit Ihren Ausnahmen eingebunden sind, erheblich umbauen, um die Vorteile in Ihrem Code zu nutzen. Aber das Fehlen von finallymacht diesen Ansatz auch unmöglich.
Val
@wvxvw: Die Konventionen von Google verbieten das Auslösen von Ausnahmen über Modulgrenzen (.so) hinweg. Dies liegt daran, dass Ausnahmen in C ++ Laufzeit-Typinformationen (RTTI) verwenden und Linux die Laufzeit-Typisierung nicht gut implementiert hat. Unter Linux können Sie Laufzeit-Typen nur dann zuverlässig zwischen Modulen übertragen, wenn Sie die Module mit derselben Version desselben Compilers kompiliert und mit der identischen Version von libstdc ++ verknüpft haben. In Wirklichkeit ist dies eine Ablehnung von C ++ im Allgemeinen durch die Linux-Community, keine Ablehnung von Ausnahmen im Besonderen.
Wandering Logic
3

Lassen Sie mich nur darauf hinweisen, dass Ausnahmen einen rechnerischen Effekt haben . Andere Computereffekte sind veränderlicher Zustand, E / A, Nichtdeterminismus, Fortsetzungen und viele andere. Ihre Frage könnte also allgemeiner gestellt werden: Wie bilden wir Hierarchien von Berechnungseffekten, wie organisieren wir sie und warum haben wir die, die wir haben, und nicht die anderen usw.

Andrej Bauer
quelle
1
Ich finde das völlig irrelevant. Es geht nicht darum, den Begriff der Ausnahmen zu modellieren, sondern ihn auf Fehler abzubilden. Ich denke, der richtige Weg, ihn aus einer PLT-Perspektive zu beschreiben, wäre eine Theorie der Ausnahmehierarchien.
Gilles 'SO- hör auf böse zu sein'
Hmm, du hast recht. Ich habe die Antwort korrigiert, um darauf hinzuweisen, aber ich glaube, es ist nicht erforderlich, sie zu löschen. Was denkst du?
Andrej Bauer