3. Umgang mit Eiffel

Gerade Eiffel unterstützt den Ansatz, Software aus wiederverwendbaren Komponenten zusammenzusetzen. Bertrand Meyer schreibt in einem Artikel über die Erfahrungen mit der Eiffel-Bibliothek ([Meyer 90]):

"A common problem in the component-based approach to software development is determining how to enable client programmers to find out about available components and retrieve them easily. Obviously, the seriousness of this problem grows with the number of components."

Bei der Implementation in Eiffel hat der Programmierer das Bedürfnis, Klassen in Bibliotheken (die zum Compiler mitgelieferten oder anderen) zu finden, die er für seine Zwecke benutzen kann.

Solange er mit dem Aufbau der Bibliotheken und den Funktionen der einzelnen Klassen nicht vertraut ist (und bei dem Umfang der meisten Bibliotheken ist dies eine sehr lange Zeit, wenn nicht immer der Fall), muß er sich auf der Suche nach einer passenden Klasse die Beschreibung und das Interface vieler Klassen ansehen, bis er eine passende gefunden hat.

Der Programmierer kann natürlich alle Klassen mit einem Texteditor o.ä. ansehen (Eiffel-Bibliotheken werden üblicherweise mit Quelltext ausgeliefert), bis er fündig wird. Die Beziehungen der Klassen untereinander müssen aber von ihm selbst (geistig) hergestellt werden. Hier ist eine Werkzeugunterstützung unbedingt nötig, sobald mit größeren Projekten gearbeitet wird.

Das gleiche Problem, die Struktur und den Aufbau der Bibliotheken zu verstehen, taucht auch bei der Einarbeitung in Programme anderer Programmierer auf. Konnte man bei Bibliotheken dem Problem z.T. noch mit einer guten Dokumentation beikommen, so ist hier jedoch oft keinerlei Dokumentation vorhanden und der Autor für Fragen oft nicht zu erreichen. Eine gute Werkzeugunterstützung ist hier fast lebenswichtig.

Einige Beispiele für Fragen eines Programmierers:

    Wo finde ich eine Behälterklasse für ca. 50 Objekte, auf die ich wahlfrei und schnell zugreifen kann ?

    Gibt es eine Behälterklasse, die ca. 20.000 "Dauerauftrag"-Objekte platzsparend speichert ?

    Welche Interaktionstypen für eine 1-aus-n Selektion gibt es ?

    Gibt es in unserem Projekt noch Klassen, die von der Klasse SPEICHERBAR erben ?

    Ich möchte Merkmalsnamen einheitlich vergeben. Gibt es schon andere Klassen, die den Merkmalsnamen "Index" verwenden ?

Dies sind nur einige Beispiele für Arbeitssituationen, in denen ein Programmierer eine Werkzeugunterstützug zum Betrachten von Quelltexten braucht, die ihm auch hilft die Zusammenarbeit der einzelnen Komponenten zu verstehen. Um zu zeigen, wie bisher mit diesen Fragen umgegangen wird, folgen zwei Szenarien, die die Arbeit mit den bisherigen Hilfsmitteln exemplarisch verdeutlichen, und eine Vision, wie es sein könnte.

3.1.   Eine Beispiel-Situation

Der Programmier soll die Klasse UEBERWEISUNGSAUFTRAG anpassen, damit sie in einer Behälter­klasse der neuen ConlibEiffel-Bibliothek gespeichert werden kann.

3.1.1.         Szenario 1 : Bewältigen der Aufgabe mit traditionellen Eiffel-Werkzeugen

Da der Programmierer die Bibliothek ConlibEiffel noch nicht kennt und sich die beigefügte Dokumentation nur auf die C++ Version bezieht, sucht er nach einem Beispiel, das die Verwendung der Bibliothek demonstriert.

Im Verzeichnis /usr/src/conlib findet er die Datei testlib.e. Der Programmierer schaut sich das Beispiel mit dem Unix-Befehl "short testlib" an. Er kann an der Ausgabe erkennen, daß die Klasse Testlib heißt und eine Creation-Feature make und drei andere parameterlose Routinen InitTest, InsertObjs und ListObjs hat.

