Benutzer:Centic/Komponentenbasierte Programmierung/Ausarbeitung

Dies ist eine alte Version dieser Seite, zuletzt bearbeitet am 10. Dezember 2005 um 23:09 Uhr durch Dashel (Diskussion | Beiträge) (Komponenten als Lösung für Teilprobleme: Typo). Sie kann sich erheblich von der aktuellen Version unterscheiden.

Komponenten und die objektorientierte Programmierung

Einführung in die Problemstellung/Motivation

Obwohl objektorientierte und komponentenbasierte Programmierung viele Gemeinsamkeiten haben, ergeben sich durch die verschiedenen Konzepte unterschiedliche Ansätze, die beim Einsatz von Objektorientierter Programmierung als Grundlage für Komponentenbasierte Programmierung beachtet werden müssen. Objektorientierung verwendet Klassen und Objekte als zentrale Design-Elemente. Komponentenbasierte Programmierung hingegen versucht, in Anlehnung an Hardware-Komponenten, austauschbare, zuverlässige Bausteine (Komponenten) zur Assemblierung von Softwaresystemen zur Verfügung zu stellen.

Wir versuchen in dieser Arbeit, Besonderheiten der Komponentenbasierten Programmierung darzustellen und in Relation zum Paradigma der Objektorientierung zu setzen. Wir untersuchen dabei nicht eine konkrete Sprache/Bibliothek, sondern das Paradigma der Objektorientierung auf Tauglichkeit zur Umsetzung des Komponentenkonzepts. Als besonders wichtig erscheinen uns hier Ansätze, die die verschiedenen Abstraktionslevel von CBSD (engl. component based software development) und OOP (engl. object orientet programming) betrachten, wie in Abbildung ~\ref{fig:CBSE} dargestellt wird.

 

Das objektorientierte Paradigma

OOP wurde in den 80er Jahren des vorigen Jahrhunderts entwickelt, um die immer größere Komplexität von Softwareprojekten in den Griff zu bekommen. Durch rasch wachsende Anforderungen an Anwendungen geriet die bis dahin vorherrschende prozedurale Programmierung immer mehr an ihre Grenzen. Das Konzept der Objektorientierung versprach hier Abhilfe durch die Aufteilung der Aufgabe in einzelne Einheiten, welche als Objekte bezeichnet werden.

Diese Objekte sind Objekten in der realen Welt nachempfunden. Dies wird erreicht, indem in Objekten Daten und die auf diese Daten definierten Operationen zusammengefast werden. Die Objekte interagieren miteinander, indem sie Nachrichten austauschen und sich gemäß diesen Nachrichten verhalten. Ein Programm ist demnach eine Menge von relativ eigenständigen Objekten, die miteinander auf die beschriebene Weise interagieren [Poetsch01]

Denkweise und Begriffe der objektorientierten Programmierung zeigten sich zuerst in Simula, einer Sprache für Simulationszwecke, die als erste (damals noch nicht so genannte) objektorietierte Verfahren einführte. Heute hat sich objektorientierte Programmierung durch Programmiersprachen wie Smalltalk, C++ und Java stark verbreitet.

Grundkonzepte

Die Grundlagen der objektorientierten Programmierung lassen sich durch einige grundlegende Konzepte erläutern. [Poetsch01] beschreibt die folgenden Grundkonzepte der Objektorientierten Programmierung:

Objektkonzept
Softwaresysteme werden als eine Menge kooperierender Objekte modelliert. Konzeptionell sind Objekte eigenständige Ausführungseinheiten, die auf Nachrichten reagieren können. Objekte haben eigene Operationen und einen eigenen Zustand. Die Ausführung eines OO-Programms besteht im Nachrichtenaustausch zwischen Objekten, dem Ändern des eigenen Zustandes und dem Erzeugen/Zerstören von Objekten. Konsequenz daraus sind im Vergleich zum prozeduralen Programmieren das eine Zusammenfassung von Daten, Zustand und Operationen in kleine Einheiten (Objekte) mit sauberer Schnittstelle nach außen erfolgt und dass das Ausführungsmodell inhärent für die parallele Ausführung geeignet ist.
Klassifikation
Objekte lassen sich anhand der öffentlichen Schnittstelle klassifizieren. Dies stellt die Grundlage für Abstraktion und Spezialisierung dar. \textbf{Abstraktion} bedeutet dabei die Zusammenfassung gemeinsamer Eigenschaften von Objekten/Typen zu einem neuen Typ unter Verkleinerung der Schnittstelle. Als \textbf{Spezialisierung} bezeichnet man die Erweitern von Objekten und Typen sowie ihrer Implementierung.

