Objektorientierte Komponentenarchitekturen
(Diese Seite wurde noch nicht auf das neue Layout umgestellt!)

 

Dieser Text ist ein Auszug aus dem Buch: "COM-Komponenten-Handbuch" (Weitere Infos hier)

 

1      Grundlagen objektorientierter Komponentenarchitekturen

Das objektorientierte Paradigma hat sich bereits in vielen Bereichen der Softwareentwicklung etabliert. Der Komponentengedanke ist die konsequente Weiterentwicklung des Prinzips der Objektorientierung; er durchzieht auch immer mehr die Windows-Betriebssysteme. Dieser Anhang bietet Personen, die noch keine Kenntnisse über Objektorientierungen und Komponentenarchitekturen haben, einen kompakten Überblick über die zugehörige Begriffswelt.

1.1          Objektorientierung

EDV-Fachleute sind heute in der Regel bereits mit dem objektorientierten Paradigma vertraut. Da in diesem Buch die Objektorientierung eine zentrale Rolle spielt, soll diese Kapitel eine gemeinsame Begriffswelt sicherstellen. Das vorliegende Buch kann aber keine umfassende Einführung in dieses weitreichende Thema geben. Daher sollen an dieser Stelle nur einige wesentliche Definitionen gegeben werden.

Die Kürzel OO oder OOx sind Sammelbegriffe für die Nutzung objektorientierter Methoden und Techniken im Softwarelebenszyklus: Objektorientierte Analyse (OOA), Design (OOD), Programmierung (OOP) und Datenbank-Managementsysteme (OODBMS) (vgl. [QUI94], S. 264).

 

1.1.1      Objekte

 

»Ein Objekt ist ein Modell eines (meist sehr genau) definierten Teils der Realität, sei es nun in der Umgebung von Alltag und Umwelt oder derjenigen von Daten. Ein Objekt kann als individuelle, identifizierbare Einheit mit folgenden Eigenschaften bezeichnet werden: Die Einheit ist real oder abstrakt, die Grenzen der Einheit sind genau definiert und die Einheit verhält sich innerhalb dieser Grenzen nach genau definierten Regeln.« ([BÖH96], S. 490)

»Ein Objekt ist eine im laufenden System konkret vorhandene und agierende Einheit.« ([OES97], S. 221)

 

Ein Objekt besteht aus Attributen und Methoden. Attribute enthalten Informationen (Daten) über das Objekt. Methoden sind Operationen, die das Verhalten eines Objekts bestimmen. Der Begriff Mitglied (Member) wird als Oberbegriff für Attribute und Methoden verwendet.

 


Beispiel für ein Objekt mit vier Mitgliedern (jeweils zwei Attributen und zwei Methoden), das einen Drucker repräsentiert

 

Ein wichtiges Prinzip der Objektorientierung ist das Information Hiding durch Kapselung: Daten und Programmcode bilden in einem Objekt eine geschlossene Einheit (Kapsel), die für die Außenwelt nur über voll definierte Schnittstellen zugänglich ist. Objekte kommunizieren untereinander über den gegenseitigen Aufruf von Methoden; man spricht in der Objektorientierung davon, dass Objekte über Botschaften (Nachrichten) miteinander kommunizieren. Die Methoden eines Objekts bestimmen, welche Nachrichten ein Objekt empfangen kann. Die Daten eines Objekts sind im Idealfall nicht direkt, sondern nur über den Aufruf von Methoden zugänglich.

Abbildung: Ein Client sendet einem Objekt, das einen Drucker repräsentiert, die Nachricht, eine Datei zu drucken.

 


 

 

 

Einige objektorientierte Sprachen (z.B. Visual Basic) verwenden darüber hinaus auch noch Ereignisse. Ein Ereignis ist eine Nachricht, die ein Objekt an einen Nutzer sendet, wenn bestimmte Bedingungen eingetreten sind. Im Gegensatz dazu ist eine Methode eine Routine, die der Nutzer in dem Objekt aufruft. Auf der Implementierungsebene steckt hinter einem Ereignis ein Methodenaufruf in umgekehrter Richtung, also von dem Objekt an seinen Nutzer. Dies setzt oft voraus, dass der Nutzer selbst ein Objekt ist. 

Objekte werden – ebenso wie elementare Datentypen – mit Hilfe von Variablen verwendet. Diese Variablen heißen oft auch Objektvariablen. Eine Objektvariable enthält entweder das Objekt oder stellt einen Zeiger auf den Speicherbereich dar, in dem das Objekt liegt. Die in diesem Buch vorgestellte Sprache Visual Basic kennt nur die letztere Form. 

Als Nutzer eines Objekts wird in der Regel kein Mensch bezeichnet, sondern ein Programm, das ein Objekt über eine Objektvariable verwendet. Alternativ spricht man auch von Client.

1.1.2      Schnittstellen (Interfaces)

»Eine Schnittstelle umfasst die ausführbaren Dienste eines Objekts. In der Schnittstelle können der Typ eines formalen Parameters festgelegt und das Über-alles-Verhalten der Anfrage beschrieben sein.« ([QUI94], S. 226) 

Bei einem Objekt unterscheidet man zwischen der Schnittstelle und der Implementierung. Eine Schnittstelle beschreibt eine Menge von Mitgliedern (also Attribute und Methoden) eines Objekts mit den zugehörigen Parametern und Rückgabewerten; wie diese Mitglieder implementiert sind, ist dabei ohne Bedeutung. Eine Schnittstelle repräsentiert die Tür zu der Funktionalität eines Objekts und ist eine Untermenge seiner Funktionalität. Eine Schnittstelle ist auch als Vertrag zwischen einem Objekt und seinem Benutzer zu interpretieren, durch den das Objekt zusichert, auf einen bestimmten Satz von Nachrichten (also Methodenaufrufen) reagieren zu können. Eine Möglichkeit zur formalen Beschreibung von Schnittstellen ist die Interface Definition Language (IDL); sie wird auch in COM eingesetzt. 

