Artikel

 
April 2010 | Artikel

Neue Dimensionen der Modularität

(Link zum Artikel: http://www.it-republik.de/jaxenter/artikel/3008)

Das Object-Teams-Projekt

Text: Stephan Herrmann
  • Teilen
  • kommentieren
  • empfehlen
  • Bookmark and Share
Das Object-Teams-Projekt [1] zieht mit seiner ausgereiften Codebasis bei Eclipse ein. Während die Möbelpacker noch die Pakete und Bündel hin- und herschieben, ist das ein guter Zeitpunkt, bei den neuen Nachbarn zu klingeln. Wir kommen nicht, um zu schnorren, sondern wir wollen unsere Hilfe anbieten, denn was wir in unseren Bündeln haben, könnte allen Nachbarn die Arbeit nachhaltig erleichtern.
Teil 1   Teil 2   Teil 3   

Eclipse ist in einer objektorientierten Sprache implementiert. Viele, die Eclipse benutzen, programmieren selbst in einer objektorientierten Sprache. 43 Jahre nach Erfindung der Objektorientierung sollte aber die Zwischenfrage erlaubt sein, ob die Objektorientierung wirklich alle in sie gesetzten Erwartungen erfüllt hat, und ob sie auch die Anforderungen des heutigen Tages erfüllt. Wer aufmerksam alle kleinen und größeren Konflikte bei der Aushandlung von Schnittstellen, bei der Planung von Wiederverwendung, bei der Weiterentwicklung bestehender Software betrachtet, mag ahnen, dass uns der konzeptionelle Rahmen von Klassen, Methoden, Importen und Vererbung bereits im Denken einschränkt. Wir könnten viel besser.

Der Object-Teams-Ansatz haucht den Objekten neuen Teamgeist ein und lässt sie spezifische Rollen in ihrem jeweiligen Team spielen. Dadurch, dass dasselbe Objekt in mehreren Teams unterschiedliche Rollen spielen kann, bringen Teams ein Konzept in die Programmierung, das aus Analyse und Entwurf schon lange nicht mehr wegzudenken ist: Teams implementieren Sichten, und die Bindung ihrer Rollen zu den jeweiligen Basisobjekten definiert, wie verschiedene Sichten zu einem Gesamtsystem komponiert werden.

Object Teams
Alle kennen die Frage: Wo in der Architektur soll die Geschäftslogik der einzelnen Anwendungsfälle implementiert werden? Die reine objektorientierte Lehre sagt eigentlich: Jedes Geschäftsobjekt soll den Teil des Verhaltens implementieren, der sich auf seinen internen Zustand bezieht. Wer eine Anwendung mit sehr vielen Anwendungsfällen nach dieser Lehre entwickelt hat, weiß, dass dadurch die Geschäftsobjekte aufgebläht werden – durch unzählige, teils spezialisierte Methoden, die irgendwie auf dem Zustand dieses Objekts operieren. Dabei wird es schier unmöglich, die Implementierung eines einzelnen Anwendungsfalls zu lokalisieren, da diese über viele Geschäftsobjekte verstreut ist. Da dieser Zustand für Wartung und Weiterentwicklung untragbar ist, geht der Trend eher dahin, die Geschäftsobjekte auf reine Daten-Records zu reduzieren, und das Verhalten nun durch diverse Entwurfsmuster angeleitet, in unabhängigen Modulen zu implementieren.

Leider verspielen wir mit der Record-basierten Lösung die zentralen Vorteile der Objektorientierung: Wo ist die natürliche Zerlegung, wie ein komplexer Anwendungsfall auf kleine Module verteilt wird, wenn die Geschäftsobjekte kein Verhalten implementieren? Wie kann Verhalten von einem Anwendungsfall für den nächsten wiederverwendet werden, ggf. mit Anpassungen? Natürlich lassen sich für all diese Fragen Entwurfsmuster und Konventionen finden, die sich den gewünschten Zielen annähern, aber die natürliche Eleganz, wie aus einer Problembeschreibung unmittelbar seine Zerlegung in Programmelemente folgt, ist niemals so realisiert worden, wie es uns die Lehrbücher der Objektorientierung weismachen.

Dabei ist die Antwort so geradlinig und gar nicht neu: Programmierung behandelt zwei Grunddimensionen: Daten und Verhalten. Bereits vor Erfindung der Objektorientierung gab es hinreichend Techniken, das Verhalten von Software zu strukturieren. Die Objektorientierung schlägt das Gegenteil vor: die Daten als Ausgangspunkt für die Modularisierung zu nehmen. Was wir brauchen, ist beides: jedes Programm als eine Matrix zu betrachten, dessen Spalten die Entitäten und dessen Zeilen die einzelnen Anwendungsfälle und Szenarien sind (Abb. 1).

Genau diese 2-Dimensionalität bietet Object Teams: Ein Team implementiert ein Stück Verhalten und zerlegt dieses auf mehrere Rollen, die im Team enthalten sind. Die Rollen werden an zugrunde liegende Basisklassen bzw. -objekte gebunden (playedBy) – ein Basisobjekt mit all seinen Rollen implementiert eine Entität. Eine Rolle ist also nichts anderes als der Schnitt einer „Verhaltensscheibe“ mit einer "Entitätssäule". Diese einfache Erweiterung der Struktur bietet folgende Vorteile:

  • Die Kernobjekte (in Abb. 1 mit dem Klassensymbol dargestellt) bleiben schlank.
  • Das Verhalten eines Objekts ist modular durch eine Klasse und eventuell mehrere daran gebundene Rollen beschrieben.
  • Das Verhalten eines Anwendungsfalls ist modular durch alle in einem Team enthaltenen Rollen beschrieben.
  • Die Integration der Anwendungsfälle zu einem System ist durch die playedBy-Beziehungen beschrieben.

Um diese Struktur mit Leben zu füllen, muss auch die Methodenebene betrachtet werden. Innerhalb eines Teams interagieren die Rollen durch ganz normale Methodenaufrufe. Entlang der playedBy-Beziehung jedoch werden Methodenaufrufe deklarativ beschrieben, wobei die beiden Aufrufrichtungen unterschieden werden:

  • Mit einer callout-Bindung sagt eine Rolle, dass an sie gerichtete Methodenaufrufe an das gebundene Basisobjekt weitergeleitet werden sollen. Dabei muss sich eine callout-Bindung nicht an die normalen Sichtbarkeitsregeln halten, da es sich um Methodenaufrufe innerhalb einer Entität handelt.
  • Mit einer callin-Bindung sagt eine Rolle, dass an das Basisobjekt gerichtete Aufrufe abgefangen werden sollen, und (zunächst) an die Rolle umgeleitet werden. Die Modifier before/after/replace bestimmen dabei die Art der Integration mit der jeweiligen Basismethode.

Beide Bindungsarten zusammen definieren eine Art von Vererbung zwischen Instanzen: Durch callout "erbt" die Rolle selektiv einige Methoden des Basisobjekts, durch callin kann sie selektiv Methoden des Basisobjekts "überschreiben". Allerdings sind diese Bindungen viel flexibler als klassenbasierte Vererbung: Das Hinzufügen einer neuen Verhaltensscheibe erfordert keine Änderungen irgendwo anders im Code, insbesondere geschieht das Hinzufügen einer Rolleninstanz zu einer Basisinstanz erst zur Laufzeit, muss also bei der Objekterzeugung noch gar nicht berücksichtigt werden. Dadurch werden mit einem Schlag alle Factories und teils auch Dependency Injection überflüssig.

Aufbauend auf diesem Modell wurde OT/J als Erweiterung von Java entwickelt. Der Schwerpunkt dieser Erweiterung lag darin, die neuen Konzepte bruchlos in die bestehende Sprache einzubinden. So lassen sich alle Java-Konzepte wie Vererbung, Generics usw. auch auf Teams und Rollen anwenden. Als Beispiel für die dabei entstehenden Synergien sei nur erwähnt, dass die Vererbung zwischen Teams ganz ungeahnte Möglichkeiten der Wiederverwendung eröffnet, da ein Subteam jede im Super-Team definierte Rolle nicht nur erbt, sondern auch überschreiben und erweitern kann.

Während die Konzepte von Object Teams die Objektorientierung radikal erweitern, ist diese Revolution doch sehr sanft, da alles bisher Gelernte nach wie vor gilt. Die Sprache OT/J orientiert sich gewissenhaft an den bestehenden Regeln von Java und ist mit existierenden Java-Bibliotheken 100 Prozent kompatibel.

Teil 1   Teil 2   Teil 3   

Anzeige

Kommentare


Anzeige

zurück zum Seitenanfang