Componentware / Wiederverwendung auf allen Ebenen

Softwaremontage mit Frameworks und Komponenten

04.10.1996

Ziel der Wiederverwendung ist es, den "Anwendungsstau" zu beseitigen. Software soll weitgehend durch Wiederverwendung großer Softwarebausteine oder durch die Anpassung vorgefertigter Architekturen und architekturspezifischer Bausteine neu- und weiterentwickelt werden. Dabei sollen sich die Entwicklungs- und Wartungskosten spürbar reduzieren, die Lieferzeiten verkürzen und die Qualität deutlich verbessern. Die Wiederverwendung soll außerdem die Ablösung von "Uraltanwendungen" durch die Einbindung in Frameworks ermöglichen.

Die Erkenntnis, daß Software-Entwicklung kein Kunsthandwerk, sondern typische Ingenieurarbeit ist, brachte nicht nur CASE, sondern auch die Anfänge der Softwarewiederverwendung hervor. Das der Mathematik entlehnte Konzept der funktionellen Abstraktion führte zur ersten Generation wiederverwendbarer Bausteine: Makros, Funktionen und Prozeduren.

Obwohl die Grundlagen der Objektorientierung wie der Datenabstraktion bereits Ende der sechziger Jahre entwickelt wurden, entfernen die Software-Ingenieure die Stolpersteine für eine erfolgreiche Wiederverwendung erst 20 Jahre später: die programmtechnische Trennung zwischen dem Wert oder dem Zustand eines Objektes und den Operationen mit diesem Objekt. Die Codeanalyse konventionell programmierter Software zeigt beispielsweise, daß Operationen für Geschäftsobjekte wie Konto, Kunde oder Rechnung über verschiedene Programmteile verstreut sind. Dabei können gleiche Operationen in unterschiedlichen Programmteilen durchaus wiederholt und dabei unterschiedlich programmiert sein.

Die Objektorientierung lehrt, daß nur die komplette Wiederverwendung von Objekten mit ihren Operationen Sinn macht. Das Konzept dafür ist die Datenabstraktion.

Das Verhalten der Objekte, ihre Zustands- beziehungsweise Werteänderungen, ist nach diesem Konzept ausschließlich durch die objektspezifischen Operationen bestimmt. Typische Operationen, die Methoden des Objektes genannt werden, sind der Konstruktor zur Erzeugung oder der Destruktor zur Vernichtung von Objekten sowie Operationen zur Wertänderung oder Wertselektion. Die Methoden rufen sich nicht wie Prozeduren gegenseitig auf, statt dessen senden Objekte an andere Nachrichten.

Es ist einer der Vorteile objektorientierter Programmiersprachen, daß sie mit dem Konzept der Objektklassen Ausdrucksmittel bieten, um Objekte als Ganzes wiederverwenden zu können. Bei Wiederverwendung wird aber häufig nicht das Originalobjekt benötigt, sondern eine Spezialisierung. Soll etwa die wiederverwendete Klasse "Kunde" andere Eigenschaften in Form von neuen, anderen oder zusätzlichen Attributen erhalten und soll sie ein anderes Verhalten in Form von anderen oder neuen Operationen bekommen oder müssen die Kunden in "Großkunden" und "Detailkunden" unterschieden werden, bedarf es zusätzlicher Mechanismen.

Das für solche Spezialisierungen gebräuchlichste Konzept ist die Vererbung. Sie läßt sich dafür nutzen, Eigenschaften von der wiederverwendeten Superklasse unverändert an spezialisierte, sogenannte Subklassen, wie "Großkunde" und "Detailkunde" zu vererben.

Andere Attribute und Operationen hingegen lassen sich in den Subklassen mit anderen Eigenschaften überschreiben. Die Compiler objektorientierter Sprachen sorgen dafür, daß zur Laufzeit jedes Objekt der jeweiligen Subklasse mit den "richtigen" ererbten oder überschriebenen Operationen bearbeitet wird.

Das Konzept, nach dem gleichnamige Attribute oder Operationen von Subklassen andere Eigenschaften oder anderes Verhalten als die der Superklasse haben dürfen, wird als Polymorphismus bezeichnet. Die Technik, die das zur Laufzeit ermöglicht, nennt sich dynamisches Binden. Delegation und Komposition ermöglichen zum Beispiel eine strukturelle Verknüpfung zwischen Objekten zur Programmlaufzeit.