In Umgebungen, in denen jedes Objekt nur eine Schnittstelle haben darf, ist die Schnittstelle gleichzusetzen mit der Vereinigungsmenge aller Mitglieder des Objekts. Wenn ein Objekt Mehrfachschnittstellen haben kann, dann fasst eine Schnittstelle eine Menge von Mitgliedern eines Objekts zu einer Einheit zusammen. Jede dieser Schnittstellen repräsentiert eine Teilmenge der Funktionalität des Objekts. Bei Mehrfachschnittstellen können die Teilmengen nach beliebigen Kriterien gebildet werden; in der Regel erfolgt die Mengenbildung jedoch nach semantischen Gesichtspunkten.

 

 

Mehrfachschnittstellen ermöglichen einen höheren Abstraktionsgrad als Einfachschnittstellen. Für einen Nutzer ist es sehr wichtig zu wissen, ob ein Objekt eine bestimmte Funktionalität bereitstellt. Im Fall der Mehrfachschnittstellen kann ein Nutzer das Objekt auf das Bestehen einer bestimmten Schnittstelle hin abfragen und sich im Falle einer positiven Antwort darauf verlassen, dass alle zugehörigen Methoden und Attribute angeboten werden. Im Fall von Einfachschnittstellen muss der Nutzer dagegen die Existenz jeder einzelnen Methode und jedes einzelnen Attributs bei dem Objekt erfragen. Durch Mehrfachschnittstellen wird der Aufruf einer Funktionalität von dem Test auf Bestehen der Funktionalität entkoppelt.

 

1.1.3      Klassen

»Eine Klasse ist die Definition der Attribute, Operationen und der Semantik für eine Menge von Objekten. Alle Objekte einer Klasse entsprechen dieser Definition« ([OES97], S. 157). 

Klassen dienen als Schablonen (auch: Templates, Vorlagen, Objektfabriken) für Objekte. Das Verhältnis von Objekt zu Klasse wird durch den Begriff Instanz beschrieben: Ein Objekt ist eine Instanz einer Klasse. Den Vorgang der Bildung von Instanzen nennt man Instanziieren (zum Teil auch Instantiieren geschrieben). Einige Autoren (vgl. z.B. [OES97], S. 221 und [BLA97], S. 421) weisen in diesem Zusammenhang darauf hin, dass die korrekte Übersetzung des englischen Begriffs Instance das deutsche Wort Exemplar ist. In der Fachsprache hat sich aber der Anglizismus Instanz durchgesetzt. 

Häufig wird eine Klasse auch als der Typ eines Objekts bezeichnet. Der feine Unterschied zwischen den Begriffen Klasse und Typ soll hier nicht näher diskutiert werden (vgl. dazu [UNL95], S. 34ff.). 

Eine Klasse gibt vor, welche Attribute und Methoden jede Instanz der Klasse haben wird. Durch das Instanziieren einer Klasse entsteht ein Objekt mit genau diesen Attributen und Methoden. Das durch die Methoden definierte Verhalten ist bei allen Instanzen einer Klasse gleich; die durch die Attributwerte repräsentierten Daten ändern sich jedoch individuell für jedes Objekt.

Eine Klasse ist wie eine Form für Weihnachtsplätzchen. Man stanzt damit Objekte aus, wobei die grundlegende Form vorgegeben ist. Danach ist es aber immer noch möglich, den einzelnen Plätzchen unterschiedliche Zuckergüsse zu geben.

 

 


Darstellung eines Instanziierungsvorgangs

 

 

Normalerweise besteht eine Klasse aus einer Schnittstellendefinition und einer Implementierung. Eine Klasse, die keine Implementierung liefert, heißt abstrakte Klasse. Eine abstrakte Klasse kann nicht instanziiert werden, sondern dient der Vererbung.

Beispiel 

Das Konzept der Klasse sei an einer konkreten Realisierung einer Klasse in der Programmiersprache Visual Basic Script gezeigt. Bitte achten Sie auf das Grundprinzip der Definition einer Klasse, der Instanziierung und der Nutzung.

' === Klassendefinition
Class Gebaeude
 ' --- Attribute der Gebäude-Klasse
 Dim Name
 Dim Strasse
 Dim PLZ
 Dim Ort
 Dim Status einweihen
 Dim Architekt
 Dim Bezugsdatum
 ' --- Nicht öffentliche globale Variablen
 Private AnzahlNutzer
 ' --- Methoden der Gebäude-Klasse
 Sub Einweihung(Jahr)
 Bezugsdatum = Jahr
 Status = "Eingeweiht"
 End Sub
 Sub NeuerNutzer(Name)
 AnzahlNutzer = AnzahlNutzer +1
 ' Weitere Implementierung...
 End Sub
 Function ErmittleAnzahlNutzer(Stand)
 ErmittleAnzahlNutzer = AnzahlNutzer
 End Function
 Sub Abreissen()
 Status = "nicht mehr existent"
 End Sub
End Class

Listing 1.1: Beispiel für eine Klassendefinition in VBScript
[CD: /code/Anhang/gebaeude.vbs]

Im Folgenden werden zwei Instanzen dieser Klasse unter den Namen WBHaus und KAHaus erzeugt und verwendet.

