Siehe auch ExceptionsDiskussion, ExceptionsAlsArchitekturBestandteil, EinGutesExceptionBeispiel, ExceptionsConsideredHarmful, CheckedExceptionsConsideredHarmful.
Aus Sicht von SpracheLava ist ein Exception-Handling-Konzept nicht nur sinnvoll, sondern geradezu unentbehrlich, da wir in SpracheLava generell anstreben, das versehentliche Arbeiten mit undefinierten Variablen-Werten durch statische oder Laufzeit-Checks zu verhindern, denn die Aufklärung solcher Fehler ist oft außerordentlich mühsam und zeitraubend:
Es kommt häufig vor, dass eine Methode einer Klasse nicht die normalerweise erwarteten Ergebnisse (Output-Parameter, Return-Value) liefern kann. Wenn in diesem Fall das Laufzeit-System nicht verhindert, dass der Aufrufer diese Rückgabewerte (soweit sie von der Methode überhaupt schon vor dem Zeitpunkt der Exception gesetzt worden sind!) dennoch unbesehen benutzt, werden oft schwer aufzuklärende Folgefehler auftreten.
|
Exception-Handling ist eine Methode, "Vertragsbrüche" beim Methodenaufruf nicht-ignorierbar zu machen und ihre Behandlung ohne viel Umstand von der unterst-möglichen auf die am besten geeignete Behandlungsebene zu verschieben.
Maßnahmen in Lava:
Auf eine "Aufräum"-Klausel "finally" (Java, C#), die unter allen Umständen bei Verlassen des try-Statements ausgeführt wird, haben wir in Lava verzichtet: Generell wird die Lebensdauer von Lava-Objekten durch Referenzzähler kontrolliert. Dadurch ist gesichert, dass ein Objekt immer zum frühestmöglichen Zeitpunkt automatisch freigegeben wird, nämlich sobald es nicht mehr referiert wird.
Zu diesem wohldefinierten Zeitpunkt wird dann auch automatisch die Finalize-Methode aufgerufen (die entweder von Klasse "Object" geerbt wird oder handprogrammiert sein kann). Durch expliziten Aufruf von Objekt::Finalize kann ein Objekt vorzeitig unbenutzbar gemacht ("zombifiziert") werden: Jeder nachfolgende Benutzungsversuch löst dann eine spezifische Exception aus.
Ein handprogrammiertes Finalize wird man in Lava nur benötigen, wenn es um die korrekte Freigabe von Betriebssystem- oder anderen Nicht-Lava-Objekten geht, deren Lebensdauer nicht durch Lava-Referenzzähler kontrolliert wird.
Ergänzende Anmerkungen: Das versehentliche Benutzen undefinierter Variablen-Werte (und damit die Haupt-Ursache von Exceptions) wird übrigens in Lava nicht nur für Output-Parameter, sondern auch für lokale und Member-Variablen (durch Programmierzeit-Checks) verhindert:
Siehe dazu auch http://lavape.sourceforge.net/doc/html/RepetComputSamples.htm.
Andere denkbare Maßnahmen, um das irrtümliche Arbeiten mit undefinierten oder semantisch nicht adäquaten Variablen-Werten unwahrscheinlicher zu machen, die z. B. die Ursache für gewisse gescheiterte Weltraum-Missionen waren:
Wenn ein Input-Parameter einer Methode in einem gewissen Wertebereich liegen muss (was beim Ariane5Absturz meines Wissens der Fall war), so müsste ein gewissenhafter Methoden-Programmierer dies entweder durch eine Assertion (eine Methoden-Vorbedingung, oder ein Lava-"assert"-Statement, löst bei Verletzung Exception aus) oder durch eine if-Verzweigung absichern, die nötigenfalls eine spezifische Exception auslöst. Zumindest aber sollte eine solche Vorbedingung als Kommentar in der Methoden-Deklaration ausdrücklich genannt werden, damit man schon zur Programmierzeit auf das Problem aufmerksam wird.
Eine amerikanische Mars-Mission ist meines Wissens gescheitert, weil Maßeinheiten (yard und meter o. ä.) verwechselt worden waren. Dies könnte man vermeiden, indem man für Zahlen-Parameter nicht einfach Float-, Double- oder Integer-Typen benutzt, sondern (sofern diese Basis-Typen, wie in Lava, normale Klassen sind) daraus abgeleitete Klassen, die die Maßeinheit ausdrücken. Dann wäre die Verwechslung schon zur Programmierzeit als Typ-Fehler aufgefallen.
Man braucht dann aber auch ein spezifisches Ausdrucksmittel (wie die "scale"-Expressions in Lava), um einen gewöhnlichen Zahlenwert, der vielleicht aus einer mathematischen Funktion (Sinus o. ä.) herauskommt, in einen solchen "dimensionierten" Wert umzuinterpretieren/zu spezialisieren. Siehe dazu Punkt 8 der Release Notes zu Lava 0.6: http://lavape.sourceforge.net/doc/html/ReleaseNotes.htm#R0_6, und das zugehörige Beispiel http://lavape.sourceforge.net/doc/Samples/ScaleUnits.htm.
Zu Exceptions in SpracheLava siehe auch http://lavape.sourceforge.net/doc/html/ExceptionSamples.htm
Exception-Handling durch Callbacks:
Das "typverzweigende" Exception-Handling durch typspezifische "catch"-Klauseln ist ja eigentlich unbefriedigend und unerwünscht, weil es das objektorientierte Denken untergräbt.
Das objektorientierte Exception-Handling durch eine überschriebene "Object::catch"-Methode (s.o.) ist nur dann sinnvoll anwendbar, wenn derjenige, der die Exception behandelt, zugleich die abgeleitete Exceptionklasse "in der Hand hat", also nach seinen Vorstellungenn gestalten kann, insbesondere die überschriebene "catch"-Methode selbst programmieren kann, was meistens nicht der Fall sein wird, da die Exceptionklasse normalerweise von dem Programmierer der gerufenen Methode gestaltet werden wird.
Ein angemessener objektorientierter Umgang mit diesen Fällen kann in Lava dadurch erreicht werden, dass die exception-auslösende Methode unmittelbar vor dem "Werfen" der Exception ein spezifisches "Signal" im Sinne des Lava-Callback-Konzeptes emittiert, für das der Methoden-Aufrufer eine von ihm programmierte Callback-Methode abonniert hat, die dann also vor dem formellen Auslösen der Exception auf Grund des emittierten Signals automatisch aufgerufen wird und die eigentliche Exceptionbehandlung übernimmt.