Sprachliche Realisierung der Grundkonzepte

Die Grundkonzepte werden durch folgende Konzepte erweitert, um diese in eine Programmiersprache zu überführen.

Klassenkonzept
Klassen werden in Verbindung mit Typisierungs- und Modularisierungskonzepten zur Deklaration von Objekteigenschaften verwendet. Saubere Schnittstellenbildung führt zur Kapselung.
Vererbungskonzept
Die Vererbung erlaubt das Übertragen von Eigenschaften existierender Klassen/Objekte auf neue Objekte, die entweder die Funktionalität der ursprünglichen Klasse erweitern oder modifizieren. Dies führt zu Anpassbarkeit, Erweiterbarkeit und reduziert die Programmgröße, da bestehende Funktionalität nicht kopiert werden muss, sondern mitverwendet werden kann.
Dynamische Methodenauswahl und Subtyping
Dynamische Methodenauswahl meint, dass zum Zeitpunkt der Implementierung nicht festgelegt, welche Klasse die Implementierung der Methode zur Verfügung stellt. Je nach Vererbungs-Hierarchie ermittelt die Laufzeitumgebung die aufzurufende Methode. Dies wird auch als Polymorphismus bezeichnet. Subtyping ermöglicht Polymorphie in typisierten Sprachen.
Kapselung (engl. Encapsulation)
Dies erlaubt den Objekten, Details über die zur Verfügung gestellte Funktionalität zu verbergen und stellt sicher, dass Benutzer des Objektes den internen Zustand nicht unvorhergesehen verändern können. Nur die Implementierung des Objekts kann den internen Zustand lesen und verändern. Zusätzlich veröffentlichen Objekte eine Schnittstelle, die festlegt, wie das Objekt mit anderen Objekten interagieren kann.

Die zuvor genannten Konzepte werden in verschiedenen objektorientierten Sprachen in unterschiedlicher Weise und Gewichtung umgesetzt. So gibt es objektorientierte Sprachen ganz ohne Typkonzept oder Sprachen, die keine Klassen kennen sondern zum Erzeugen eines neuen Objektes ein bestehendes kopieren und dann nach Bedarf modifizieren. Weiter soll an dieser Stelle aber nicht darauf eingegangen werden.

Vorteile der Objektorientierten Programmierung

Objektorientierte Programmiersprachen wurden von Beginn an als Ablösung der vorherrschenden prozeduralen Programmierung entworfen. Die Vorteile manifestieren sich hauptsächlich durch die folgenden Eigenschaften (nach [Page00] und [Poetsch01]):

  • Objektorientierung unterstützt die Wiederverwendung von Software. Klassen können einfacher wiederverwendet werden, als die wenig zusammenhängenden einzelnen Methoden in früheren Ansätzen, da sie einen inneren funktionalen Zusammenhang, sowie eine definierte Schnittstelle nach aussen haben.
  • Objektorientierte Programme sind in der Regel besser erweiterbar als z.B. prozedurale. Dies hat zwei Ursachen: Durch Nutzung von Vererbung können die Eigenschaften von bereits bestehenden Programmen genutzt werden, ohne die wiederverwendeten Programmteile zu ändern. Die Programme werden nur um den neuen Teil ergänzt. Ausserdem sind durch Nutzung des Geheimnisprinzips (strenge Kapselung und Schnittstellenbildung) die Wirkungen von Änderungen gut erkennbar. Änderungen, die die Schnittstelle nicht betreffen, können als lokal betrachtet werden und erzeugen geringeren Prüfaufwand.
  • Das objektorientierte Grundkonzept bietet gute Ansätze für paralelle Programmierung. Objekte in Programmen reagieren auf Nachrichten von anderen Objekten und reagieren selbst wieder durch Zustandsänderungen und/oder Nachrichten. Vom Modell her spricht nichts dagegen, dass mehrere Nachrichten gleichzeitig abgeschickt unterwegs sind und somit mehrere Ausführungsfäden gleichzeitig abgearbeitet werden.
  • Durch die logische Zusammenfassung von Daten und Funktion in Objekte und die gute Eignung für paralelle Programmierung bietet die Objektorientierung gute Voraussetzungen zur Lösung verteilter Probleme. Objekte eines Programms müssen sich nicht zwingend auf einem einzelnen Rechner befinden. In Architekturen wie z.B. CORBA werden diese Eigenschaften genutzt und die Entwicklung verteilter Programme durch eine entsprechende Infrastruktur unterstützt.
  • Objekte können direkt gespeichert und so persistiert werden. Man meint damit die Speicherung des Objekt-Zustandes auf nicht-flüchtigen Speichermedien wie Dateisystemen oder Datenbanken, um das Objekt später wieder in den gleichen Zustand versetzen zu können.