' === Klassennutzung der Gebäude-Klasse
' --- Instanziierung!
Dim WBHaus
Set WBHaus = new Gebaeude
' --- Nutzung der Attribute
WBHaus.Name = "WillyBrandtHaus"
WBHaus.Strasse = "Wilhelmstraße 140"
WBHaus.PLZ = 10963
WBHaus.Ort = "Berlin"
WBHaus.Architekt = "Prof. Helge Bofinger"
' --- Nutzung der Methoden
WBHaus.Einweihung(1996)
WBHaus.NeuerNutzer("SPD")
WBHaus.NeuerNutzer("speedGroup")
Msgbox WBHaus.ErmittleAnzahlNutzer(#6/20/2000#)
' --- Instanziierung eines zweiten Gebäudes
Dim KAHaus
Set KAHaus = new Gebaeude
' --- Nutzung der Attribute
KAHaus.Name = "KonradAdenauerHaus"
KAHaus.Ort = "Bonn"
' usw.
' --- Objektvernichtung
KAHaus.Abreissen
Set KAHaus = Nothing

Listing 1.2: Beispiel für die Nutzung der zuvor definierten Klasse Gebaeude [CD: /code/Anhang/gebaeude.vbs]

Objekt versus Klasse

Ein Objekt ist eine Instanz einer Klasse. Objekte werden immer zur Laufzeit gebildet, während eine Klasse ein statisches Konzept repräsentiert, das zur Entwicklungszeit im Quellcode festgelegt wird.

Nicht immer ist es einfach, die Begriffe zu trennen und sich in einem konkreten Fall zwischen der Verwendung des Begriffs Klasse und des Begriffs Objekt zu entscheiden. Wenn man beispielsweise eine Methode beschreibt, soll man dann von der »Methode der Klasse x« oder der »Methode des Objekts x« sprechen? Grundsätzlich sind beide Ausdrücke richtig. Welchen Begriff Sie im konkreten Fall verwenden, sollten Sie vom Kontext abhängig machen. Verwenden Sie Objekt nur dann, wenn es um das Verhalten einer konkreten Instanz zur Laufzeit geht. Beschreiben Sie jedoch allgemein die bereitgestellten Funktionen, so verwenden Sie besser die Klasse als Bezugspunkt. Viele stellen den Begriff Objekt viel zu sehr in den Vordergrund und sprechen in der Beschreibung der Klassen meistens von Objekten.

 

 

 

1.1.4      Vererbung (Inheritance)

»Unter Vererbung versteht man die Übernahme der Merkmale einer (Ober-)Klasse A in eine (Unter-)Klasse B. Die Unterklasse besitzt zusätzlich zu den eigenen Merkmalen auch alle Merkmale der Oberklasse.« ([GOO97], S. 398)

»Vererbung bezeichnet die gemeinsame Verwendung von Attributen und Operationen durch verschiedene Klassen auf Basis einer hierarchischen Relation. Eine Klasse kann sehr allgemein definiert sein und dann in immer detaillierteren Unterklassen verfeinert werden. Jede Unterklasse übernimmt oder erbt alle Eigenschaften ihrer Oberklasse und fügt ihre eigenen, individuellen Eigenschaften hinzu. Die Eigenschaften der Oberklasse müssen nicht in jeder Unterklasse wiederholt werden.« ([RUM93], S. 3f.) 

Die Oberklasse wird auch Basisklasse, Superklasse oder Elternklasse, die Unterklasse abgeleitete Klasse, Subklasse oder Kinderklasse genannt. Vererbung ermöglicht es, Attribute und Methoden, die mehreren Klassen gemein sind, an einer zentralen Stelle zu definieren. Unterklassen können wiederum Oberklassen für andere Klassen sein. Daraus ergibt sich eine baumartige Vererbungshierarchie (auch Klassenhierarchie genannt).

 


Beispiel für eine Vererbungshierarchie

Mit Vererbung ist in der Regel eine Implementierungsvererbung gemeint, d.h., die Unterklasse erbt den Code der Oberklasse. Wird in einer erbenden Unterklasse eine Methode aufgerufen, die von der Oberklasse geerbt wurde, so wird der in der Oberklasse implementierte Programmcode aufgerufen. Eine redundante Implementierung in der Unterklasse ist nicht notwendig. Gleichwohl kann eine Unterklasse eine neue Implementierung einer Methode der Oberklasse liefern. Man spricht dann von Überschreibung (Overriding). 

Eine andere Form der Vererbung ist die Schnittstellenvererbung. Dabei erbt die Unterklasse nur die Schnittstellendefinitionen mit Namen und Typ der Attribute sowie Namen, Parameter und Rückgabewerte der Methoden. Die eigentliche Implementierung der Methoden wird nicht vererbt. Eine Unterklasse muss also für eine von der Oberklasse geerbte Methode eine eigene Implementierung bereitstellen.

 

 

Die Erstellung einer Vererbungshierarchie ist eine Aufgabe im Rahmen der Entwicklung von objektorientierten Anwendungen und Komponenten. Als Nutzer von Softwarekomponenten haben Sie in der Regel mit der Vererbungshierarchie wenig zu tun. Bei einigen Softwarekomponenten (z.B. dem Windows Management Instrumentarium, kurz: WMI) erleichtert jedoch die Kenntnis der Vererbungshierarchie das Verständnis der Verwendung der Klassen.

 

1.1.5      Beziehungen zwischen Objekten und Klassen

Zwischen Klassen kann es zwei Arten von Beziehungen geben: Vererbungsbeziehungen und Nutzungsbeziehungen. 

Vererbungsbeziehungen drücken aus, welche Klassen von anderen Klassen erben, und sie sind ein Indikator für die Ähnlichkeit der Klassen. Aus den Vererbungsbeziehungen ergibt sich die Vererbungshierarchie (auch: Klassenhierarchie). Diese Beziehungsart wurde bereits im letzten Unterkapitel besprochen. 

Nutzungsbeziehungen (auch: Containment-Beziehungen) beziehen sich auf die möglichen Verbindungen der Instanzen zur Laufzeit. Eine Instanz kann entweder durch eine Aggregation oder durch eine Assoziation mit einem anderen Objekt verbunden sein.

·         Bei einer Aggregation (Is-part-of-Beziehung) ist ein Objekt Bestandteil eines anderen Objekts.

·         Bei einer Assoziation bestehen die Objekte unabhängig voneinander, es gibt jedoch einen Verweis von einem Objekt auf das andere. Aus den Nutzungsbeziehungen ergibt sich eine Objekthierarchie (auch: Containment-Hierarchie). Eine Objekthierarchie bildet ein Objektmodell.

 

 

Rauh und Stickel ([RAS97], S. 260ff.) weisen darauf hin, dass die Semantik der Beziehungsarten nicht in allen objektorientierten Ansätzen die gleiche ist. Dieses Buch orientiert sich an den in der COM-Welt üblichen Definitionen:

E  »Eine Klassenhierarchie beschreibt die Vererbung. Dies bedeutet, dass die Klassenhierarchie zeigt, wie Objekte von einfacheren Objekten abgeleitet werden, indem sie ihr Verhalten erben.« ([MIC98], S. 66)

E  »Das Objektmodell definiert eine Objekthierarchie, die einem objektbasierten Programm seine Struktur gibt. Das Objektmodell legt die Beziehungen zwischen den Programmobjekten fest und organisiert die Objekte so, dass die Programmierung erleichtert wird.« ([MIC98], S. 66)

 

 


Vererbungshierarchie versus Objekthierarchie

 

Kardinalität von Beziehungen zwischen Objekten

 

Eine Nutzungsbeziehung besitzt eine Kardinalität. Ähnlich wie bei der Modellierung relationaler Datenbanken kann es auch zwischen Objekten 1‑zu-1-, 1-zu-n- und n-zu-m-Beziehungen geben: 

  • Bei einer 1-zu-1-Beziehung nutzt eine Instanz einer Klasse genau eine (andere) Instanz einer (anderen) Klasse.

  • Bei einer 1-zu-n-Beziehung nutzt eine Instanz einer Klasse mindestens eine (andere) Instanz einer (anderen) Klasse.

  • Bei einer n-zu-m-Beziehung gibt es eine beidseitige 1-zu-n-Nutzungsbeziehung: eine Instanz der Klasse A nutzt n Instanzen der Klasse B. Eine Instanz der Klasse B nutzt andererseits n Instanzen der Klasse A.

Diese Bedingungen können weiter aufgefächert werden, wenn man zwischen einer Muss- und einer Kann-Beziehung unterscheidet. So kann zwischen einer 1-zu-1- und einer 1-zu-0/1-Beziehung unterschieden werden. Im ersten Fall muss eine Instanz der Klasse A mit einer Instanz der Klasse B verbunden sein. Im Fall der 1-zu-0/1-Beziehung ist die Nutzungsbeziehung eine optionale Beziehung. Entsprechend gibt es auch 1-zu-0/n-Beziehungen und 0/n-zu-0/m-Beziehungen.

Objektmengen

Eine 1-zu-1- oder 1-zu-0/1-Beziehung kann durch ein Mitglied (ein Attribut oder eine Methode) der Ausgangsklasse A, das einen Zeiger auf eine Instanz der Zielklasse B liefert, modelliert werden. Dies ist bei den anderen Beziehungsarten nicht möglich. Instanzen können daher zu Objektmengen zusammengefasst werden.

Eine Objektmenge (auch: Objektsammlung) fasst n Instanzen zusammen. Es gibt in der Objektorientierung zwei weit verbreitete Verfahren, eine Objektmenge zu realisieren: 

  • Das erste Verfahren sind (doppelt) verkettete Listen. Dabei verweist ein Objekt der Objektmenge durch einen Zeiger auf das nächste Objekt. Bei einer doppelten Verkettung weist auch ein Objekt auf das vorherige Objekt. Eine Objektmenge wird dann über einen Zeiger auf das erste Objekt der verketteten Liste identifiziert. Der Nachteil dieses Verfahrens ist, dass die für die Verkettung notwendigen Attribute und Methoden (z.B. Next, Previous, AddNew(), Remove() etc.) in den Klassen der in die Liste aufzunehmenden Objekte implementiert sein müssen. Eine Instanz einer Klasse, die diese Mitglieder nicht anbietet, kann nicht in die Liste aufgenommen werden. Um Implementierungsaufwand zu sparen, werden die für die Listenverwaltung notwendigen Funktionalitäten üblicherweise in einer Basisklasse implementiert, von der die Klassen erben, die in einer Liste aufgenommen werden sollen. Diese Form der Implementierung von Objektmengen ist in objektorientierten Programmiersprachen wie C++ und Java üblich.

  • Das zweite Verfahren basiert auf einer separaten Objektmengen-Verwaltungsklasse. Diese Klasse implementiert eine Möglichkeit, Zeiger auf eine beliebige Menge von Instanzen zu speichern und zu verwalten. Zur Laufzeit wird eine Instanz einer Objektmengen-Verwaltungsklasse (Verwaltungsobjekt) erzeugt, die Zeiger auf Instanzen anderer Klassen aufnehmen kann. Die einzelnen Instanzen, die in die Objektmenge aufgenommen werden, müssen über keinerlei Verwaltungsfunktionen verfügen. Visual Basic verwendet dieses Verfahren zur Implementierung von Objektmengen. Zur Abgrenzung einer Objektmengen-Verwaltungsklasse sei eine normale Klasse, die nicht in der Lage ist, eine Objektmenge zu verwalten, eine Einzelklasse genannt. Diese Form der Implementierung von Objektmengen verwendet Visual Basic.

 

Modellierungen von mehrwertigen Nutzungsbeziehungen durch Objektmengen

 

1-zu-n- und n-zu-m-Beziehungen zwischen Objekten können durch die Verwendung von Objektmengen modelliert werden. Dabei ist der 1-zu-n-Fall einfacher. Ähnlich wie bei relationalen Datenbanken kann eine n-zu-m-Beziehung nicht direkt modelliert werden, sondern muss auf zwei 1-zu-Bziehungen zurückgeführt werden. Die folgende Tabelle unterscheidet die vier Fälle zur Modellierung mehrwertiger Nutzungsbeziehungen. 

 

Im Component Object Model (COM) werden fast ausschließlich Verwalterklassen eingesetzt.


Tabelle: Fallunterscheidung bei der Modellierung mehrwertiger Nutzungsbeziehungen

 

 

 

1-zu-n-Beziehung

n-zu-m-Beziehung

Verkettete Liste

Klasse A enthält einen Zeiger auf das erste Element einer verketteten Liste von Instanzen der Klasse B.

Klasse A enthält einen Zeiger auf das erste Element einer verketteten Liste von Instanzen der Klasse B; Klasse B enthält einen Zeiger auf das erste Element einer verketteten Liste von Instanzen der Klasse A.

Verwalter-klasse

Klasse A enthält einen Verweis auf eine Verwalterklasse C. Die Verwalterklasse C kann dann n Instanzen der Klasse B aufnehmen.

Klasse A enthält einen Verweis auf eine Verwalterklasse C. Die Verwalterklasse C kann dann n Instanzen der Klasse B aufnehmen; Klasse B enthält einen Verweis auf eine Verwalterklasse D. Die Verwalterklasse D kann dann n Instanzen der Klasse A aufnehmen.

 


Grafische Darstellung 

In der in diesem Buch verwendeten Notation (siehe Anhang B) werden Einzelobjekte durch Ovale und Objektmengen-Verwaltungsobjekte durch Rechtecke dargestellt. Ein einfacher Pfeil bedeutet eine 1-zu-1-Beziehung; ein doppelter Pfeil eine 1-zu-n-Beziehung. Die folgende Abbildung zeigt die Modellierung und grafische Darstellung der wichtigsten Beziehungstypen. Eine Unterscheidung zwischen Muss- und Kann-Beziehungen findet nicht statt. Die Beschriftung mit »Klasse xy« bedeutet, dass es sich um ein Objekt der Klasse xy handelt.

Zusammensetzung von Objektmengen

Ein weiteres Unterscheidungskriterium zwischen Objektmengen sind die Bedingungen an die Zusammensetzung der in der Menge enthaltenen Objekte. Man unterscheidet drei Typen: 

  • Sets dürfen nur Objekte einer Klasse und jedes konkrete Objekt jeweils nur einmal enthalten. 

  • Bags dürfen nur Objekte einer Klasse enthalten, Duplikate sind jedoch erlaubt. 

  • Collections dürfen Objekte verschiedener Klassen enthalten.

Sets und Bags sind homogene Objektmengen, während Collections heterogene Objektmengen darstellen. Als deutsche Übersetzung für den Begriff Collection findet man Kollektion.

 

 

In COM wird die diskutierte Unterscheidung zwischen Set, Bag und Collection in der Regel nicht vorgenommen. In der COM-Welt werden Objektmengen unabhängig davon, ob die enthaltenen Instanzen homogen oder heterogen sind, Collections genannt.

 

1.1.6      Objektmodelle

Im Rahmen der Object Modelling Technique (OMT) wird folgende Definition für Objektmodell verwendet: »Das Objektmodell beschreibt die statische Struktur der Objekte in einem System und ihre Relationen. Das Objektmodell enthält Objektdiagramme. Ein Objektdiagramm ist ein Graph, dessen Knoten Objektklassen sind und dessen Linien (Kanten) Relationen zwischen Klassen sind.« ([RUM93], S. 7)

Objektmodelle werden eingesetzt, um den gewünschten Ausschnitt aus der Realwelt auf natürliche Weise zu modellieren. Die Realwelt kann aus der Sicht eines Objektmodells auch selbst wieder eine Software sein. Sofern Objektmodelle Programmierschnittstellen zu Anwendungen darstellen, spiegeln diese die Benutzeroberfläche und/oder das konzeptionelle Design der Anwendung wider. Während die Klassenhierarchie durch den Quellcode konkret vorgegeben ist, sind Objektmodelle zunächst abstrakt; sie werden erst zur Laufzeit realisiert und können sich zur Laufzeit verändern. Den Rahmen für die Veränderung bilden die durch den Quellcode vorgegebenen möglichen Nutzungsbeziehungen. Natürlich können die Vorgaben des Quellcodes so starr sein, dass es nur eine mögliche Anordnung der Instanzen gibt.

Ein Objektmodell kann aus beliebig vielen Klassen bestehen. Seine Struktur muss kein echter Baum sein, sondern kann auch Rekursionen enthalten. Dabei wird die Klasse, die den Einstieg in das Objektmodell darstellt, Stammklasse (auch: Wurzelklasse) genannt. In vielen Fällen sind auch Klassen, die in der Realwelt nicht in Beziehung zu anderen Klassen der Komponente stehen, so modelliert, dass sie über die Stammklasse erreichbar sind.

 


Ein Objektmodell ist die Abbildung von Elementen und deren Beziehungen aus der Realwelt.

 

 


Beispiel für ein durch ein Objektdiagramm verbildlichtes Objektmodell

 

Ein Objektmodell ermöglicht dem Nutzer ein wesentlich intuitiveres Verständnis der abgebildeten Funktionalität als eine Menge »frei im Raum schwebender« Objekte. Komponenten, die eine Menge von Klassen darstellen, enthalten daher in der Regel ein oder mehrere Objektmodelle. Die grafische Darstellung eines Objektmodells in Form eines Objektdiagramms ermöglicht einem Menschen die schnelle Erfassung des Objektmodells. Sie werden in diesem Buch zahlreiche Objektdiagramme zur Veranschaulichung der vorgestellten COM-Komponenten finden. Die dazu verwendete Notation ist in Anhang B beschrieben.

 

 

Objektmodell ist nicht gleich Objektmodell

Der Begriff Objektmodell kommt in der Informatik auch noch in einer anderen Bedeutung vor. In der Modellierung wird ein Objektmodell als eine abstrakte Beschreibung der verfügbaren Elemente betrachtet. Ein Objektmodell auf Modellierungsebene beschreibt also, dass es Komponenten, Klassen, Objekte, Attribute, Methoden, Assoziationen etc. gibt und in welchen Beziehungen diese Elemente zueinander stehen können. Diese Definition von Objektmodell ist gemeint, wenn man von dem Object Model der Object Management Group oder dem Component Object Model spricht (vgl. z.B. [SHW97], S. 283ff.]). In Abgrenzung dazu kann man den Objektmodellbegriff, wie er von Komponentenherstellern verwendet wird, als ein Objektmodell auf Anwendungsebene bezeichnen. In der Begrifflichkeit von Microsoft besteht eine Inkonsistenz, weil die Verwendung des Begriffs Objektmodell im Begriff Component Object Model nicht zu der Verwendung dieses Begriffs in den konkreten Microsoft-Komponenten passt.

 

 