Da die Klasse von keiner anderen erbt, schaut er sich nun mit dem Unix-Befehl "more" die Datei an. Im Beispiel werden INTEGER-Objekte in eine Liste (SORTED_LIST) eingefügt und danach der Reihe nach wieder ausgegeben. Ein Testlauf des Beispiels zeigt, daß es einwandfrei funktioniert.

Da offenbar keine Modifikationen an der Klasse INTEGER nötig waren, ändert er das Beispiel, so daß nun Überweisungsaufträge in die Liste eingefügt werden. Er ist ein wenig verwundert, daß er keine Möglichkeit sieht, anzugeben, wie die Überweisungsaufträge sortiert werden sollen.

Ein Blick auf die Ausgabe von "short SORTED_LIST" zeigt, daß SORTED_LIST das Merkmal AddAt redefiniert und sonst keine Änderungen an der geerbten Klasse LIST vornimmt. Da dieses Feature im Beispiel aber nicht verwendet wird, kann der Programmierer mit dieser Information nichts weiter anfangen. Da die Ausgabe von "flat SORTED_LIST | short" ca. 15 Bildschirmseiten lang ist, entscheidet sich der Programmierer für einen Testlauf des eben modifizierten Testprogramms.

Vom Compiler erhält er die Fehlermeldung, daß das Einfügen von UEBERWEISUNGS­AUFTRAG mit Insert nicht typverträglich ist. Der Programmierer schaut sich mit "flat SORTED_LIST | short | more" nun erneut die volle Klassenschnittstelle an und sucht nach dem Insert Feature. Nachdem er es gefunden hat, stellt er fest, daß nur Objekte vom Typ COMPARABLE eingefügt werden dürfen.

Ein "short COMPARABLE" zeigt ihm, daß die Klasse aufgeschoben (deferred) ist. Aus den Kommentaren ist ersichtlich, daß mindestens der Operator < von Unterklassen implementiert werden muß.

Mit diesem Wissen ausgerüstet, modifiziert er seine Klasse UEBERWEISUNGSAUFTRAG derart, daß sie nun zusätzlich von COMPARABLE erbt und den Operator < implementiert (abhängig von der Kontonummer des Absenders - oder der laufenden Nummer des Überweisungs­auftrags).

Das Testbeispiel funktioniert nun auch mit Überweisungsaufträgen, und der Programmierer gibt die modifizierte Klasse für die restlichen Entwickler frei.

3.1.2.         Szenario 2: Bewältigen der Aufgabe mit ISE Eiffel 3[4]

Da der Programmierer die Bibliothek ConlibEiffel noch nicht kennt und sich die beigefügte Dokumentation nur auf die C++ Version bezieht, sucht er nach einem Beispiel, das die Verwendung der Bibliothek demonstriert.

Im Verzeichnis /usr/src/conlib findet er die Datei testlib.e, die er in das Class Tool lädt. Im Beispiel werden INTEGER-Objekte in eine Liste (SORTED_LIST) eingefügt und danach der Reihe nach wieder ausgegeben. Ein Testlauf des Beispiels zeigt, daß es einwandfrei funktioniert.

Da offenbar keine Modifikationen an der Klasse INTEGER nötig waren, ändert er das Beispiel, so daß nun Überweisungsaufträge in die Liste eingefügt werden. Er ist ein wenig verwundert, daß er keine Möglichkeit sieht, anzugeben, wie die Überweisungsaufträge sortiert werden sollen.

Er stellt den Darstellungsmodus auf "clickable" um, klickt mit der rechten Maustaste auf den Klassennamen SORTED_LIST und zieht ihn auf das Class Tool-Icon links oben im Fenster. Er sieht nun den Klassentext der Klasse SORTED_LIST. Da er an den Details der Implementie­rung nicht interessiert ist, schaltet er mit einem Klick auf das Short-Icon am unteren Fenster­rand auf die Short-Darstellung um. Er sieht, daß das Feature AddAt redefiniert wird (das im Beispiel aber nicht verwendet wird) und sonst keine Änderungen an der geerbten Klasse LIST vorgenommen werden.

Mit einem Klick auf das Flatshort-Icon am unteren Fensterrand schaltet er auf die Flatshort-Form um (was ihm Gelegenheit gibt, seinen Kaffee auszutrinken). Danach hat er eine ca. 15 Bildschirmseiten lange Klassenschnittstelle im Editor. Da er nicht genau weiß, wonach er sucht, entscheidet sich der Programmierer für einen Testlauf des eben modifizierten Test­programms.