Das Konzept der Komponentenbasierten Programmierung

Die komponentenbasierte Softwareentwicklung (engl. CBSE: component based software engineering bzw. CBSD: component based software development) beschäftigt sich mit der Entwicklung von Systemen auf Basis von wiederbenutzbaren Artefakten – den Komponenten – und der Entwicklung von Komponenten [Crnkovic02].

Warum ein neues Programmierparadigma?

Programmierer sind mit dem ständigen Wachstum der Komplexität von Software konfrontiert. Diese Komplexität führte in den späten 60er Jahren zu einer Krise in der Softwarebranche, die heute noch nicht als beendet betrachtet werden kann.

Einer der erfolgversprechenden Wege aus dieser Krise scheint vielen Entwicklern der Versuch, die durch eine Software zu lösenden Probleme in Teilprobleme zu zerlegen und letztlich diese Teilprobleme für sich getrennt zu betrachten.

Diese Gedankengänge führten zunächst zur Modularisierung von Programmen, später zur Objektorientierung und letztlich zur komponentenbasierten Softwareentwicklung.

CBSE ist damit kein vollständig neues Paradigma, sondern greift weitgehend auf bestehende, bereits bewährte Konzepte zurück, um diese in einem konsistenten Modell zusammenzufassen. Es beschäftigt sich zum einen mit der Entwicklung und Wartung von Softwarekomponenten (kurz Komponenten), zum anderen mit der Konstruktion von Softwaresystemen aus Softwarekomponenten.

Komponenten als Lösung für Teilprobleme

Für eine Betrachtung von Problemen als Summe von Teilprobleme ist es notwendig, diese weitgehend voneinander zu entkoppeln. Das heisst, die Teilprobleme müssen so gewählt sein, dass ihre Abhängigkeiten untereinander so gering wie möglich sind. Die Schnittstelle zwischen den Teilproblemen muss also möglichst schmal sein.

Hier sieht [Griffel98] Analogien von Objektorientierung (insbesondere verteilter Objektorientierung) zur CBSE: Eine starke Kapselung der Komponenten/Objekte mit enger Kommunikationsschnittstelle und der daraus resultierenden losen Kopplung innerhalb des Gesamtsystems. Dem zufolge müssen Komponenten also als Blackboxen entwickelt werden, die innere Funktionsweise der Komponente ist also von aussen nicht sichtbar. Gleichzeitig muss die Schnittstelle, über die die Komponente ihre Dienstleistung anbietet, klar definiert und gut dokumentiert sein, um eine einfache Nutzbarkeit zu gewährleisten.

Da das Feld CBSE aus anderen Gebieten hervorgegangen ist, sind viele der Begriffe historisch gewachsen und so sind eindeutige, in der Fachwelt anerkannte Definitionen schwer zu finden. Weitestgehend ist man sich aber darüber einig, dass folgende Eigenschaften eine Komponente ausmachen:

  • Komponenten sind nach aussen streng gekapselt.
  • Kommunikation mit der Komponente geschieht über eine klar definierte Schnittstelle.
  • Komponenten sind eigenständig lauffähige Produkte. Sie unterliegen einer eigenen Versionierung und können als eigenständiges Produkt vertrieben werden.
  • Komponenten können aus anderen Komponenten zusammengesetzt werden.

[Szyperski02] legt zudem noch Wert darauf, dass eine Komponente keinen nach aussen sichtbaren Zustand hat. Diese Forderung hat zur Folge, dass die Kopien einer Komponente voneinander nicht unterscheidbar sind. Demnach können zur Laufzeit die Kopien ausgetauscht werden (z.B. zu Redundanzzwecken oder zum Einspielen eines Updates).