1.1.7      Polymorphismus

»Polymorphie (Vielgestaltigkeit) ist die Eigenschaft einer Variablen, für Objekte verschiedener Klassen stehen zu können.« ([BLA97], S. 425)

»Polymorphismus meint, dass sich die gleiche Operation in unterschiedlichen Klassen unterschiedlich verhalten kann.« ([RUM93], S. 2)

Dabei kann die Variable auf all jene Nachrichten reagieren, die das Objekt, für das die Variable zu einem bestimmten Zeitpunkt steht, unterstützt. Die Implementierung, die durch eine konkrete Nachricht aufgerufen wird, ist über die Lebensdauer der Variablen nicht die gleiche; sie kann sich durch den Verweis auf ein anderes Objekt ändern.

Man nennt zwei Objekte polymorph hinsichtlich einer Nachricht, wenn sie beide auf diese Nachricht reagieren können. Sofern zwei Objekte die gleiche Schnittstelle besitzen, sind sie hinsichtlich aller zu dieser Schnittstelle gehörenden Mitglieder polymorph. Instanzen einer Unterklasse sind hinsichtlich aller geerbten Mitglieder zu den Instanzen der Oberklasse polymorph.

Beispiele

 

Ein Beispiel aus dem Bereich der Gebäude wäre eine Methode NeuerMieter(), die sowohl in der Klasse Wohngebäude als auch in der Klasse Bürogebäude angeboten wird. Sofern eine Variable für ein Gebäude steht, wird in Abhängigkeit davon, um welchen Typ von Gebäude es sich handelt, entweder Wohngebäude::NeuerMieter() oder Geschäftsgebäude::NeuerMieter() aufgerufen. Dieser Polymorphismus beruht auf der Existenz einer gemeinsamen Oberklasse Gebäude. 

