zurück zum Artikel

Wenn Objekte Smalltalk machen

Hans Nikolaus Beck
Wenn Objekte Smalltalk machen

Smalltalk gilt als wesentlich für die Ausprägung der objektorientierten Programmiersprachen. Dabei ist Smalltalk mehr als nur eine Sprache, es ist ebenso Entwicklungsumgebung wie auch ein Softwaresystem mit eigener Philosophie.

Der Satz "Make things as simple as possible, but not simpler" stammt von Albert Einstein. In der Realität der Softwareentwicklung verfehlen Teams dieses Ziel oft genug. Um der Komplexität zu Leibe zu rücken, entstanden viele Programmiersprachen mit raffinierten Konzepten. Entwickler können sich mit Funktionen ausdrücken, Klassen und Objekte ersinnen und Agenten an die Arbeit schicken. Trotz dieser Vielfalt scheinen Funktionen, Objekte und Schritt-für-Schritt Anweisungen (also imperative Programmierung) immer noch so etwas wie wesentliche Säulen der Programmierung zu sein.

Smalltalk ist dabei fast in Vergessenheit geraten. Die Entwicklung der Programmiersprache reicht in die frühen siebziger Jahre zurück. Sich mit ihr zu beschäftigen kommt einer wunderbaren Zeit- und Erkenntnisreise gleich. Man erkennt Intention und Sinn vieler für Entwickler selbstverständlichen Ideen. Dabei zeigt Smalltalk in seinem Aufbau eine klare Synthese von Objektprogrammierung, Funktionen und Typen. Die Sprache ist trotz ihres Alters auf dem Stand der Technik. Mit der interaktiven Umgebung und dynamischen Anlage ist sie mehr denn je schlagkräftig für die Beherrschung von Softwarekomplexität und -qualität. Aktuelle Smalltalk-Systeme bieten alles für den Umgang zeitgemäßer Techniken und laden zu einer Entdeckungsreise ein.

Für die praktische Betrachtung sei das Beispiel Pharo [1] herangezogen. Nach dem Start zeigt es ein Fenster, das wieder mehrere Fenster enthalten kann (vgl. Abb. 1)

Screenshot des Pharo Desktop (Abb. 1)

Screenshot des Pharo Desktop (Abb. 1)

Aufrufbar über das Kontextmenü existieren beispielsweise das Playground- und das Workspace-Fenster, ein leeres Textfenster, in dem Entwickler Smalltalk-Ausdrücke eingeben und direkt ausführen können, nach bestem REPL-Prinzip (Read-Eval-Print Loop).

Unter anderem steht ein Systembrowser zur Verfügung, der es erlaubt, alle im System verfügbaren Klassen und Methoden einzusehen. Mit dem Playground lassen sich ein paar einfache Experimente durchführen, um Erfahrungen bei der Arbeit mit Smalltalk zu sammeln.

Smalltalk zeichnet sich durch seine Interaktivität aus. Ausdrücke lassen sich markieren und ausführen beziehungsweise evaluieren. Geben Entwickler beispielsweise 3+4 ein, markieren den Text und bestätigen mit der Tastenkombination Ctrl + P, so erscheint 7. Soweit so gut. Spannend ist, Objekten "live" Nachrichten zu schicken. Nach der Eingabe folgender Befehle in den Playground:

myObject := OrderedCollection new.  
myObject add: 'eins'.
myObject add: 'zwei'.
myObject.

und dem Markieren des gesamten Textes erscheint nach dem Druck auf Ctrl + P folgende Ausgabe:

an OrderedCollection ('eins' 'zwei')

Ctrl + P löst die Evaluierung des markierten Ausdrucks und die Ausgabe des Ergebnisses aus. Die erste Zeile erzeugt ein neues Objekt der Klasse beziehungsweise des Typs OrderedCollection, das in der Variablen myObject gespeichert und zugreifbar ist. Die folgende Zeile schickte dem Objekt die Nachricht add: mit dem Parameter 'eins'. Das Vorgehen heißt in anderen Sprachen Methodenaufruf. Die dritte Zeile fügt den String 'zwei' hinzu. Schließlich sorgt die letzte Zeile für den Zugriff auf das Objekt in der Variablen. Das Ergebnis dieser Zeile ist das Objekt selbst.

Ob Entwickler alle Zeilen markieren und evaluieren oder Zeile für Zeile vorgehen, führt zum selben Ergebnis. Es spielt zudem keine Rolle, ob sie im Playground einen Ausdruck markieren und evaluieren oder in einem Systembrowserfenster. Auf die Weise demonstriert Smalltalk schnell seine großartige Interaktivität: Überall wo Nutzer Text eingeben und markieren können, können sie Objekten interaktiv Nachrichten senden.