Vorteile

Der Komponentenentwickler kann sich ganz auf die Implementierung der Geschäfts- oder Applikationslogik spezialisieren. Komponentensystem bieten eine Reihe von Infrastruktur-Funktionalität an, welche nach der Übersetzung einer Komponente konfiguriert werden können und das Laufzeitverhalten beeinflußen. Implementierung und Wartung dieser Dienste liegen somit auf Seiten der Entwickler der Container und Applikationsserver. Weitere Belange wie die Verteilung von Komponenten, Lebensdauerverwaltung, Fernzugriff oder Persistenz können ebenfalls von der Laufzeitumgebung übernommen werden.

Nachteile

Trotz der höheren Abstraktion und der damit verbundenen Aufteilung der Aufgaben zeichnen sich auch einige Probleme mit in der komponentenbasierten Programmierung ab. [Schmah03]

Programmiermodell

Komponententechnologien machen eine direkte Abbildung der Komponentenkonzepte auf einer höheren Ebene nicht möglich. Obwohl der Entwickler sich von der Idee her mit Komponenten beschäftigt, ist er durch das Programmiermodell gezwungen, die Konzepte in Konstrukte auf der Ebene der benutzten Programmiersprache, z.B. Objekte, umzusetzen.

In der Regel werden mit den Komponentenmodellen zusätzliche Konventionen definiert, die das Implementieren weiter erschweren. Das Programmiermodell wird dadurch komplexer, der geschriebene Code schwerer verständlich und ein Komponentenentwickler braucht deshalb detailliertes Wissen über diese Konventionen. Auch auf der Clientseite haben die Code Konventionen Auswirkungen, denn der Zugriff auf eine Komponente ist in den meisten Programmiersprachen nicht transparent, z.B. der lookup bei Enterprise JavaBeans. Daneben geht bei EJB ein weiterer Vorteil der Sprache Java verloren – die statische Typüberprüfung. Fehler, die beim Anfordern einer Komponenteninstanz gemacht werden, bleiben bis zur Laufzeit unentdeckt.

Ein weiterer wichtiger Punkt betrifft die Einhaltung von Implementierungsrestriktionen. Diese werden allerdings nicht durch einen Compiler überprüft und deren Einhaltung obliegt somit nur der Disziplin des Entwicklers.

Schließlich ist jede Komponente von der ihr zugrunde liegenden Komponententechnologie abhängig, was bedeutet, dass eine Portierung auf eine andere Technologie nur durch signifikante Änderungen am Code bewerkstelligt werden kann.

Infrastrukturelle Dienste

Implementierung und Bindung infrastruktureller Dienste an die Geschäftslogik werden von den Applikationsservern (engl. Containern) übernommen. Der Vorteil dabei wurde bereits genannt, der Komponentenentwickler ist frei von der Verantwortung und kann sich der Geschäfts- oder Applikationslogik widmen. Dennoch bringt diese Lösung einige Nachteile mit sich.

Zunächst sind die meisten Applikationsserver schwergewichtige „Black Boxen“, d.h. Programme, die alle implementierten Dienste für den Nutzer transparent anbieten, auch wenn nur ein kleiner Teil dessen genutzt wird. Ein Anpassung an spezielle Applikationen ist oft nicht möglich. Dies umfasst die Möglichkeit der Modifikation der Implementierung von Diensten, sowie das Hinzufügen neuer oder das Weglassen nicht genutzter Dienste [POM02].

Zusammenfassend kristallisieren sich folgende Kritikpunkte an standardisierten Komponentenlösungen heraus:

  • komplexe Programmiermodelle erschweren die Realisierung von Komponenten
  • von der Komponententechnologie abhängige Implementierung der Geschäftslogik
  • Implementierungsrestriktionen werden nicht durch den Compiler erzwungen
  • infrastrukturelle Dienste sind vorgegeben und nicht modifizierbar (statisch)
  • fehlender Stanardisierung unter den verschiedenen vorhandenen Komponentensystemen, eine Festlegung macht einen späteren Umstieg sehr aufwändig


Eignung der objektorientierten Programmierung für die komponentenbasierte Programmierung

Objektorientierte und komponentenbasierte Programmierung haben viele Gemeinsamkeiten, vor allem da komponentenbasierte Programmierung aus der Objektorientierung entwickelt wurde und somit als logische Weiterführung der Konzepte der Objektorientierung verstanden werden kann.