Es gibt heute einen etablierten und wachsenden Markt für Klassenbibliotheken. Basisobjekte für grafische Benutzeroberflächen oder für Strings, Arrays, Datum, Zeit oder sogenannte Container-Klassen wie Warteschlangen, Keller, Listen und Bäume sind typische Produkte dieses Marktes. Dennoch eignen sich die Objektklassen nicht zur massenhaften Wiederverwendung. Allerdings erweist sich die Objektorientierung als Basistechnologie zum Beispiel für Komponentensoftware.

Komponenten sind speziell für die Wiederverwendung entwickelte Softwarebausteine. Jede Komponente bietet eine Gruppe von öffentlichen Diensten zur Wiederverwendung an, um technische Objekte oder Geschäftsobjekte zu manipulieren. Beispiele für technische Objekte sind Zeit, Zugriffsrechte, Transaktionen, E- Mail und Drucker.

Entsprechend der Schichtenarchitektur von Anwendungssoftware werden zudem horizontale und vertikale Komponenten unterschieden. Zu den ersteren gehören die Dienste zur Wiederverwendung von Objekten der grafischen Benutzeroberfläche und die Komponenten von Client-Server-Middleware, die der Kooperation zwischen Client- und Server-Anwendungsteilen dienen. Als vertikale Komponenten gelten die Geschäftsobjekte wie Kunden, Rechnungen und Konten.

Horizontale und vertikale Komponenten werden für die Black-box- Wiederverwendung, ohne Auslieferung des implementierenden Quelltextes, ebenso aber auch zur White-box-Wiederverwendung angeboten. Aus den einzelnen Komponenten wird jedoch nur eine Anwendung, wenn ein spezifischer, steuernder Rahmen bereitsteht, der die Komponenten zu einem kooperierenden System verbindet. Eine zentrale Rolle in Componentware-Systemen spielt die Middleware, die zur Laufzeit die netzwerkweite Kooperation zwischen den Komponenten ermöglicht.

Die wohl bekannteste, hersteller- und sprachneutrale Spezifikation für objektorientierte Componentware ist die Common Object Request Broker Architecture (Corba). Die Interface Definition Language (IDL) von Corba dient dazu, die Eigenschaften und das Verhalten von Objekten in Form einer objektorientierten Interface-Definition zu spezifizieren. Sie unterstützt als objektorientierte Sprache die Vererbung zwischen Komponenten.

Broker sind effizienter als CICS oder APPC

Der Corba-Ansatz definiert sogenannte Sprachbindungen für die semantisch korrekte Hin- und Rückübertragung zwischen IDL und den Programmiersprachen. Darauf aufbauend, haben Anbieter von Corba- Implementierungen Sprachkonverter zwischen IDL und verschiedenen Programmiersprachen wie C, C++ und Object Cobol entwickelt.

Heute gibt es eine breite Palette von ORB-Implementierungen, wobei die Entscheidung für ein ORB-Produkt noch mit der Bindung an einen Hersteller verbunden ist. Den Brokern aber ist gemein, daß sie die Entwickler wesentlich effizienter als klassische Middleware- Produkte wie CICS oder APPC bei der Erstellung objektorientierter Anwendungen unterstützen. Das betrifft insbesondere die Objekt- Objekt-Kommunikation und -Kooperation.

Dennoch kann ein erheblicher Anpassungsaufwand erforderlich sein, wenn Anwendungen aus unabhängig voneinander entwickelten Komponenten erstellt werden. Soll etwa ein Objekt einer Komponente Nachrichten mit einem Objekts einer anderen Komponente austauschen, müßten Eigenschaften und Verhalten des kooperierenden Objektes mit den "Erwartungen" des nutzenden Objekts übereinstimmen. Außerdem dürften die Objekte nicht zu spezifisch für eine Anwendung sein.

Diesen Ansatz verfolgen sogenannte Pattern, Lösungsvorschriften für Entwurfsprobleme. Damit lassen sich zum Beispiel aus einfachen Vorstufen strukturierte Objekte mit neuen Eigenschaften und Verhalten erzeugen und darstellen. Aber auch die Übertragung des Verhaltens von einem Objekt auf ein anderes, das persistente Verwalten von Objekten in relationalen Datenbanken oder die Mehrsprachigkeit von Software eignen sich für Lösungen durch Pattern.