Als kleines Experiment kann man zunächst die erste, dann die dritte und erst zuletzt die zweite Zeile evaluieren und kommt zu einem anderen Ergebnis.

Alles ist in Smalltalk ein Objekt – auch Zahlen – und allen Objekten lassen sich Nachrichten senden. Das funktioniert sowohl in der beschriebenen Weise interaktiv als auch in einem Programm. Folgerichtig ist im obigen Listing die Klasse OrderedCollection ebenfalls ein Objekt, denn sie bekommt die Nachricht new. Willkommen im Kaninchenbau.

Ein kleines Experiment demonstriert, was passiert, wenn das Objekt eine Nachricht nicht versteht. Wie in Abbildung 2 zu sehen ist, meldet das Objekt, die Nachricht könne es nicht verstehen ("does not understand").

Das Objekt meldet fehlendes Verständnis (Abb. 2).

Das Objekt meldet fehlendes Verständnis (Abb. 2).

Das Programm stürzt jedoch weder ab, noch bleibt es in einer Schleife stecken. Das Objekt existiert weiterhin und kann weitere Nachrichten entgegennehmen. Da sich die Meldung "does not understand" programmtechnisch nutzen lässt, können Entwickler fehlertolerante Software schreiben.

Im Alltag stellt sich oft die Frage, welche Nachrichten ein Objekt versteht. Die Suche in Dokumentationsportalen und Wikis ist eine Möglichkeit. Smalltalk bietet jedoch eine praktische Abkürzung: Wer im Playground die OrderedCollection markiert und Ctrl + B drückt, öffnet einen Systembrowser, der die Klasse OrderedCollection mit all ihren Nachrichten (Methoden), dem Sourcecode und anderen Details zur Untersuchung anzeigt. Das Vorgehen funktioniert erneut mit allen Objekten und in jedem Fenster.

In der gleichen Weise lassen sich Sourcecode oder Sender von Nachrichten schnell ermitteln: Dazu markieren Entwickler sie und wählen den Befehl Implenters of beziehungsweise Senders of im Kontextmenü aus oder aktivieren ihn per Tastenkombination. Smalltalk hütet nicht nur keine Geheimnisse, sondern unterstützt beim Finden und Verstehen des Codes. Ob Systemklassen oder das frisch heruntergeladene Paket – alles ist transparent. Smalltalk ist ein Lernsystem, indem es Nutzern hilft, von anderen Programmierern zu lernen. Das ist Open Source im besten Wortsinne.

Smalltalk ist nicht nur interaktiv, sondern auch live. Beim Anlegen eines Objekts einer Klasse mit der Nachricht new bleibt es im Speicher, bis kein anderes Objekt mehr darauf zugreift. Das gilt sogar beim zwischenzeitlichen Verlassen von Smalltalk mit Save und dem späteren Neustart. Alle Objekte existieren im sogenannten Image und sind Teil des Gesamtsystems.

Darüber hinaus mag es von Interesse sein, ein Objekt zu untersuchen: Welche Daten enthält es, und welcher Klasse gehört es an? Die Variable myObject aus dem obigen Beispiel enthält demnach immer noch eine OrderedCollection. Das Tastenkürzel Ctrl + I nach dem Markieren von myObject öffnet ein Fenster, aus dem sich entnehmen lässt, welches Objekt in der Variable steckt. Die Daten des Objekts ('eins' und 'zwei') sind ebenfalls einsehbar.

Innenschau eines Objektes (Abb. 3)

Innenschau eines Objektes (Abb. 3)

Das funktioniert ebenso im laufenden Programm. Nach dem Setzen eines Haltepunkts (Breakpoint) an beliebiger Stelle im Code springt beim Erreichen der betreffenden Stelle in der Ausführung der Systembrowser auf. Mit ihm können Entwickler jedes Objekt wie gewohnt inspizieren. Alternativ können sie Ausdrücke mit Ctrl + Shift + D statt Ctrl + P evaluieren und damit einen Debugger starten (s. Abb. 4). Durch die Interaktion mit dem Code ist dessen dynamisches Verhalten in Smalltalk nachvollziehbar. Die Programmiersprache bietet somit ein mächtiges Debugging-System.

Debugger-Fenster mit "Live" Daten (Abb. 4)

Debugger-Fenster mit "Live" Daten (Abb. 4)