Frank Griffel stellt in seinem Buch Componentware zum Beispiel fest, dass die CBSE als Skalierung der OOP betrachtet werden kann (vgl. [Griffel98], Kap. 2.2.2.). Er akzeptiert damit die objektorientierten Techniken als beste heute verfügbare Ausgangsbasis für eine komponentenbasierte Software und bringt diese Überlegungen mit der Formel

\begin{quotation} Komponenten = Objekte + "irgend etwas" \end{quotation}

\noindent auf den Punkt.

In diesem Kapitel wird daher untersucht, welche Probleme auftreten können, wenn objektorientierte Techniken bei der Erstellung von Komponenten zum Einsatz kommen. Dazu untersuchen wir kurz einige exemplarisch ausgewählte Eigenschaften, anhand derer wir die beiden Techniken gegenüberstellen und wesentliche Unterschiede aufzeigen möchten.

Standards

Auch wenn in vielen Projekten Standards verwendet werden, um die Ergebnisse konsistent zu halten, macht Objektorientierung per-se keine Vorgaben, welche Operationen eine Klasse zur Verfügung stellen muß um in das Gesamtsystem integriert werden zu können. Ein komponentenbasiertes System hingegen kann üblicherweise nur in der dafür vorgesehenen Umgebung ausgeführt werden und muß dafür eine von der Umgebung vorgegebene Anzahl von Operationen zur Verfügung stellen. Die Anforderungen können sowohl technischer als auch geschäftlicher Natur sein.

Zustand

Wenn Objekte aus Klassen instantiiert werden, so halten diese Informationen, die zu jeder Zeit den Zustand des Objektes darstellen. Methodenaufrufe können diesen Zustand verändern. Bei Komponenten hingegen wird versucht, möglichst keinen Zustand zu halten und die Komponenten zustandslos zu machen, dies ist jedoch bei den verschiedenen verfügbaren Komponententechnologien unterschiedlich realisiert.

Ablaufumgebung

Bei Objektorientierung wird üblicherweise keine Umgebung für die Ausführung der Objekte definiert und zur Verfügung gestellt. Es wird also keine Vorgabe über die Ausführungsumgebung gemacht. Bei Komponenten hingegen muß normalerweise zur Entwicklungszeit bereits die definierte Ausführungsumgebung (Oft als Container bezeichnet) beachtet werden. Die Ausführungsumgebung kann allerdings dem Entwickler Arbeit abnehmen und häufig verwendete Funktionalität zur Verfügung stellen. Oft ist die Umgebung nötig, um die Komponente überhaupt einsetzen zu können.

Binärstandards

Da Komponenten üblicherweise in übersetzter Form als ausführbare Dateien verteilt werden, haben sie mehr Analogien mit Objekten als mit Klassen, die ja zum Zeitpunkt der Entwicklung verwendet werden. Ausserdem sind Standards für Komponenten meist auf den ausführbaren Code bezogen, die Erfüllung des Binärstandards ermöglicht Verbindungen zwischen Komponenten über ihre Schnittstellen ohne auf die ursprüngliche Implementierungssprache acht nehmen zu müssen. Dies erlaubt auch, Komponenten, die in unterschiedlichen Sprachen entwickelt wurden, zusammen einzusetzen, solange die binären Schnittstellen kompatibel sind.

Metadaten

Manche Komponentensysteme erfordern Metadaten als Teil der eingesetzten Komponenten und ermöglichen damit Prüfungen, welche Operationen eine Komponente zur Verfügung stellt. Eine Komponente wird dabei alle Schnittstellen bekannt geben, die sie zur Verfügung stellt.

Schnittstelle

Sowohl in der Objektorientierung als auch in der Komponentenbasierten Softwareentwicklung hat die Schnittstelle wesentliche Rolle. Sie beschreibt durch Eigenschaften, Methoden und Ereignisse das Verhalten eines Objektes bzw. einer Komponente nach aussen. So wird nur über diese Schnittstelle mit der Umwelt der Komponente/des Objekts kommuniziert.

Durch diese Gemeinsamkeit scheint die Erstellung von Komponenten durch objektorientierte Ansätze sehr gut unterstützt zu werden.

Sprachabhängkeit der Schnittstellen