Vom Compiler erhält er die Fehlermeldung, daß das Einfügen von UEBERWEISUNGS­AUFTRAG mit Insert nicht typverträglich ist. Der Programmierer sucht nun nach dem Insert Feature. Nachdem er es gefunden hat, stellt er fest, daß nur Objekte vom Typ COMPARABLE eingefügt werden dürfen.

Er stellt den Darstellungsmodus auf "clickable" um, klickt mit der rechten Maustaste auf den Klassennamen COMPARABLE und zieht ihn auf das Class Tool-Icon links oben im Fenster. Im Class Tool hat er nun die Klasse COMPARABLE in Flatshort-Form vor sich. Nachdem er die Darstellung auf Short-Form umgeschaltet hat, sieht er, daß die Klasse aufgeschoben (deferred) ist. Aus dem Kommentaren ist ersichtlich, daß mindestens der Operator < von Unterklassen implementiert werden muß.

Mit diesem Wissen ausgerüstet, modifiziert er seine Klasse UEBERWEISUNGSAUFTRAG derart, daß sie nun zusätzlich von COMPARABLE erbt und den Operator < implementiert (abhängig von der Kontonummer des Absenders - oder der laufenden Nummer des Überweisungs­auftrags).

Das Testbeispiel funktioniert nun auch mit Überweisungsaufträgen.

Mit einem Klick auf das Ancestors-Icon am unteren Bildschirmrand sieht er sich die neue Vererbungshierarchie (Oberklassen) an. Ihm fällt auf, daß die Klasse UEBERWEISUNGS­AUFTRAG noch von SPEICHERBAR erbt. Nach dem Durchsehen des Klassentextes stellt er fest, daß dies nur für die alte Behälterbibliothek nötig war, und entfernt SPEICHERBAR aus der Liste der Oberklassen.

Er compiliert die Klasse UEBERWEISUNGSAUFTRAG erneut, und der Programmierer gibt die modifizierte Klasse für die restlichen Entwickler frei.

3.1.3.         Bewertung der Szenarien

Das zweite Szenario macht ansatzweise deutlich, wie ein Browser dem Programmierer helfen kann, seine Probleme zu lösen. Insoweit ist der Einsatz von ISE Eiffel 3 sicher ein Schritt in die richtige Richtung.

Bei einem guten Browser wird der Programmierer oft auch auf Dinge stoßen, nach denen er nicht explizit sucht, die aber für seine Arbeit doch hilfreich sind. Im Beispiel wird bei der Arbeit mit traditionellen Werkzeugen beispielsweise überhaupt nicht bemerkt, daß eine Klasse über­flüssig geworden ist. Solange die Informationsbeschaffung schwierig und langwierig ist, wird sich der Programmierer auch kaum bemühen, solchen Details nachzugehen.

Es gibt dabei jedoch auch Probleme beim Einsatz von ISE Eiffel 3, die nur zum Teil aus dem Szenario zu erkennen sind. Dies beginnt mit der sehr gewöhnungsbedürftigen Oberfläche, die bei mir zu keinem Zeitpunkt das Gefühl von direkter Manipulation aufkommen ließ. Zum einen liegt dies an der Handhabung, die nicht dem Styleguide der jeweiligen Plattform entspricht. Zum anderen treten aber auch oft störende Wartezeiten bei der Arbeit mit größeren Informationsmengen auf, da die monolithische Umgebung kaum skalierbar ist.

Auch geht die Umsetzung der Darstellungsmethoden auf eine graphische Oberfläche nicht weit genug. War es bei den traditionellen Werkzeugen short und flat noch sinnvoll, immer die Schnittstelle der gesamten Klasse anzuzeigen, so wird man unter der graphischen Oberfläche z.T. von der Informationsmenge erschlagen und benötigt eine weitere Filterbarkeit der Informationen.

Im Szenario nicht sichtbar ist auch die explizite Beachtung, die der Programmierer bei ISE Eiffel 3 der Aktualität der angezeigten Informationen widmen muß. Viele Darstellungen sind nur dann korrekt, wenn sich der Quelltext in einer vorkompilierten Form befindet (melted). Auch werden offene Fenster nicht automatisch aktualisiert, wenn sich der Quelltext geändert hat.

