Entwurf und Implementierung effizienter Objektsysteme für funktionale und imperative Programmiersprachen am Beispiel von Lisp [article]

Harry Bretthauer, Universität Des Saarlandes, Universität Des Saarlandes
2007
In der Reihe GMD Research Series werden Forschungs-und Entwicklungsergebnisse aus der GMD zum wissenschaftlichen, nichtkommerziellen Gebrauch veröffentlicht. Jegliche Inhaltsänderung des Dokuments sowie die entgeltliche Weitergabe sind verboten. The purpose of the GMD Research Series is the dissemination of research work for scientific non-commercial use. The commercial distribution of this document is prohibited, as is any modification of its content. Die vorliegende Veröffentlichung entstand
more » ... m/ The present publication was prepared within: Abstract Up to now a gap is evident in object systems of functional and procedural programming languages. The most expressive object system developed in the family of functional languages is CLOS with its outstanding metaobject protocol. Its performance, h o wever, does not meet the users' needs. In the family of procedural languages the most e cient object system developed is C++. But its support of central concepts of object-oriented programming, such a s specialization and generalization of object classes, is not su cient. This also applies in some degree for Java. Using Lisp as an example this thesis shows how e cient object systems can bedesigned and implemented so that simple constructs have no overhead because of the presence of complex concepts such as the metaobject protocol or the rede nition of classes. In contrast to former assumptions, this thesis proofs for the rst time that the above mentioned concepts can be realized without embedding an interpreter or an incremental compiler in the run-time environment. Therefore, they can also be supported in traditional compileroriented programming languages such as Ada, Pascal, Ei el, C ++ , and Java. Kurzfassung Bisherige Objektsysteme funktionaler und imperativer Programmiersprachen weisen eine L ucke auf. Aus der funktionalen Tradition wurde das ausdrucksst arkste Objektsystem CLOS entwickelt, das insbesondere durch sein Metaobjektprotokoll hervorsticht, dessen Performanz aber zu w unschen ubrig l at. Auf der anderen Seite zeichnet sich C++ als besonders e zient aus, unterst utzt aber zentrale Konzepte objektorientierter Programmierung wie Spezialisieren und Generalisieren von Objektklassen nur unzureichend, was abgeschw acht auch f ur Java gilt. In dieser Arbeit wird am Beispiel von Lisp gezeigt, wie man e ziente Objektsysteme unter Ber ucksichtigung des Verursacherprinzips so entwirft und implementiert, da einfache Konstrukte keinen Overhead durch die Pr asenz aufwendiger Konzepte, wie des Metaobjektprotokolls oder des Rede nierens von Klassen, mittragen m ussen. Entgegen bisherigen Annahmen wird hier erstmals nachgewiesen, da diese Konzepte auch ohne Quellcodeinterpretation bzw. -kompilation zur Laufzeit realisiert und somit auch in traditionellen, compiler-orientierten Programmiersprachen, wie Ada, Pascal, Ei el, C ++ und nat urlich Java, u n terst utzt werden k onnen. Schlagw orter: Objektsystem, Konzepte objektorientierter Programmierung, Spezialisieren, Generalisieren, Metaobjektprotokoll, Rede nieren von Klassen, funktionale und imperative Programmiersprachen, Performanz, Quellcodeinterpretation, Kompilation zur Laufzeit. vi Zusammenfassung Objektorientierte Sprachkonstrukte kann man inzwischen in fast allen Programmiersprachen nden. Bei genauerer Betrachtung stellt man jedoch fest, da es weder einen Konsens uber die zu unterst utzenden Konzepte noch eine einheitliche Terminologie gibt. Im Spektrum objektorientierter sowie funktionaler und imperativer Programmiersprachen mit entsprechenden objektorientierten Erweiterungen lassen sich z w ei Entwicklungsstr ange identi zieren. Der eine Strang ist vom Bem uhen um problemad aquate Ausdrucksmittel gepr agt, oft unter Vernachl assigung des Performanzaspekts. Hierzu z ahlen Sprachen wie Smalltalk und CLOS. Der andere Strang stellt E zienzfragen in den Vordergrund und ber ucksichtigt Erkenntnisse und Anforderungen aus der objektorientierten Wissensrepr asentation nur unzureichend. Hier ist vor allem C++, aber auch Java zu nennen. Es stellt sich daher die Frage, ob die L ucke zwischen den beiden Str angen geschlossen und der Gegensatz zwischen Erfordernissen einer problemad aquaten und somit anwendungsnahen objektorientierten Sprache und den Restriktionen einer f ur die gegenw artige Rechnergeneration e zient implementierbaren Sprache uberwunden werden kann. Das Ziel dieser Arbeit ist also der Entwurf und die Implementierung von Objektsystemen f ur funktionale und imperative Programmiersprachen, die den Anforderungen komplexer Anwendungen bez uglich k onzeptueller Klarheit, Flexibilit at und E zienz standhalten. Am Beispiel von Lisp mit seinen bekanntesten Objektsystemen Flavors und CLOS wird hier schrittweise gezeigt, wie man die E zienz dieser Objektsystemen verbessern kann, ohne ihre wesentlichen objektorientierten Konzepte aufzugeben und auf das Niveau von C++ zur uckzufallen. Allerdings mu signi kanten E zienzverbesserungen eine kritische Re ektion dieser Konzepte vorausgehen. Ausgehend von den De ziten existierender Objektsysteme sowie den Anforderungen komplexer, insbesondere wissensbasierter, Systeme habe ich 12 Kriterien formuliert, an denen alle Entwurfsentscheidungen zu messen sind: Abstraktion, Klassi kation, Spezialisierung, Komposition, Modularisierung, Orthogonalit at, Einfachheit, Re ektion, Erweiterbarkeit, Robustheit, E zienz und das Verursacherprinzip. Diese Kriterien m ussen auf unterschiedliche Weise ber ucksichtigt werden. Die Unterst utzung der Klassi kation, der Spezialisierung, der Re ektion und der Erweiterbarkeit ist die ureigenste Aufgabe eines Objektsystems. Komposition und Modularisierung stellen dazu orthogonale Prinzipien dar. Ein Modulkonzept sollte zus atzlich zum Objektsystem vorhanden sein und es sollte benutzt werden, um das Objektsystem zu modularisieren. Orthogonalit at und Einfachheit beziehen sich auf die Gestaltung der Grundkonzepte und entsprechender Sprachkonstrukte. Ein Objektsystem mu robust gegen uber seinen Erweiterungen sein. Re ektions-und Spezialisierungsmittel d urfen die Integrit at des Ob-viii jektsystems und seiner Anwendungen nicht gef ahrden. Die E zienz eines Objektsystems bezieht sich v or allem auf die statische und dynamische Objekterzeugung, auf Feldzugri e und den generischen Dispatch einschlielich der Methodenkombination. Um ein e zientes Verhalten komplexer Systeme zu erreichen, brauchen Programmierer ein transparentes Efzienzmodell der Programmiersprache. Die Sprachkonstrukte des Objektsystems m ussen daher das Verursacherprinzip einhalten und dieses dem Programmierer bewut machen. Schlielich mu das Sprachdesign verschiedene Implementierungstechniken unterst utzen, um eine umfassende E zienz zu erm oglichen. Auf der Grundlage dieser Kriterien und der bisherigen Objektsysteme habe ich objektorientierte Sprachkonzepte f ur TEO entwickelt, die zum einen bessere Ausdrucksm oglichkeiten scha en und zum anderen e zienter implementierbar sind, z. B. im Vergleich zu CLOS. Objektorientierte Sprachkonzepte lassen sich unter vier Aspekten diskutieren: der Objektstruktur, dem Objektverhalten, der Vererbung und der Re ektion. Die ersten drei Aspekte k onnen in einer Ebene behandelt werden, der sogenannten Objektebene. Die Objektstruktur und das Objektverhalten sind der Gegenstand von Vererbungskonzepten. Mit der Re ektion wird eine weitere Ebene betreten, die sogenannte Metaobjektebene. Zusammen erh alt man eine metare ektive Systemarchitektur. Auf der Metaobjektebene werden Metaobjekte zu Objekten erster Ordnung. Wie man auf der Objektebene seine Anwendungsklassen erweitert und spezialisiert, so kann man auf der Metaobjektebene das Objektsystem der Programmiersprache erweitern und spezialisieren. Diese neue Dimension objektorientierter Programmierung wurde bisher nur in CLOS richtig unterst utzt. Irrt umlicherweise glaubte man bisher, als Voraussetzung daf ur die Quellcodeinterpretation bzw. -kompilation zur Laufzeit zu ben otigen. Mit dieser Arbeit habe ich erstmals nachgewiesen, da dies nicht der Fall ist. Damit sind die Grundlagen gescha en worden, um die Konzepte der Spracherweiterungsprotokolle auch in traditionellen, compiler-orientierten Programmiersprachen, wie Ada, Pascal, Ei el, C ++ und nat urlich Java, z u u n terst utzen. Die Klassi kation der Struktur und des Verhaltens von Objekten steht im Mittelpunkt objektorientierter Programmierung. Mit der Unterst utzung des Generalisierens und Spezialisierens von Objektklassen wird die Hauptaufgabe eines Objektsystems angesprochen: Um die Objektstruktur spezialisieren zu k onnen, m ussen die Felder der Superklassen ererbt und ihre Annotationen wie z. B. der Default-Wert spezialisiert werden k onnen. Dies ist weder in Smalltalk noch in C ++ noch in Java m oglich. In diesen Sprachen k onnen nur neue Felder de niert werden, ererbte Felder werden unspezialisiert ubernommen. Um das Objektverhalten spezialisieren zu k onnen, m ussen Methoden der Superklassen ererbt und speziellere Methoden de niert werden k onnen. Dabei mu es m oglich sein, die ererbte Methode auf abstrakte Weise wiederzuverwenden und zu erg anzen. Dazu braucht man mindestens die einfache explizite Methodenkombination mit callNextMethod als die Generalisierung von super aus Smalltalk sowie inner aus BETA. Dies ist in C ++ nicht gegeben. Im Unterschied zu CLOS unterscheide ich in TEO zwischen expliziter und impliziter Methodenkombination, um z. B. Java-Konstruktoren nicht als Einzelfall, sondern als Methoden mit impliziter Methodenkombination zu subsumieren. ix Die Vererbung regelt, wie das Generalisieren und Spezialisieren von statten geht. Als ein wesentliches Resultat dieser Arbeit wurde die Mixin-Vererbung entwickelt, um die Nachteile der einfachen und allgemeinen multiplen Vererbung zu uberwinden. Dabei wird zwischen wesentlichen und zus atzlichen Aspekten von Objekten unterschieden. Letztere k onnen mehrfach ererbt werden, in Analogie zur Aneinanderreihung mehrerer Adjektive in der nat urlichen Sprache: Basisklassen, die wesentliche Aspekte repr asentieren, bilden untereinander eine einfache Vererbungshierarchie. Mixin-Klassen, die zus atzliche Aspekte repr asentieren, k onnen mehrfach geerbt werden. Allerdings kann eine Basisklasse nur disjunkte Mixin-Klassen erben. E ziente Implementierungen von Objektsystemen setzen ein entsprechendes Sprachdesign voraus. Dieses sollte idealerweise f unf Implementierungstechniken unterst utzen: Modul-Kompilation, Applikations-Kompilation, inkrementelle Kompilation, Bytecode-Kompilation bzw. -Interpretation und Einbettungstechnik. Dabei kann die Bytecode-Kompilation auch unter der Modul-Kompilation subsumiert werden. Auerdem pro tiert die Einbettungstechnik von allen Formen der Kompilation der Basissprache. Da auch Sprachen der Lisp-Familie von der Modul-und Applikations-Kompilation pro tieren k onnen, wurde im Projekt APPLY nachgewiesen. Der daf ur notwendige Verzicht auf Quellcodeinterpretation und -kompilation zur Laufzeit reicht im Prinzip aus, um traditionelle Kompilationstechniken erfolgreich anzuwenden. Im Verzicht auf Quellcodeinterpretation liegt auch der Schl ussel f ur die E zienz meiner Implementierung. Im Unterschied zu CLOS, da mit seinen Rede nitionsm oglichkeiten prim ar auf inkrementelle Kompilation ausgerichtet ist, unterst utzt TEO alle genannten Implementierungstechniken. Insbesondere tr agt die strikte Unterscheidung zwischen Sprachkonstrukten der Objekt-und der Metaobjektebene sowie die Modularisierung des Metaobjektprotokolls dazu bei, auch die Modul-und Applikations-Kompilation zu unterst utzen, was ein Novum f ur metare ektive Objektsysteme darstellt. Aber selbst mit der Einbettungstechnik und ohne explizite Verwendung des inkrementellen Compilers ist meine TEO-Implementierung insgesamt e zienter als die derzeit besten kommerziellen CLOS-Realisierungen. Dies ist das Resultat eines konsequenten Sprachdesigns und einer einfachen Implementierungstechnik unter Beachtung des Verursacherprinzips. Dies hat insbesondere am Beispiel des Rede nitionskonzepts in TEO dazu beigetragen, den entsprechenden Overhead auf Objekte zu beschr anken, die diese Funktionalit at auch wirklich ben otigen. Dar uberhinaus konnte die Objekterzeugung und die Methodenkombination in TEO wesentlich e zienter realisiert werden als in CLOS. x Danksagung Diese Arbeit entstand nicht uber nacht, es waren eher viele N achte. Voraus-und mitgegangen war die Hilfe vieler Menschen, denen ich besonders danken m ochte.
doi:10.22028/d291-25894 fatcat:73lb266sqrfhpfgvfdt4btuege