Die Objektschnittstelle hat aber aus Sicht der CBSE einen entscheidenden Nachteil. Die Schnittstelle eines einzelnen Objekts ist in einer konkreten Programmiersprache verfasst. Z.B. befinden sich diese Beschreibungen in der Sprache ADA in eingenen Spec-Dateien. In Java wird die Schnittstelle durch Schlüsselworte (z.B. public) direkt in der Implementation einer Klasse festgelegt.

Diese Sprachbarriere muss durch eine sprachübergreifende Technik, die vom objektorientierten Grundmodell nicht verlangt wird, überwunden werden. Verschiedene Komponentenmodelle verlangen daher häufig eine externalisierte Schnittstellenbeschreibung (IDL, Interface Definition Language), welche die Schnittstelleneigenschaften in sprachunabhängiger Form festlegt.

Specification Matching

Obwohl beide Paradigmen ähnliche Schnittstellen-Begriffe kennen, geht der Ansatz in der Komponententechnologie doch bedeutend weiter. Über entsprechende Metadaten und formalisierte Verhaltensangaben kann die Auswahl passender Komponenten automatisiert werden. Diese Technik wird als Specification Matching bezeichnet.

[Zaremski96] beschreibt solch eine Möglichkeit, die Spezifikation von Komponenten miteinander zu vergleichen und festzustellen, ob eine Komponente durch eine andere ersetzt werden kann. Dazu werden Vor- und Nachbedingungen (pre- and post-condition predicates) verwendet, durch die das Verhalten der Komponenten beschrieben und formell vergleichbar wird. Punkte, die beim automatisierten Specification Matching geklärt werden müssen sind laut [Zaremski96]: Retrieval, Reuse, Substitution, Subtype, Interoperation.

Unser Eindruck ist, dass dadurch allerdings zu einem gewissen Grad Implementierungsdetails freigegeben und somit das Konzept der Kapselung aufgeweicht werden. Andere Ansätze wären z.B. ein globales Repository mit Schnittstellen, die von Komponenten erfüllt werden können.

Object Aliasing

Aliasing ist ein Problem der Objektorientierung, bei dem Kapselung durchbrochen und die öffentliche Schnittstelle umgangen wird. Trotztdem soll dieses Problem in einem eigenen Kapitel betrachtet werden, da es sich um ein in der Objektorientierung bisher nicht zufriedenstellend gelöstes Problem handelt.

[Hogg92] definiert den Begriff Aliasing folgendermassen: An object is aliased with respect to some context if two or more access-paths to it exist. Aliase entstehen z.B. dann, wenn nicht mit Objekten selbst sondern mit Referenzen auf Objekten gearbeitet wird.

Referenzen auf Objekte haben durchaus ihre Berechtigung (Keine doppelte Haltung von Objekten im Speicher, call by reference etc.). Jedoch muss dem Entwickler objektorientierter Software bewußt sein, dass Aliasing zu Problemen führen kann.

\noindent Ein Beispiel (aus [Hogg92]):

Das Zuweisungsaxiom $\{x = true\} y := false \{x = true\}$ ist nicht mehr ohne weiteres gültig, wenn $x$ und $y$ Referenzen auf ein und das selbe (boolsche) Objekt sind. Dieser Zusammenhang ist bei der Einzelbetrachtung des Hoare-Tripels nicht auffallend.

Problematisch wird das Aliasing, wenn Objekte selbst wiederum aus anderen Objekten zusammengesetzt sind. So ist es denkbar, dass ein Objekt (unbeabsichtigt) über seine Schnittstelle eine Referenz auf ein inneres Objekt herausgibt, und somit an dieser Stelle die Kapselung durchbricht.

Eine solche Referenz könnte ausgenutzt werden, um zu den vertrauenswürdigen Teilen eines Programms Zugang zu erhalten. In [Noble98] wird ein derartiger Defekt in einer Implementierung in SUN's digitalen Signaturen für Java-Applets beschrieben, durch den sich jedes beliebige Applet als Trusted ausweisen konnte, weil statt einer Kopie ein Alias auf die interne Signaturliste zurückgegeben wurde. Diese war dann leicht entsprechend zu modifizieren.

An diesem Beispiel zeigt sich auch die Relevanz von Aliasing für die Komponentenbasierte Entwicklung. Werden Komponenten als Objekte bzw. als Objekt-Cluster implementiert, ist es notwendig, die Schnittstellen der Komponente gegen derartigen Missbrauch abzusichern.