Ein Beispiel aus dem Bereich der Betriebssysteme wären zwei Klassen User und Group, die insofern polymorph sind, als sie beide eine Schnittstelle IGrunddaten anbieten. IGrunddaten definiert ein Attribut Name und eine Methode Deaktivieren(). Es ist somit möglich, in einer Schleife über alle Elemente der Benutzerdatenbank auf die Namen der einzelnen Einträge zuzugreifen, ohne dabei eine Fallunterscheidung durchzuführen, um welche Art von Objekt es sich handelt. Das würde in Visual Basic so aussehen:

For Each obj in BenutzerDatenbank
  obj.Deaktivieren()
  MsgBox obj.Name & " wurde deaktiviert!"
Next

 

1.1.8      Dynamische Bindung

»Unter Bindung versteht man die Verknüpfung eines Prozedur- oder Methodenaufrufs mit dem aufrufenden Code. In nicht-objektorientierten Sprachen kann diese Verknüpfung statisch vom Compiler oder Binder vorgenommen werden, so dass sich die Bindungen zur Laufzeit nicht mehr ändern. In objektorientierten Sprachen kann eine Variable wegen der Polymorphie für Objekte verschiedener Klassen stehen. Deshalb muss die Bindung dynamisch erfolgen, also zur Laufzeit.« ([BLA97], S. 428)

 