3.1.4.         Vision: Bewältigen der Aufgabe mit einem neuen Eiffel-Browser

Da der Programmierer die Bibliothek ConlibEiffel noch nicht kennt und sich die beigefügte Dokumentation nur auf die C++ Version bezieht, sucht er nach einem Beispiel, das die Verwendung der Bibliothek demonstriert.

Im Unterprojekt ConlibEiffel sieht er die Datei testlib.e, die er mit einem Doppelklick in den Editor lädt. Im Beispiel werden INTEGER-Objekte in eine Liste (SORTED_LIST) eingefügt und danach der Reihe nach wieder ausgegeben. Ein Testlauf des Beispiels zeigt, daß es einwandfrei funktioniert.

Da offenbar keine Modifikationen an der Klasse INTEGER nötig waren, ändert er das Beispiel, so daß nun Überweisungsaufträge in die Liste eingefügt werden. Er ist ein wenig verwundert, daß er keine Möglichkeit sieht, anzugeben, wie die Überweisungsaufträge sortiert werden sollen.

Er öffnet den Symbol-Browser und lädt SORTED_LIST mit einem Doppelklick auf den Klassennamen in den Editor. Am rechten Rand sieht er, daß nur das Feature AddAt in dieser Klasse definiert wird (das im Beispiel aber nicht verwendet wird).

Er wählt den Menüpunkt "Show SORTED_LIST in Hierarchie" aus und sieht, daß SORTED_LIST nur von LIST erbt. Ihm fällt auf, daß im gleichen Projekt andere zu speichernde Klassen von COMPARABLE erben. Mit einem Doppelklick lädt er LIST in den Editor.

In der Feature-Liste am rechten Rand des Editors sieht er die ca. 20 in dieser Klasse definierten Features. Da er nicht genau weiß, wonach er sucht, entscheidet sich der Programmierer für einen Testlauf des eben modifizierten Testprogramms.

Vom Compiler erhält er die Fehlermeldung, daß das Einfügen von UEBERWEISUNGS­AUFTRAG mit Insert nicht typverträglich ist. Im Editor klickt der Programmierer nun rechts in der Liste auf Insert, und der Editor springt auf die Implementation von Insert. Hier sieht er, daß nur Objekte vom Typ COMPARABLE eingefügt werden dürfen.

Im Symbol-Browser klickt er nun auf COMPARABLE, um es in den Editor zu laden. Dort sieht er, daß die Klasse aufgeschoben (deferred) ist. Aus dem Kommentaren ist ersichtlich, daß mindestens der Operator < von Unterklassen implementiert werden muß.

Mit diesem Wissen ausgerüstet, modifiziert er seine Klasse UEBERWEISUNGSAUFTRAG derart, daß sie nun zusätzlich von COMPARABLE erbt und den Operator < implementiert (abhängig von der Kontonummer des Absenders - oder der laufenden Nummer des Überweisungs­auftrags).

Nachdem er die Änderungen im Editor gespeichert hat, ändert sich die Darstellung im Hierarchie-Browser (noch bevor er den Compiler gestartet hat). Ihm fällt auf, daß die Klasse UEBERWEISUNGSAUFTRAG noch von SPEICHERBAR erbt. Nach dem Durchsehen des Klassen­textes stellt er fest, daß dies nur für die alte Behälterbibliothek nötig war, und entfernt SPEICHERBAR aus der Liste der Oberklassen.

Da SPEICHERBAR in der nächsten Woche überarbeitet werden sollte, schickt er eine EMail an den Rest des Entwicklerteams mit der Anregung, diese ohnehin recht problematische Klasse völlig aus dem Projekt zu entfernen.

Er compiliert das Testbeispiel nun. Es funktioniert nun auch mit Überweisungsaufträgen, und der Programmierer gibt die modifizierte Klasse für die restlichen Entwickler frei.

 

 


Last updated: 24. Aug 2005
Page maintained by Jan Willamowius
Impressum · Datenschutz
 
English: Home | Linux | Perl | Java | Eiffel | Books | Music | Jan Willamowius | Updates | Site Map
Deutsch: Home | Badminton | ISBN-Suche | Musik-Suche | Rezepte | Jan Willamowius