Objekt Aliasing in Schnittstellen vollständig zu verbieten, ist nicht zweckdienlich, da durchaus Komponenten denkbar sind, die Referenzen auf andere Objekte für die Erfüllung ihrer Aufgabe benötigen (z.B. Container).

Es ist an sich auch noch kein Problem, ein Object Alias nach aussen zu geben. Nach [Noble98] entstehen die Probleme erst, wenn von dem herausgegebenen Objekt die korrekte Funktion der Komponente abhängt (siehe das Signatur-Beispiel) und ausserdem dieses Objekt verändert werden kann, ohne dass die Komponente dies feststellt.

Zur Lösung dieses Problems gibt es verschiedene Ansätze. So schlägt [Hogg92] verschiedene mögliche Strategien vor:

  • Detection: Beschreibt statische oder dynamische Verfahren, um problematisches Aliasing zu erkennen und zu verhindern.
  • Advertisment: Methoden beschreiben durch Annotationen, wieweit Aliasing unterstützt wird und erlaubt so eine entsprechende Programmierung.
  • Prevention: Einrichtungen, die durch statische Prüfungen Aliasing verhindern.
  • Control: Versuche, die Auswirkungen von Aliasing zu minimieren.

Diese Strategien hier weiterzuverfolgen, würde aber den Rahmen der Seminararbeit sprengen. Daher sei hier nur auf John Hoggs Islands-Konzept [Hogg91], Almeidas Balloon Types [Almeida97] und auf den beiden aufbauend das Flexible Alias Protection-Modell von Noble, Vitek und Potter [Noble98] verwiesen.

Wiederverwendung

[Griffel98] definiert Wiederverwendbarkeit von Software als das erneute Anwenden von bei der Entwicklung eines Softwaresystems entstandenen Artefakten und angesammelten Wissen bei der Entwicklung eines neuen Softwaresystems, um den Aufwand zur Erstellung und Pflege dieses neuen Systems zu reduzieren.

Beide Paradigmen haben die Zielsetzung, Wiederverwendung zu erleichtern und somit Zeit und Ressourcen zu sparen.

Durch die Kapselung und die daraus resultierende Lokalität von Änderungen sowie durch Vererbung unterstützt die Objektorientierung die Wiederverendung von bereits implementierten Funktionaliäten. Diese Wiederverwendung findet sich bereits in der Anaylsephase wieder und setzt sich bis zur Implementation fort. So ist die Nutzung von Entwurfsmustern genauso eine Form der Wiederverwendung bewährter Lösungen wie das erben und modifizieren einer Klasse.

Bei der Erstellung und Pflege von Komponenten kann diese Eigenschaft der Objektorientierung gewinnbringend einfliessen, wenn man bei der Erstellung die objektorientierte Techniken benutzt.

Es gibt zudem noch die Form der Wiederverwendung von Komponenten als ganzes. Komponenten als Fertiglösungen für Teilprobleme zu nutzen ist ein erklärtes Ziel der Komponentenbasierten Porgrammierung. Hier kann die Objektorientierung nur einen kleinen Beitrag leisten, da diese Form der Wiederverwendung auf einer höheren Abstaktionsebende geschieht (s.a. die Betrachtungen zur Schnittstelle).

Insgesamt ist bei Komponenten üblicherweise Wiederverwendbarkeit stärker betont, Objekte werden wiederverwendet, wenn später Bedarf für ähnliche Funktionalität entsteht, Komponenten hingegen werden für die Wiederverwendung entworfen. Außerdem wird Wert darauf gelegt, Komponenten später durch Alternativimplementierungen austauschen zu können.

Schlussfolgerungen

Durch die Entstehung der komponentenbasierten aus der objektorientierten Programmierung ergeben sich viele Gemeinsamkeiten, besonders in den Bereichen Schnittstellen und Techniken zur Wiederverwendbarkeit. Es kristallisiert sich jedoch heraus, dass CBSD in einigen Punkten beträchtlich weiter fortgeschritten ist und versucht, Schwächen der rein objektorientiert aufgebauten Systeme zu vermeiden.

Anhand der vorgestellten Konzepte der beiden Paradigmen und aufgrund der Ergebnisse unseres Vergleiches, lässt sich schließen, dass Objektorientierung und Komponentenbasierte Programmierung keine Gegensätzlichen Konzepte sind, sondern aufeinander aufbauen, wie auch [Griffel98] feststellt:

