| Das ATOS-Magazin 1/99 ATOS Programmierpraxis Moderne Zeiten # Objekttypen in informationellen Systemen Die im Folgenden gemachten Aussagen lassen sich im Allgemeinen auch auf beliebige technische Systeme übertragen. Hier soll die Konzentration aber verständlicherweise auf informationellen Systemen liegen, also auf Systemen, die Information darstellen, übertragen oder verarbeiten. Und damit wurden auch schon die drei Systemtypen, die in der Informationstechnik auftreten, genannt:
informationsdarstellende Systeme: | Systeme, die der Darstellung von Information dienen, nennt man Strukturpläne. Das Aufbaubild der GFA-Basic-Entwicklungsumgebung, das eingangs gezeigt wurde, ist ein solcher Strukturplan. Strukturpläne sind also statische Systeme, die nichts mit dem Ablauf der Zeit zu tun haben. Sie vermitteln lediglich Information, und zwar Information über andere Systeme. Deshalb sind Strukturpläne von großer Bedeutung, wenn es darum geht, andere Systeme zu entwerfen und zu beschreiben.
informationsübertragende Systeme: | Diese Systeme dienen der Übertragung von Information. Mal abgesehen davon, daß es im Falle der Telepathie vielleicht anders sein mag, wird zur Informationsübertragung immer ein verformbares Medium benötigt. Bspw. ist ein Blatt Papier durch Bekritzeln mit einem Bleistift "verformbar". Auch die Luft läßt sich durch Druckänderungen (Schallwellen) verformen, so daß sie sich als Medium eignet. Ein Medium kann zur Informationsübertragung genutzt werden, in dem man sich verschiedene mögliche Formen herausgreift und diesen eine Bedeutung zuordnet. Es muß also eine Sprache vereinbart werden. Die Formen, die durch die Sprache eine Bedeutung erhalten, nennt man Werte. In der Tat haben sie nur für jemanden, der die Sprache kennt, auch einen Wert, für alle anderen sind diese Formen wertlos. Zur Informationsübertragung muß man also letztendlich Formen übertragen. Wichtig ist, daß man zwischen zwei grundverschiedenen Übertragungsarten unterscheidet:
örtliche Übertragung: | Ein Medium, das Information über eine örtliche Distanz überträgt, nennt man (wie schon angesprochen) Kanal. Bekannte Medien diesen Typs wären Fernsehen, Rundfunk oder Telefon.
zeitliche Übertragung: | Die zeitliche Übertragung findet hingegen in Speichern statt. Beispiele wären etwa ein Geschichtsbuch oder das RAM eines Rechners.
informationsverarbeitende Systeme: | Systeme diesen Typs verarbeiten Information. Man könnte zum Beispiel die Information "Steffi hat am 19. August Geburtstag" mit seinem Wissen über Astrologie derart "verarbeiten", daß man am Ende weiß, daß Steffis Sternzeichen der Löwe ist. Informationsverarbeitung bringt keinen faktischen Wissenszuwachs. Das Wissen wird aber in eine neue Form gebracht, mit der man dann vielleicht besser umzugehen weiß. Diese neue Form dann ebenfalls (sozusagen auswendig) zu kennen, bringt also schon einen Wissenszuwachs, nur eben keinen faktischen. Maschinen verarbeiten natürlich keine Informationen, sondern nur Formen. Die Formverarbeitungsprozesse lassen sich dabei aber als Informationsverarbeitungsprozesse interpretieren. Wenn z.B. ein Taschenrechner nur durch Hin- und Herbewegen von Ladungen in seinen elektrischen Bauteilen und durch Umdrehen von Kristallen in seinem Display uns "mitteilt", daß die Quadratwurzel aus 16 vier ist, dann weiß er nicht wirklich, wie man Wurzeln zieht. Aber sein Konstrukteur wußte, wie man Formen maschinell so verarbeiten kann, daß als Bedeutung der Ausgangsform die Quadratwurzel der Bedeutung der Eingangsform herauskommt.
Der Grund, weshalb hier so viel über die verschiedenen Systemtypen geredet wird ist, daß auch die Komponenten der Systeme von diesen Typen sind. Rufen Sie sich noch einmal das Aufbaubild in Erinnerung. Passive Komponenten (die rund gezeichneten) sind nämlich vom Typ "informationsübertagend", wohingegen die aktiven Komponenten (in Anlehnung an eine Blackbox rechteckig gezeichnet) vom Typ "informationsverarbeitend" sind. Schrittweise Verfeinerung Solche Komponenten können dann wie schon angedeutet ihrerseits als Systeme aufgefaßt werden und abermals in Komponenten zerlegt werden. Dieses Spiel geht so lange, bis man auf die elementaren Komponenten stößt, also die Komponenten, die sich nicht weiter verfeinern lassen. Diese Komponenten sind demnach die Grundbausteine des Systems, die hier als gegeben vorausgesetzt werden. Bei programmierten Systemen werden diese Komponenten durch die Programmiersprache festgelegt. Man kann z.B. `WORD`-Variablen anlegen und benutzen, ohne deren inneren Aufbau näher betrachten zu müssen. Alle in einem System auftauchenden Komponenten sind also Objekte jeweils eines der folgenden Typen: Speicherobjekte Kanalobjekte Verarbeitungsobjekte, im Folgenden nochmals unterteilt in: Operationsobjekte Steuerobjekte Die Operationsobjekte Eine Operation ist ein abgeschlossener Vorgang, bei dem der Vorgang an sich nicht von Belang ist. Wichtig sind bei einer Operation nur der Zustand vor und nach der Operation, die sog. pre- und post-Zustände (Blinddarm ist drin/ Blinddarm ist draußen). Demnach sind Operationsobjekte solche Objekte, die den Zustand von Speichern auf Kommando verändern können und melden, wann die Veränderung abgeschlossen ist. Ein Listensortierer wäre ein solches, typisches Objekt, aber auch ein "Inkrementierer", der eine Zahl erhöht. Operationsobjekte bearbeiten also ergebnisorientierte Anweisungen. Ein Operationsobjekt arbeitet dabei nach außen hin bei jedem Aufruf gleich. Seine Benutzung führt also (bei gleichen Eingangswerten) immer zum gleichen Ergebnis - egal zu welchem Zeitpunkt es aufgerufen wird. Die Steuerobjekte Steuerobjekte sind Objekte, die bestimmen, wann und unter welchen Bedingungen welche Operationen zu tun sind. So verfügt der Listensortierer intern beispielsweise über ein Steuerobjekt, welches den Ablauf des Sortierens kennt und steuert. Daneben gibt es ein Operationsobjekt, das Listenelemente vertauschen kann. Das Steuerobjekt bestimmt also, wann welche Elemente vertauscht werden sollen, läßt die Vertauschung selber aber vom Operationsobjekt durchführen. Ein Steuerobjekt wird also immer durch einen Ablauf beschrieben. Eine GFA-Basic-Prozedur ist z.B. eine Beschreibung für ein Steuerobjekt. Ein Steuerobjekt muß nicht immer den Ablauf einer ergebnisorientierten Operation steuern, große Bedeutung haben vor allem die Steuerobjekte, die die Bearbeitung prozeßorientierter Anweisungen steuern. Prozeßorientierte Anweisungen sind solche, bei denen man nicht nur auf das Ergebnis der Abarbeitung warten möchte, um mit dem Ergebnis weiterzuarbeiten (s. Operationsobjekte), sondern durch die ein Prozeß ausgelöst werden soll, an dem man teilnehmen möchte. Beispiele wären "Spiele ein Musikstück!", "Öffne ein Editorfenster!" oder "Schalte den Videorekorder auf >>Play<<!". Die Steuerungsvorgänge mehrerer, gleichzeitig vorhandender Steuerobjekte müssen nun nämlich nebenläufig ablaufen, was bei nur einem zur Verfügung stehenden Abwickler ein Problem hervorbringt. In diesem Fall muß man den Abwickler dann im Multiplex betreiben, also hin- und wieder zwischen den verschiedenen Aufgaben (engl. "Tasks") umschalten (Multitasking). Dieses Umschalten wird bei programmierten Systemen überlicherweise von einem Betriebssystem übernommen, so daß man dem Betriebssystem nur zu sagen braucht, welche prozeßorientierten Steuerobjekte anzulegen sind, welche Abläufe also nebenläufig abgearbeitet werden sollen. Alle verschiedenden Typen (Kanal-, Speicher-, Steuer- und Operationsobjekte) unterscheiden sich also in grundlegenden Eigenschaften. Deshalb sollten die Objekte dieser Typen auch mit verschiedenen Strukturierungen beschrieben werden (Sie erinnern sich, daß die Objektorientierung nur eine besondere Strukturierung des Programms war). Normalerweise greift man bei objektorientierten Programmiersprachen auf eine einzige Strukturierung zurück, mit der sich alle Objekttypen beschreiben lassen. Dabei verwischt man als Programmierer aber natürlich gerne die Grenzen und kann am Ende gar nicht mehr so leicht feststellen, von welchem Typ denn nun ein bestimmtes Objekt wirklich ist. Versucht man als Beispiel eine Parallele zum strukturierten Programmieren zu ziehen, so wäre diese Begebenheit vielleicht damit vergleichbar, daß es dann dort ebenfalls nur einen Strukturtyp gäbe, der unter anderem Schleifen und Fallunterscheidungen zugleich abdeckt. Statt der Schleifenvielfalt von `WHILE`/`WEND`, `REPEAT`/`UNTIL` oder `FOR`/`NEXT` und den Entscheidungstypen `IF`/`ELSE`/`ENDIF`, `SELECT`/`CASE` oder `ON x GOSUB` gäbe es dann vielleicht nur noch `WHILE anzahl bedingung`/`WEND`. Statt `IF bedingung` schreibt man dann `WHILE 1 bedingung`, und statt `FOR i=1 to 10` schreibt man `WHILE 10 TRUE` usw. Denkbar wäre ein solches Konstrukt also. Eine Verallgemeinerung bringt hier aber - wie sofort ersichtlich ist - den Nachteil mit sich, daß die Verständlichkeit stark darunter leidet. Genauso leidet beim objektorientierten Programmieren die Verständlichkeit, wenn man Objekten nicht ihren Typ ansieht. Wichtig ist also nur, daß der Typ entsprechend zu erkennen ist. Ob das durch die Syntax der Programmiersprache bereits ermöglicht wird oder ob man es irgendwie sonst dokumentieren muß, ist demnach nicht so wichtig. Im zweiten Fall wird es nur ganz gerne nicht gemacht. Realisierung von Objekten dieser Typen Im nächstem Schritt müßte nun eigentlich ermittelt werden, wie sich Objekte der vier genannten Typen beschreiben und zu einem System verschalten lassen. Mit Unterstützung der OT/OB-Lib lassen sich aber zunächst nur Speicherobjekte anlegen. Wie das funktioniert, wird in den folgenden Abschnitten genauer dargelegt. Nach den Überlegungen, daß die "Operandenorientierung" (s.o.) einen sinnvollen Ansatz zum Entwurf liefert, wird das erste, was man in seinem Programm definiert, eine Reihe von Speicherobjekttypen sein. Für die eingangs angesprochene Bildverarbeitungssoftware wurden z.B. Speicherobjekte vom Typ `Bild` benötigt. Auf die drei anderen Objekttypen soll nun noch kurz eingegangen werden, um zu erläutern, daß auch sie - aufbauend auf den Speicherobjekten - in GFA-Basic realisert werden können. Diese Abhandlung ist allerdings sehr knapp. Kanalobjekte können im Regelfall sehr leicht auch durch Speicherobjekte realisiert werden. Zur Übertragung legt dazu der Absender ein Speicherobjekt des gewünschten Typs an und übergibt es an den Empfänger. Zum Beschreiben von Operationsobjekten reicht die GFA-Syntax bereits aus, da Operationsobjekte im Prinzip einfach durch Prozeduren beschrieben werden können, die nicht auf globale Variablen zugreifen dürfen. Ergebnisorientierte Steuerobjekte stellen sich auf die gleiche Weise dar, denn die Prozedur eines Operationsobjektes ist nichts anderes, als ein ergebnisorientiertes Steuerobjekt innerhalb des Operationsobjektes, welches die Abarbeitung der Operation steuert. Auch die prozeßorientierten Steuerobjekte sind in GFA-Basic ohne weiteres beschreibbar, leider nur im Form eines einzigen Hauptprogramms, wobei keine Nebenläufigkeiten beschrieben werden können. Steht man vor dem Dilemma, mehrere Steuerobjekte anlegen zu müssen (weil der Benutzer vielleicht auch mal ein zweites Editorfenster öffnen möchte), muß man einige Umwege machen. Manchmal empfiehlt es sich, dazu auf mehrere, einzelne Programme auszuweichen. Eine andere Möglichkeit ist, sich die Bearbeitungszustände der einzelnen Steuerobjekte in Speicherobjekten zu merken und für diese Speicherobjekte ferner eine Operation "bearbeite ein Ereignis" zu definieren. Das Hauptprogramm baut man dann als eine Hauptschleife (die idle-Loop), in der auf ein Ereignis gewartet wird. Ein eintreffendes Ereignis wird nacheinander den relevanten "Steuerspeicherobjekten" durch Aufruf der jeweiligen Operation "bearbeite ein Ereignis" gemeldet, worauf diese eine Operation ausführen, sich in ihren Speicherobjekten den neuen Bearbeitungszustand vermerken, und anschließend wieder ins Hauptprogramm zurückkehren. Das Hauptprogramm wartet danach auf das nächste Ereignis und das Spiel beginnt von vorne. In Wirklichkeit sind dann also die Steuerobjekte als Kombination aus Speicher- und Operationsobjekt realisiert. Wichtig war in diesem Abschnitt, daß Ihnen die Unterschiede zwischen den vier Objekttypen bekannt sind, und daß Sie wissen, daß im Folgenden nur über einen dieser Typen gesprochen wird: die Speicherobjekte. Das Objekt und der Objekttyp im Sinne des Programmierers