Die dynamische Bindung ist die notwendige Voraussetzung für die Umsetzung des Polymorphismus.

 

1.2          Komponentenarchitekturen

»Components repräsentieren speziell im Hinblick auf Wiederverwendung entworfene und implementierte Softwarebausteine. Ein Baustein stellt eine Menge von öffentlichen Diensten (engl. public services) zur Nutzung bereit.« ([EIC99], S. 363) 

Betriebssysteme und Anwendungen waren bisher monolithisch aufgebaut. Mit dem Ansatz der Componentware werden sie in kleine(re) Einheiten (Komponenten) aufgeteilt, die einzeln oder in Zusammenarbeit mit anderen Komponenten einzelne Dienste erbringen. Das Prinzip der komponentenbasierten Softwareentwicklung besteht darin, Softwaresysteme aus voneinander unabhängigen Softwarebausteinen zusammenzusetzen. Diese Softwarebausteine können Produkte verschiedener Hersteller sein. Anwendungen werden somit nicht mehr von Grund auf neu entwickelt, sondern aus vorgefertigten Komponenten zu einem Endprodukt zusammengesetzt. Man spricht in diesem Zusammenhang auch von einem Plug&Play-Prinzip für Software. Componentware wird daher als der Schlüssel zur »Industrialisierung« der Softwareentwicklung bezeichnet.

Der Begriff Komponente wird für sehr viele unterschiedliche Dinge verwendet. In diesem Buch ist mit Komponente stets ein Softwarebaustein im objektorientierten Sinne gemeint. Eine objektorientierte Komponente enthält Klassen und bildet zur Laufzeit die Umgebung für die Instanzen dieser Klassen. Man sagt, dass eine bestimmte COM-Komponente ein bestimmtes Objektmodell implementiert oder realisiert.

 

 

Objekt versus Komponente

