next up previous
Nächste Seite: Stilistische Konventionen Aufwärts: Organisation und Aufbau von Vorherige Seite: Strukturierung in Schichten

Hierarchien

Das nächste wichtige Ordnungsprinzip bei Bibliotheken sind Hierarchien, wobei es sich nicht immer um Hierarchien im strengen Sinne handelt, sondern häufig nur um gerichtete Graphen ohne Zyklen (DAGs). Entscheidend ist somit die topologische Sortierbarkeit. Die beiden folgenden Beziehungen sind dabei von besonderem Interesse:

Abbildung 3.6: Modulhierarchie im Ein- und Ausgabebereich
\begin{figure}\epsfig{file=streams-hier.eps}\end{figure}

Importbeziehung:
Auf der Basis von Importbeziehungen lassen sich die irreflexiven Ordnungsrelationen $\rightarrow$ und $\rightarrow^+$ zwischen Modulen definieren (Schnittstelle und MODULE werden als zusammengehörig betrachtet): Zwar lassen viele Programmiersprachen (einschließlich Oberon) Import-Zyklen zu - dennoch sollten sie in jedem Fall vermieden werden (und es ist auch in jedem Fall möglich), da ansonsten die Initialisierungsreihenfolge undefiniert ist.

In den später folgenden Diagrammen, die Modulhierarchien darstellen, beziehen sich die Pfeile immer auf die Relation $\rightarrow$ (wie z.B. in Abbildung 3.6). Wenn zwischen zwei Modulen $A$ und $B$ die Relation $A \rightarrow^+ B$ definiert ist, wird $A$ unterhalb von $B$ angeordnet.

Natürlich ist es auch möglich, die Importbeziehungen von Schichten zu betrachten und darzustellen, wie es zum Beispiel in Abbildung 3.5 für die Ulmer Oberon-Bibliothek zu sehen ist.

Abbildung 3.7: Abstraktionen und Implementierungen
\begin{figure}\epsfig{file=abstr-impl.eps} \end{figure}

Erweiterungsbeziehung:
Analog können Ordnungsrelationen $\rightarrow$ und $\rightarrow^+$ zwischen Typen (Zeiger und Records) definiert werden (siehe auch §2.3): Wenn $M(T)$ das Modul ist, indem $T$ definiert ist, dann gilt

\begin{eqnarray*}
T \rightarrow U & \Rightarrow & M(T) \rightarrow M(U) \\
T ...
... M(T) \rightarrow^+ M(U),
\quad\mbox{falls}\quad T \not= U \\
\end{eqnarray*}



Im Falle von single inheritance handelt es sich um Hierarchien im strengen Sinne, bei multiple inheritance ergibt diese Relation einen DAG.

Die später folgenden Diagramme, die Typhierarchien darstellen, werden analog zu den Modulhierarchien angeordnet (Basistypen unten, abgeleitete Typen weiter oben), wenngleich in der Literatur überwiegend die umgekehrte Variante bevorzugt wird.

Die beiden wichtigsten Modulvarianten sind Abstraktionen (deferred classes) und implementierende Module. Generell ist es bei objekt-orientierten Bibliotheken interessant, wie Abstraktionshierarchien (auf Basis von Erweiterungsbeziehungen) und Implementierungshierarchien (auf Basis von Importbeziehungen ohne entsprechende Erweiterungen) aufgebaut und miteinander verknüpft sind.

Im idealen Fall läßt sich jedes Modul einer der beiden Kategorien exklusiv zuordnen und in eine entsprechende Hierarchie einordnen. Während das Ziel bei einer Hierarchie von Abstraktionen darin liegt, allgemeine abstrakte Schnittstellen zu offerieren, die in jede gewünschte Richtung verfeinert werden können, liegt der Hauptzweck bei Implementierungshierarchien in der Wiederverwendung von Programmtext. So können vielerlei Algorithmen als Baukasten zur Verfügung stehen und bei mehr als einer Implementierung einer Abstraktion eingesetzt werden. Abbildung 3.7 zeigt die sich daraus ergebende Struktur, wobei Implementierungsbeziehungen gestrichelt dargestellt sind.

Diese ideale Situation wird leider häufig nicht erreicht, da bei den klassischen objekt-orientierten Programmiersprachen die Versuchung zu groß ist, eine Implementierung bereits bei der Abstraktion unterzubringen, die dann im Verfahren der Überdefinition alternativ implementiert werden kann. Auch werden häufig Erweiterungsbeziehungen verwendet, um den Programmtext von Implementierungen wiederzuverwenden.

Abbildung 3.8: Implementierungs-orientierte Klassenhierarchie bei Eiffel
\begin{figure}\epsfig{file=eiffel-hier.eps}\end{figure}

Ein Beispiel dafür liefert eine frühe Version der Eiffel-Bibliothek (siehe Abbildung 3.8), bei der sich der Aufbau an den Implementierungen orientiert. So offeriert TREE die Funktionalität eines Mehrwegbaumes, wobei es eine Erweiterung von LINKED_LIST ist, um den Programmtext für lineare Listen wiederzuverwenden. Wenn hingegen streng zwischen Abstraktionen und Implementierungen unterschieden wird, könnte der in Abbildung 3.9 demonstrierte Aufbau entstehen, der bemerkenswerterweise völlig ohne multiple inheritance auskommt.

Abbildung 3.9: Alternative mit zweigeteilter Hierarchie
\begin{figure}\epsfig{file=eiffel-alt.eps}\end{figure}


next up previous
Nächste Seite: Stilistische Konventionen Aufwärts: Organisation und Aufbau von Vorherige Seite: Strukturierung in Schichten
Andreas Borchert 2000-12-18