Klassen sind wieder Objekte. Sie beantworten Fragen nach ihrem Typ (der Klasse und der Oberklasse) und nach deren bekannten Nachrichten. Das nutzt der oben gezeigte Befehl Senders of. Zudem lassen sich Klassenobjekte in ihrem aktuellen Zustand inspizieren. Das Stichwort für diese Systemeigenschaften ist der Begriff "Reflection".

Entwickler können die Struktur des Systems ermitteln und ändern oder verschieben. Das gilt unter anderem für die Namen von Klassen und Nachrichten (Methoden). Der Vorgang ist als Refactoring bekannt. Es verwundert wenig, dass diese Form der Codeverbesserung im Kontext von Smalltalk ihren Anfang nahm. In seinem Buch "Smalltalk Best Practice Patterns" [1] beschreibt Kent Beck eine Reihe solcher Codepflegearbeiten. Smalltalk unterstützt damit ganz besonders den Anspruch, lesbaren und verständlichen Code zu schreiben und dessen Qualität immer weiter zu erhöhen.

Das wirft die Frage auf, wie jemand auf die Idee kam, ein System zu schaffen, das nicht nur ein elegantes Programmiersystem ist, sondern sozusagen ein Programmierverstehsystem. Dahinter steht die menschenorientierte Philosophie seiner Schöpfer. Ein kleiner Blick auf die Geschichte hilft beim Verständnis.

Die Wurzeln von Smalltalk gehen auf die Idee zurück, dass ein Computer für alle Menschen da sein sollte. Statt eine Maschine nur für Experten zu sein, sollte er sogar Kindern beim Lernen helfen. Diese Vision leitete den am Xerox PARC arbeitenden Alan Kay und seine Kollegen Dan Ingalls, Adele Goldberg und andere in den frühen 1970er Jahren an. Das bedeutete aber zusätzlich, dass das Gerät klein sein musste und kein wandfüllender Schrank. Grafische Displays, Einfachheit in Konzepten wie Bedienung und Interaktivität waren zwingend.

Alan Kay wusste von Seymour Paperts LOGO, einer Sprache gedacht für pädagogische Zwecke. In den 1960er Jahren präsentierte Ivan Sutherland seine graphische Umgebung Sketchpad. Sie erlaubte das interaktive Erstellen von (Linien-)Zeichnungen am Bildschirm, was zu der Zeit ein absolutes Novum war. Sketchpad stellte eine deutliche Erweiterung der damaligen Rolle des Computers als reiner Zahlenfresser dar. Die geometrischen Zeichenfiguren waren übrigens als Instanzen eines Masters implementiert.

Alan Kay hatte eine Ausbildung in Biologie. In dem Dokument "Early History of Smalltalk [2]" beschreibt er, dass er sich von der Idee kommunizierender Zellen hatte inspirieren lassen. Wenn also der Computer helfen sollte, die Welt zu verstehen, sollte er die Natur der kommunizierenden Elemente abbilden. Jedes Objekt für sich wurde auf die Weise zu einem Computer, der Nachrichten versteht und sendet.

Anregungen von Lisp mit seinem interaktiven Evaluieren, LOGO mit dessen Syntax und anderen Systemen anderer Forscher sowie nicht zuletzt die damals beschränkte Hardware bestimmten die praktische Umsetzung der Ideen. Das System bildete eine Nachricht auf die Sequenz <Empfänger, Token, Ausdrücke> ab. Das Token adressierte die gewünschte Funktion des Empfängerobjektes, die Interpretation der Ausdrücke geschah auf ähnliche Art wie bei einem Micro-LISP. Das war der Kern von Smalltalk-72, geschrieben von Dan Ingalls. Diese Urform von Smalltalk bestand letztlich aus einer Sammlung von Objekten mit interpretierten Funktionen.

Es folgten Smalltalk-76 mit virtueller Maschine und Vererbung und schließlich das für heutige Systeme immer noch relevante Smalltalk-80. Von den Grundideen her war Smalltalk also ein Modell der Welt, gedacht um kinderleicht weitere Modelle der Welt zu entwerfen und in Form eines laufenden Programms erlebbar zu machen.

Dass jede Klasse eine Oberklasse hat, ist ein naheliegender Gedanke. Im aktuellen Smalltalk ist die Hierarchie äußerst ausgefeilt, damit die Programmiersprache die gebotene Symmetrie maximal umsetzen kann. Jede Klasse soll schließlich wieder ein ansprechbares Objekt sein. Die Klassen, deren Objekte wiederum Klassen sind, heißen Metaklassen. Die METACLASS ist als einziger Typ im System eine Instanz von sich selbst, also quasi die Wurzel. Die mächtige Reflection-Fähigkeit von Smalltalk begründet sich in der strikt hierarchischen und konsequenten Architektur.