»Komponenten sind trotz zahlreicher Gemeinsamkeiten mit Objekten im Sinne der objektorientierten Programmierung von diesen erstens in Bezug auf die Größe abzugrenzen: Komponenten sind größere Bausteine, bestehen meist aus einer Menge von Objekten. Zweitens ist mit Komponenten und Objekten ein anderer Zweck verbunden; insbesondere sind Komponenten häufig in ihrer Funktionalität für den Anwender sichtbar. [...] Adressat von Objekten ist aufgrund ihrer feineren Granularität eher der Entwickler von Nicht-Standardlösungen. Schließlich muss drittens die Realisierung von Komponenten nicht notwendigerweise objektorientiert erfolgen, eine Komponente muss nur eine dem objektorientierten Paradigma folgende Schnittstelle besitzen.« ([EIC99], S. 363)

 

 

Die Grenzen von Plug&Play

Plug&Play bedeutet jedoch nicht, dass es für den Nutzer von Softwarekomponenten nichts mehr zu tun gäbe. Drei Aspekte sind – je nach Anwendungsfall in unterschiedlichem Grade – weiterhin von ihm zu leisten: 

  • Installation und Konfiguration der Komponenten: Nach der Installation muss das Umfeld der Komponente konfiguriert werden. Dazu gehören insbesondere die Zugriffsrechte auf die Komponente und die Ressourcen, die die Komponente verwenden darf.

  • Parametrisierung der Komponenten: Ähnlich wie Standardsoftware wird in der Regel auch eine Sammlung von Standardkomponenten nicht alle individuellen Ansprüche des Kunden erfüllen. Daher müssen die Komponenten mit Hilfe der bereitgestellten Schnittstellen parametrisiert werden. Insbesondere sind Standardwerte festzulegen.

  • Verbindung der Komponenten: Die einzelnen Komponenten müssen durch verbindenden Programmcode (engl. Glue Code) integriert werden. Damit eine Integration von Komponenten unterschiedlicher Hersteller möglich ist, müssen Komponenten über eine standardisierte Schnittstelle verfügen. Wenn Softwarehersteller nicht nur einzelne Komponenten mit Teilfunktionalitäten, sondern ein komplettes Komponenten-Bundle für eine bestimmte Problemlösung vertreiben, liefern sie oft auch Glue Code mit. Aus der Sicht des Kunden ist die Bereitstellung einer Gesamtlösung aus Komponenten und mitgeliefertem Standard-Glue-Code zu begrüßen. Sie hat den Vorteil, dass ihm damit eine Test- und Lernumgebung für die Komponenten zur Verfügung steht. Immer häufiger werden dabei Skriptsprachen zur Verbindung von Komponenten eingesetzt. Diesem Trend folgt auch Microsoft mit der ActiveX Scripting-Architektur.

 

 

Komponente versus Klasse

Oft wird der Begriff Komponente mit dem Begriff Klasse gleichgesetzt. Jedoch sind diese Begriffe allenfalls dann gleichbedeutend, wenn eine Komponente nur eine Klasse enthält. Aber auch dann sollten Sie zwischen den beiden Konzepten sauber unterscheiden.

In der Regel besteht eine Komponente aus n Klassen. Eine Komponente ist zudem in der Regel die binäre Form einer Implementierung von Klassen. Verwirrung entsteht auch dadurch, dass manche von der Instanziierung von Komponenten sprechen und damit meinen, dass eine Komponente im Rahmen verschiedener Prozesse mehrfach in den Speicher geladen werden kann.

Leider macht Microsoft selbst in der Dokumentation und auch in Benutzer- sowie Programmierschnittstellen den Fehler, von Komponenten zu sprechen, wenn eigentlich von Klassen gesprochen werden müsste. Das ist nicht nur aus theoretischer Sicht unbefriedigend, sondern bringt auch in der Praxis viel Verwirrung mit sich.

 

 

 

 

Schema einer Softwarekomponente

 

Jede Softwarekomponente im objektorientierten Sinn besitzt ein Schema. Ein Schema ist die Definition der in der Komponente enthaltenen Klassen und der Beziehungen zwischen den Klassen. Auch eine Schnittstellendefinition ist Teil des Schemas einer Komponente. Im Gegensatz zu einer Schnittstellendefinition beschreibt ein Schema eine Komponente vollständig.

Ein Schema definiert ein oder mehrere Objektmodelle. Dies gilt nicht in den Sonderfällen, dass eine Komponente nur aus einer Klasse besteht oder es keine Nutzungsbeziehungen zwischen den Klassen der Komponente gibt. Der Begriff Objektmodell wird häufig auch mit dem Schema einer Komponente gleichgesetzt, obwohl das Objektmodell eigentlich auch nur ein Teil des Schemas ist. 

Komponentenentwickler haben die Wahl, ob sie dem Komponentennutzer das Schema der Komponente (teilweise) offen legen oder aber es vollständig vor dem Benutzer verbergen. Im letzten Fall spricht man von einer Black-Box-Komponente. Eine Komponente, die ihr Schema offen legt und damit semantische Informationen über ihre Arbeit preisgibt, ist eine Grey-Box-Komponente. Sofern der komplette Quellcode der Komponente für den Nutzer einsehbar ist, handelt es sich um eine White-Box-Komponente (in Anlehnung an [BÜC97]). Die Offenlegung des Schemas ist jedoch nur eine Form der semantischen Beschreibung einer Grey-Box-Komponente. Ein transparentes Schema wird zweckmäßigerweise in der Regel selbst wieder objektorientiert in Form einer Objekthierarchie abgebildet.

Middleware

Eine Middleware (auch: Verteilungsplattform, Verteilungsinfrastruktur) ist eine Architektur zur Überbrückung von Rechnergrenzen und zum Aufbau eines verteilten Systems. Die wichtigste Anforderung an eine Middleware ist die (Verteilungs-)Transparenz. Ein Benutzer (egal ob Mensch oder Anwendung) soll entfernte Ressourcen auf die gleiche Weise benutzen können wie lokale. Dazu muss die Middleware von den komplexen internen Aufgaben abschirmen, die nötig sind, um Verteiltheit zu überwinden. Middleware soll auch die Interaktion zwischen Anwendungskomponenten auf heterogenen Systemen unterstützen. In dieser Definition wurde bewusst der allgemeine Begriff »Ressource« verwendet, um von der Frage zu abstrahieren, ob es sich dabei um Objekte oder Komponenten oder nur um einfache Programmroutinen oder Daten handelt.