Wird das Wie der Lösung für wiederkehrende Entwurfsprobleme in Form von Modellen, Beschreibungen und Softwarebeispiellösungen festgehalten, entstehen Lösungsmuster. Damit sind Pattern a priori keine Softwarebausteine, aus denen durch bloße Montage Anwendungen gebildet werden können. Vielmehr sind es Lösungsvorschriften für typische, sich wiederholende, komplexe Entwurfsprobleme.

Frameworks dagegen sind so etwas wie moderne Nachkommen der Standardsoftwaresysteme, wobei sie sich gegenüber ihren Vorfahren durch höhere Flexibilität und wesentlich einfachere Anpassungsfähigkeit auszeichnen. Analog zur Baukunst entsprechen Frameworks sowohl kompletten Bau- und Montageplänen als auch erprobten und für die Anpassung entwickelten Bausteinen zur serienmäßigen Herstellung von Softwaresystemen. Sie ersparen den Entwicklern den für Componentware typischen Aufwand zur Entwicklung von Anwendungsrahmen, weil sie ihn mitliefern. Es lassen sich im übrigen anwendungsunterstützende (Application Enabling Frameworks) und Anwendungsrahmen (Application Frameworks) unterscheiden.

Der Markt für Anwendungs-Frameworks, Framework-Technologien und Framework-basierte Anwendungen wird in den nächsten fünf Jahren enorm wachsen und die Wettbewerbssituation im Softwaremarkt deutlich verändern. Allerdings können auch Framework-basierte Anwendungen in den wenigsten Fällen "auf die grüne Wiese gebaut" werden. Nur selten lassen sich Altsysteme durch neue Anwendungen auf Client-Server-Plattformen ersetzen.

Die meisten Unternehmen gehen Kompromisse ein. Dabei bleiben die bewährten überkommenen Anwendungen der Kern der zukünftigen Anwendungslandschaft. Sie müssen demnach um die Möglichkeit ergänzt werden, Objekte auszutauschen.

Datenkapselung ermöglicht Objekte auf dem Host

Typisch für die Mainframe-Software sind zeichenorientierte Benutzeroberflächen und On-line-Transaktionssysteme, über die auf die Geschäftsobjekte zugegriffen wird. Damit sich diese als Objekt-Server nutzen lassen, erhält die Mainframe-Anwendung ein Objekt-Interface. (siehe Abbildung). Dieses "verpackt" die existente Software nach dem Prinzip der Datenkapselung und bietet den objektorientierten Anwendungsteilen wiederverwendbare Anwendungsobjekte mit allen zugehörigen Operationen als Einheit.

Je nach Middleware-Typus bieten sich unterschiedliche Lösungen an: das "entfernte" Objekt-Interface, das auf den Clients und dedizierten Servern liegt, oder das Mainframe-Objekt-Interface. Im ersten Fall bringt "klassische" Middleware, etwa ein Client- Server-fähiges Online-Transaktionssystem oder eine nachrichtenbasierte Middleware, die Funktionen des Mainframes direkt und unverändert zu den Clients und Servern. Dort werden Gruppen dieser Funktionen objektorientiert zum Objekt-Interface "verpackt".

Im zweiten Fall werden die Anwendungen auf dem Mainframe gekapselt und über objektorientierte Middleware, zum Beispiel eine ORB- Implementierung, der Client-Server-Software zur Verfügung gestellt. Die erste Lösung erscheint dann sinnvoll, wenn die Clients vorwiegend dazu dienen, die zeichenorientierte Benutzeroberfläche durch eine grafische zu ersetzen. Sollen objektorientierte Anwendungsteile auf dedizierten Servern und auf Clients entwickelt werden, bietet das zweite Szenarium langfristig Vorteile.

Angeklickt

Verfechter von Komponentensoftware stellen die Module häufig als Puzzle-Teile dar, die zueinander passen. Tatsächlich erfordern unabhängig voneinander entwickelte Komponenten allerdings häufig einen erheblichen Anpassungsaufwand. Dafür gibt es laut Lindner zwei Ursachen. Sollen Objekte von verschiedenen Komponenten Nachrichten austauschen, müßten die "Erwartungen" des dienstnehmenden Objekts mit den Eigenschaften und dem Verhalten des kooperierenden übereinstimmen. Das ist jedoch unwahrscheinlich. Die zweite Ursache ist die Spezialisierung der Objekte: Sie passen nur in die Anwendung, für die sie konzipiert wurden.

*Ulrich Lindner ist Management-Berater bei der Softlab GmbH, in München.