... Daher sollten die Konzepte der Objektorientierung und einer Komponentenorientierung nicht als nebeneinanderstehendem, sondern eher als aufeinander aufbauende Techniken betrachtet werden..

Es ergeben sich allerdings auch einige Unterschiede, die Griffel zu folgender Feststellung veranlassen:

\emph{OO-Anwendungen werden typischerweise durch Klassen bzw. Objekte strukturiert. Komponenten können diese Techniken zwar gewinnbringend intern nutzen, bevorzugen aber dynamische strukturelle Bindungen, so daß die Objektorientierung in ihrer heutigen Form möglicherweise am besten zur Modellierung geeignet ist, der komponentenorientierte Ansatz dagegen die vorteilhaftere Implementationssicht darstellt.}

Es scheint, dass sich viele bereits vorhandene Konzepte der objektorientierten Programmierung problemlos in die Welt der Komponenten übertragen und anwenden lassen. Ein Umdenken ist für die angesprochenen Unterschiede zum Teil nötig. Besonders Schnittstellen erfordern eine differenzierte Behandlung, da Komponenten pro\-grammier\-spra\-chen-un\-ab\-hängig automatisch ausgewählt werden können. Ebenso können Problemstellungen, die in objektorientierter Programmierung nur am Rande behandelt werden, für CBSD an Bedeutung gewinnen und bedürfen daher genauerer Betrachtung. Exemplarisch haben wir Object Aliasing besprochen.

Komponentenbasierte Programmierung ist ein vielversprechender Ansatz, der durch die Verbreitung ausgereifter Komponentensysteme (.NET, J2EE, CORBA, ...) große Chancen hat, auf lange Sicht das Objektorientierte Paradigma zu ergänzen und in vielen Bereichen abzulösen.

\newpage

Literatur

  • [Almeida97] Paulo Sergio Almeida. Balloon types: Controlling sharing of state in data types. 1997.
  • [Crnkovic02] Crnkovic, Ivica, Larsson, Stig, Stafford, Judith: Composing Systems From Components. Proceedings of the 9th IEEE Conference and Workshops on Engineering of Computer-Based Systems, Lund University, Lund, Sweden. IEEE. 2002.
  • [Griffel98] Griffel, Frank: Componentware: Konzepte und Techniken eines Softwareparadigmas. 1. Aufl., dpunk-Verlag, 1998, ISBN 3-932588-02-9
  • [Hogg91] J. Hogg. Islands: Alias protection in object-oriented languages. 1991
  • [Hogg92] J. Hogg, D. Lea, A. Wills, D. deChampeaux, and R. Holt. The Geneva convention on the treatment of object aliasing. Follow-up report on ECOOP'91 workshop W3: Object-oriented formal methods. OOPS Messanger, 3(2):11-16, April 1992. http://citeseer.ist.psu.edu/hogg92geneva.html
  • [Noble98] James Noble, Jan Vitek, John Potter: Flexible Alias Protection. 1998. http://citeseer.ist.psu.edu/47376.html
  • [Page00] Page-Jones, Meilir: Fundamentals of Object-Oriented Design in UML. Addison-Wesley, 2000, ISBN 0-201-69946-X
  • [Poetsch01] A. Poetsch-Heffter, J. Meyer, P. Müller: Kurs 01618: Einführung in die objektorientierte Programmierung. Kursunterlagen der Fern-Universität Hagen, 2001
  • [POM02] Roman Pichler, Klaus Ostermann, Mira Mezini, On aspectualizing component models, Darmstadt University of Technology, 2002
  • [Schmah03] Schmah, Steffen: ALICE, Implementierung semantischer Annotationen für Java. 2003. Diplomarbeit am Fachgebiet Softwaretechnik der Technischen Universität Darmstadt. http://www.aop.informatik.tu-darmstadt.de/database/theses/thesis/Diplomarbeit.pdf?id=1
  • [Szyperski02] Szyperski, Clemens, Gruntz Dominik, Murer, Stephan: Component software : beyond object-oriented programming. 2nd ed., Addison-Wesley, 2002, ISBN 0-201-74572-0
  • [Zaremski96] Zaremski, Amy Moormann, Wing, Jeannette M.: Specification Matching of Software Components. 1996. http://citeseer.ist.psu.edu/355687.html