Heute verfügen alle wichtigen Komponentenarchitekturen auch über eine Middleware und sind daher zum Aufbau verteilter Systeme geeignet.

Österle definiert Middleware folgendermaßen: »Zusammenfassend gesagt ist Middleware eine Softwareschicht, welche auf Basis standardisierter Schnittstellen und Protokolle Dienste für eine transparente Kommunikation verteilter Anwendungen bereitstellt. Middlewaredienste stellen eine Infrastruktur für die Integration von Anwendungen und Daten in einem heterogenen und verteilten Umfeld zur Verfügung.« ([ÖST96], S. 28). »Middleware ist im Rahmen des ISO/OSI-Referenzmodells für Rechnerkommunikation in offenen Systemen den anwendungsorientierten Schichten (Ebene 5-7) zuzuordnen.« ([ÖST96], S. 27)

 

 

 

Eine Komponente wird im Bereich der Componentware auch als Server bezeichnet, da sie einen bestimmten Dienst bereitstellt. Analog dazu ist der Nutzer einer Komponente ein Client. Diese Bezeichnungen sind unabhängig davon, ob die Komponenten sich auf demselben oder auf verschiedenen Computern befinden, und abhängig davon, welche Rolle der Computer in einem Client-Server-Netzwerk besitzt. So kann auch auf einer Windows NT-Workstation eine Komponente ein Server für eine Komponente auf einem NT-Server sein.

 

1.3          Verfügbare Komponentenarchitekturen

 

Es gibt inzwischen verschiedene Ansätze für Komponentenarchitekturen, die in der Praxis eingesetzt werden:

  • das Component Object Model (COM) von Microsoft

  • das .NET-Framework von Microsoft bzw. die Common Language Infrastructure (CLI) der ECMA

  • Java Beans und Enterprise Java Beans (EJB) von der Firma Sun

  • die Common Object Request Broker Architecture (CORBA) der Object Management Group (OMG)

Verbreitung der Komponentenarchitekturen

Das amerikanische Analyse-Unternehmen Cutter Consortium hat im Jahr 2000 die Verbreitung der verschiedenen Komponentenmodelle untersucht. Befragt wurden nordamerkanische und europäische Unternehmen. Paul Harmon dokumentiert in [CUT00], dass 68% der befragten Unternehmen Komponentenarchitekturen einsetzen. Die folgende Grafik zeigt die Verbreitung der verschiedenen Architekturen gemäß dieses Berichts. Das .NET-Framework und die CLI wurden dabei nicht berücksichtigt, da es zum Zeitpunkt der Untersuchung noch nicht einmal eine Beta-Version der Software gab.

Abbildung 1.5: Verbreitung der verschiedenen Komponentenarchitekturen gemäß [CUT00]

Kriterien zur Bewertung der Komponentenarchitekturen

Zur Einstufung der Ansätze gibt es drei wichtige Kriterien:

  • Programmiersprachenabhängigkeit: Ist die Architektur auf eine Sprache zugeschnitten oder können Komponenten, die in unterschiedlichen Sprachen erzeugt wurden, miteinander kommunizieren?

  • Plattformabhängigkeit: Ist die Komponentenarchitektur grundsätzlich nur auf einem Betriebssystem lauffähig? Muss es für jede unterstützte Plattform eine eigene Binärform der Komponenten geben?

  • Herstellerbindung: Wie sehr legt man sich bei der Verwendung der Komponentenarchitektur auf einen bestimmten Hersteller fest?

Einen sehr ausführlichen Vergleich auf Basis zahlreicher Kriterien und unter Verwendung einer Beispielanwendung bietet das Buch von Gruhn/Thiel [GRU00].

Bewertung der Komponentenarchitekturen

 

Während der Java Beans/Java Enterprise Beans-Ansatz programmiersprachenabhängig ist, sind COM, .NET und CORBA programmiersprachenneutrale Komponentenarchitekturen.

Der große Vorteil der Java-Ansätze ist jedoch die Plattformunabhängigkeit der Komponenten, die COM und CORBA hinsichtlich der Binärform der Komponenten nicht bieten. Immerhin gibt es inzwischen zahlreiche Portierungen der Basisdienste von COM und CORBA auf verschiedenen Betriebssystemplattformen. .NET ist grundsätzlich plattformunabhängig, es gibt aber bisher nur eine Implementierung für Microsoft Windows.

Die Herstellerbindung (engl. Vendor Log-In) ist eindeutig bei COM/DCOM am größten. Allerdings unterstützen inzwischen sehr viele Windows-Softwarehersteller (z.B. Corel, Borland) und auch die Open Source-Szene (z.B. bei PHP4) dieses Komponentenmodell. Für .NET hat Microsoft von Beginn an die Unterstützung durch zahlreiche Hersteller als Werbeargument verwendet. Über die langfristige Unterstützung durch andere Hersteller lässt sich aber noch nichts sagen.

JavaBeans und EJB wurden im Schwerpunkt von Sun entwickelt, jedoch waren andere Hersteller auch daran beteiligt. Java Application Server für EJB gibt es von zahlreichen Herstellern. Da diese verschiedenen Implementierungen (nicht zuletzt durch proprietäre Erweiterungen) nicht vollständig kompatibel zueinander sind, begibt man sich auch mit dem Einsatz von EJB Application Servern in eine Abhängigkeit.

CORBA ist ein offener Standard, der aber noch mehr wie EJB darunter leidet, dass es zahlreiche verschiedene Hersteller mit inkompatiblen Implementierungen gibt.


Autor: Holger Schwichtenberg
Dieser Text ist ein Auszug aus dem Buch: "COM-Komponenten-Handbuch" (Weitere Infos hier)