Smalltalk besitzt einen Objektspeicher (Image) mit einem Garbage Collector. Alle Objekte bleiben erhalten, bis die letzte Referenz auf sie erlischt. Klassen sind definiert durch ihre Oberklasse und ein Methodenverzeichnis, der Katalog aller verstandenen Nachrichten und deren Funktion.

Das Wort "Funktion" ist ernst zu nehmen: Funktionale Entwickler mögen Lambda-Ausdrücke, also anonyme Funktionen, die wiederum Objekte sein können. Smalltalk bietet dafür als Blöcke bezeichnete vollwertige Objekte, die Nachrichten empfangen können. Sie haben Closures und lassen sich mit der passenden Nachricht zur Angabe ihres Wertes bewegen:

myObject := OrderedCollection new.       
myObject add: [ x | x*x ].
myFunc := myObject at: 1.
myFunc value: 2.

Smalltalk gibt als Ergebnis der Evaluierung '4' aus. Auf unterster Ebene führt eine virtuelle Maschine sogenannte Primitive aus, also Bytecode-Befehle. In heutigen Systemen besitzen die virtuellen Maschinen effiziente JIT-Compiler (Just in Time).

Seit Smalltalk-72 finden Anwender eine grafische Benutzeroberfläche mit Mausbedienung. Fenster und Menüs gehörten und gehören fest zum System. Heutzutage lässt sich aber (manches) Smalltalk für Serveranwendungen "headless" ohne GUI betreiben.

Zu einer Programmiersprache gehört immer eine gut gepflegte Bibliothek. Smalltalk zeigt dabei seinen Charakter als Systemumgebung. Es gibt Klassen für Collections wie die im Beispiel gezeigte OrderedCollection. In diesen Strukturen lassen sich alle Arten von Objekten speichern. Array und Dictionary sind Spezialformen davon. Schließlich finden Entwickler viele Arten von Streams und eine breite Klassenpalette für Grafik und die GUI. Die konkrete Ausstattung hängt vom jeweiligen System ab.

Als Sprache bietet Smalltalk zudem Kontroll- und Schleifenstrukturen. Schleifenkörper oder Elemente in IF-Konstrukten sind nicht nur alternativer Code, sondern Blöcke im obigen Sinne. Sie bereiten damit die Bahn für einen funktionsorientierten Ausdrucksstil.

Schließlich existieren Klassen zur Unterstützung des Test Driven Development. Unit-Tests unterstützt Smalltalk gut, und sie gehören zum guten Stil. Geschriebener Code lässt sich in eine Datei serialisieren. Je nach Smalltalk-Implementation ist eine Anbindung an ein Repository wie Git möglich. Gemstone als kommerzielles Smalltalk erlaubt sogar das Speichern in eine objektorientierte Datenbank. Neben den exemplarisch vorgestellten Erweiterungen haben aktuelle Implementierungen deutlich mehr zu bieten.

Smalltalk ist nicht nur eine Programmiersprache. Es ist eine komplette Umgebung und auch eine Sichtweise der Welt. Seine Schöpfer wollten Computing für jeden Menschen beherrschbar, verständlich und interaktiv gestalten. Die Intention von Ausdrücken sollte sich denjenigen deutlich erschließen, die den Code lesen. Smalltalk ist aber auch eine Domain Specific Language für die Modellierung der Welt, in der Funktionen wie auch unabhängige und kommunizierende Objekte als Modellelemente ihren Platz haben. Sich mit Smalltalk zu beschäftigen ist überaus lohnenswert, denn viele Prinzipien sind in zahlreiche neuere Programmiersprachen eingeflossen. Der Grundgedanke hinter Smalltalk steht sicher jedem Programmierer gut: Computer für die Unterstützung des Menschen – was könnte man mehr wollen?

Hans Nikolaus Beck
befasst sich unter anderem mit Lernen durch Computerspiele und Serious Games beziehungsweise Gamification. Als langjähriger Entwickler hat er Erfahrung in diversen Programmiersprachen gesammelt.

  1. Kent Beck; Smalltalk Best Practice Patterns; Prentice Hall PTR; 1997

(rme [3])


URL dieses Artikels:
https://www.heise.de/-3999014

Links in diesem Artikel:
[1] http://pharo.org
[2] http://worrydream.com/EarlyHistoryOfSmalltalk/#p29
[3] mailto:rme@ix.de