
\section{Iterationsabstraktion} \label{Iterationsabstraktion}
Unter Iterationsabstraktion soll hier die M"oglichkeit verstanden werden, die
Elemente eines Beh"alters in einer von der Beh"alterart unabh"angigen Art und
Weise zu durchlaufen. Es werden innerhalb der Bibliothek drei Varianten
angeboten. Zwei davon sind bereits in der Wurzelklasse des Vererbungsgraphen
{\sf Container} sichtbar. Die dritte ergibt sich aus der Aufteilung der
allgemeinen Beh"altereigenschaften in Eigenschaftsgruppen. Eine Iteration kann
folgenderma"sen durchgef"uhrt werden:

\begin{itemize}
\item{Nutzung des von jedem Beh"alter zur Verf"ugung gestellten Elementstromes}
\item{Verwendung der beh"altereigenen Traversierungsfunktionalit"at, sofern
diese vorhanden ist}
\item{Einfache Iteration "uber alle Elemente mittels der von allen Beh"altern
angebotenen Methode {\sf do}}
\end{itemize}

Die eigentliche Iterationsabstraktion und die m"achtigste Funktionalit"at
bieten die unter der Wurzelklasse {\sf Stream} zusammengefa"sten verschiedenen
Varianten von Objektstr"omen. Abbildung \ref{StreamFig} bietet eine "Ubersicht
auf die verschiedenen Stromkonzepte.

Die Schnittstelle zwischen Beh"altern und
Objektstr"omen stellt die in {\sf Container} eingef"uhrte Methode {\sf
elements} dar (siehe Abbildung \ref{EigUnProFig}). Die Applikation
dieser Methode verlangt von jedem Beh"alter die Erzeugung eines Stroms von
Objekten seines Elementtyps. In der Klasse {\sf ReadStream}, durch welche der
R"uckgabetyp von {\sf elements} beschrieben ist, werden zun"achst nur wenige
Methoden angeboten. Der R"uckgabetyp kann jedoch durch die Subklassen
von {\sf ReadStream} spezialisiert werden. Dies ist m"oglich, da die
Spezialisierung innerhalb der {\sf Stream}-Hierarchie subtyperhaltend
durchgef"uhrt wurde.

Die Implementierung erfolgt "uber die nicht abstrakten
Nachfolger von {\sf Stream}, welche durch den Pr"afix {\sf Internal}
gekennzeichnet sind. Sie spezifizieren ein einfaches, dem Spezialisierungsgrad
angemessenes Basisprotokoll, dessen Realisierung durch Initialisierung der
bereitgestellten Funktionsvariablen mit der richtigen Implementierung erreicht
wird.

Das in der Eigenschaftsgruppe der Traversierungsformen zusammengefa"ste
Protokoll 
wird von unterschiedlichen Beh"altern geerbt. Dadurch wird die M"oglichkeit zum
Traversieren zu einer Eigenschaft des Beh"alters selbst. Eine Trennung zwischen
Beh"alterzustand und Navigationszustand besteht nicht. Daher stellt diese Form
des Traversierens eigentlich keine Iterationsabstraktion dar, weil sie den
Zustand des Beh"alters direkt beeinflu"st. Es besteht deshalb im allgemeinen
auch nicht die M"oglichkeit, mehrere Iterationen dieser Art gleichzeitig
durchzuf"uhren. 

Die Einf"uhrung einer Methode {\sf do} in der Klasse {\sf Container} scheint
redundant zu seien, da entsprechende Funktionalit"at bereits "uber die {\sf
Streams} angeboten wird. Durch diese Methode soll jedoch eine einfache,
optimierbare M"oglichkeit der Iteration "uber alle Elemente angeboten werden.
Diese kann dann unter Vermeidung der eventuell komplexen {\sf
Stream}-Implementierung durch direkten Zugriff auf die Repr"asentation
realisiert werden.
\subsection{'Stream'-Varianten}
Die Klasse {\sf Stream} spezifiziert die Methode {\sf isAtEnd}, durch welche
ein Versiechen des Stroms erkannt werden kann. Die Einf"uhrung einer Methode,
die die Gr"o"se des aktuellen {\sf Streams} bekannt gibt, wurde vorgenommen,
obwohl 
diese Information eventuell nicht beschaffbar ist (z.B. f"ur einen unendlichen
{\sf Stream}). Es kann aber auch sein, da"s die Beschaffung des Wertes zu
aufwendig ist, etwa wenn der Strom f"ur die Berechnung verbraucht werden
m"u"ste. Es wird daher von vorneherein auch der R"uckgabewert {\bf nil} f"ur
eine unbekannte Gr"o"se des verbleibenden Stroms zugelassen.

%%%%%%%%%Bild: Streams
\renewcommand{\epsfsize}[2]{0.789#1}
\begin{figure}[htb]
\begin{center}
\leavevmode
\epsfysize=8cm
\epsffile{../Bilder/bjoern/Bib.Streams.ps}
\end{center}
\caption{{\sf Stream}-Varianten}\label{StreamFig}
\end{figure}

Im folgenden
werden drei Stromeigenschaften unterschieden. Der lesbare Strom {\sf
ReadStream} definiert die Basismethode f"ur den Elementzugriff und
das Ansteuern des n"achsten Elementes {\sf get}, sowie weitere Methoden zur
Iteration und zur Abbildung auf einen anderen Elementtyp ({\sf do} und {\sf
map}). Der beschreibbare Strom {\sf WriteStream} bietet mit der Methode {\sf
put} das Gegenst"uck zu {\sf get}. Sie modifiziert ein Element und geht weiter
zum N"achsten. Der positionierbare Strom f"uhrt einen zus"atzlichen
Typparameter in die Klasse ein, der den Positionstyp beschreibt. "Uber die
Methoden {\sf position} und {\sf position$:=$} kann dann die Position abgefragt
bzw. eine bestimmte Position innerhalb des Stroms angesteuert werden.

F"ur lesbare Str"ome werden drei weitere Varianten unterschieden. Der endliche
lesbare Strom {\sf FiniteReadStream} bietet weitere Methoden zur Bearbeitung
von Str"omen an, die erst durch die Annahme der Endlichkeit sinnvoll
werden. So sind dort beispielsweise pr"adikative Aussagen "uber einen Strom zu
finden wie die Methode {\sf some}, welche feststellt, ob eine Element innerhalb
des Stroms existiert, da"s das "ubergebene Pr"adikat erf"ullt. Ein anderer
Bereich besch"aftigt sich mit der Reduktion von Elementen auf einen Wert oder
mit der Verkn"upfung von Str"omen, wie die Methode ({\sf append}) der in
Abbildung \ref{StreamFig} abgebildeten Klasse.

Anhand dieser letzten Methode {\sf append} in {\sf FiniteReadStream}
sind die Konsequenzen der subtyperhaltenden Spezialisierung innerhalb der {\sf
Stream}-Hierarchie zu erkennen. Die Parameter und der R"uckgabetyp der Methode
sind auf den Objekttyp der Klasse festgelegt. Dies bedeutet, da"s bei der
Nutzung einer solchen Methode f"ur speziellere, z.B. durch Kombination mit den
anderen Eigenschaften entstandene Str"ome das verfeinerte Protokoll "uber die
Parameter nicht sichtbar ist und da"s als Ergebnis der Methode auch nur ein
{\sf FiniteReadStream} zur Verf"ugung steht. Die Implementierung einer Methode
kann daher in einem spezialisierten Strom nicht unter Ausnutzung der neuen
M"oglichkeiten optimiert werden und ein Nutzer, der einen spezialisierten Strom
vorliegen hat, verliert durch Anwendung einer solchen Methode die
Spezialisierungseigenschaften. Vorteil der subtyperhaltenden Spezialisierung
ist jedoch die M"oglichkeit zur Definition einer f"ur alle Beh"alter
einheitlichen Methode zur Erzeugung von Elementstr"omen.

Der gepufferte Strom {\sf
BufferedReadStream} bietet mit der Methode {\sf peek} die M"oglichkeit das
aktuelle Element (mehrfach) abzurufen,  ohne den Schritt zum n"achsten Element
zu vollziehen.

Die Klasse {\sf InternalReadStream} schlie"slich stellt die
schon angek"undigten Funktionsvariablen f"ur das Basisprotokoll eines {\sf
ReadStreams} zur Verf"ugung. Sie werden bei Kombination mit anderen
Eigenschaften durch weitere Variablen erg"anzt. So m"ussen zur Realisierung der
Positionierbarkeit die Methoden zum Auslesen und Setzen der Position vom
Stromerzeuger (oder von einer Subklasse) auf diese Weise implementiert werden.

\subsection{Abgrenzung} Die Str"ome der TooL Klassenbibliothek sind
durch Anpassung und Erweiterung aus den in der Tycoon Modulbibliothek
angebotenen Iteratoren entstanden. Sie sind, im Gegensatz zu der dort erfolgten
rein funktionalen Implementierung, prinzipiell eigenst"andige
Objekte, mit internem Zustand und definiertem Protokoll. Offensichtlich ist
dies bei Nachfolgern wie {\sf File} und {\sf PrimesStream}, welche die
Basismethoden direkt implementieren.

Die Realisierung des Basisprotokolls
mittels Funktionsvariablen, denen die Implementierung erst zugewiesen werden
mu"s, verlagert einen Teil des internen Zustandes in den Funktionsabschlu"s
(die 'Closure') der zugewiesenen Funktionen und damit auf die Seite des
Nutzers.

Aus Sicht eines Beh"alters bedeutet dies, da"s er die Anpassung des
{\sf Stream}-Protokolls individuell selbst durchf"uhren kann. Der Bedarf f"ur
eine parallele, den verschiedenen Beh"altertypen gerecht werdende {\sf
Stream}-Hierarchie entsteht dadurch nicht. F"ur die Trennung von
Beh"alterzustand und Zustand des {\sf Streams} ist der Nutzer (die
Beh"alterklasse) allerdings selbst
verantwortlich, was bei der Verwendung von auf den Beh"altertypus
spezialisierten {\sf Streams} vermieden werden k"onnte. Andererseits l"a"st
sich in der vorliegenden Variante die Koppelung zwischen Beh"alter und
angebotenem Elementstrom flexibel gestalten, ohne das die Definition eines
ver"anderten Basisprotokolls notwendig w"are. Die Implementierung der {\sf
elements}-Methode in einem Beh"alter sollte aber auf jeden Fall erm"oglichen,
da"s mehrere Iterationen gleichzeitig, bzw. geschachtelt auf dem 
selben Beh"alter durchf"uhbar sind ohne da"s diese sich gegenseitig
st"oren. Dieser Grundsatz wurde bei den vorhandenen Implementierungen 
eingehalten.

Bei der Nutzung der {\sf Streams} als Iterationsabstraktion f"ur die Beh"alter
stellt sich die Frage nach der Stabilit"at des Iterierungsprozesses,
d.h. seiner Beeinflu"sbarkeit oder St"orungsanf"alligkeit gegen"uber Einf"uge-
L"osch- und Reorganisationsaktionen auf dem in Bearbeitung begriffenen
Beh"alter \cite[S.86]{Tr95}.

F"ur Iteratoren kann in diesem
Zusammenhang eine Unterteilung in interne und externe Iteratoren getroffen
werden \cite{Kof93}. Als extern wird das schrittweise
Durchlaufen mittels weniger Grundoperationen, als intern die Bearbeitung der
Gesamtmenge durch {\em einen} Methodenaufruf bezeichnet.

Bei einem rein funktionalen
Ansatz ist das interne Iterieren gegen"uber St"orungen unanf"allig. Die Methode
ist auf eine gew"unschte Aussage spezialisiert und l"a"st keine Beeinflussung
zu:

\begin{xple}
without(e :E) :ReadStream(E) {reject(fun(e1 :E){e1 == e})}
\end{xple}

Eine andere Form des internen Iterierens wird durch die "Ubergabe einer
Funktion gesteuert, wie die zur Implementierung von {\sf without} verwendete
Methode {\sf reject}. Sind Funktionen seiteneffektfrei, so ist auch in
diesem Fall der Iterationsprozess stabil.

Beim schrittweisen Vorgehen sind prinzipiell jederzeit Operationen m"oglich,
die den zugrundeliegenden Beh"alter beeinflussen und dadurch die Iteration
destabilisieren k"onnen. 

Alle drei Varianten kommen nebeneinander in der Schnittstelle eines TooL-{\sf
Streams} vor. Eine Aufteilung in interne und externe Iteratoren wird nicht
vorgenommen. Funktionen in TooL k"onnen im allgemeinen seiteneffektbehaftet
sein. Die Funktionsr"umpfe k"onnen jede Art von Beh"altermanipulationen
enthalten, so da"s die Unterscheidung der internen und externen Iteration hier
nicht greift. 

Der Grad der Stabilit"at des Iterierungsprozesses "uber Beh"alterelemente kann
durch eine dreistufige Klassifizierung festgelegt werden. Dabei wird auf
drei Methodengruppen Bezug genommen, welche die Inkonsistenz 
verursachen k"onnen. Die drei Gruppen sind Einf"uge-, L"osch- und
reorganisierende Methoden. Die Klassifizierung lautet dann nach
\cite[S.86]{Tr95}: 

\begin{itemize}
\item{Als {\bf stabil} gilt eine Iterierung, wenn sie weder durch Einf"uge- und
L"oschoperationen in den Beh"alter noch durch die Reorganisation desselben in
einen inkonsistenten Zustand ger"at.}
\item{{\bf Robust} hei"st eine lediglich gegen"uber Beh"alterreorganisationen
konsistenzgef"ahrdete Iterierung.}
\item{Mit {\bf instabil} bezeichnet man schlie"slich eine, durch alle drei
Modifikationsereignisse gef"ahrdete Iterierung.}
\end{itemize}

In dem hier betrachteten Fall ist der Grad der Stabilit"at von der
Implementierung der {\sf Stream}-Basisoperationen durch die einzelnen
Beh"altertypen abh"angig und wird daher von jedem Beh"alter selbst bestimmt. In
der derzeitigen Version der Beh"alterbibliothek liefern die meisten Beh"alter
nach dieser Definition instabile {\sf Streams}.

Die Nutzung eines {\sf
Streams} zur direkten Manipulation der Beh"alterstruktur ist allerdings
meistens nicht notwendig. Dies kann ebenso direkt "uber die Schnittstelle des
Beh"alters geschehen, ohne da"s die Gefahr einer Inkonsistenz besteht. Die
{\sf Streams} k"onnen dagegen zur kompakten Bearbeitung, Filterung,
Konvertierung und Transportierung der Elementmenge eingesetzt werden, wie dies
die meisten Methoden auch nahelegen. Die Einhaltung dieser Trennung erspart den
Aufwand f"ur eine robuste oder gar stabile Implementierung. Die Umsetzung
dieser Trennung von Anfrage und Modifikation f"uhrt zu algorithmischen
Probleml"osung auf einem hohen Abstraktionsniveau. 

Die Verwendung eines
Konzeptes, welches explizite frei bewegliche Zeiger in den Beh"alter anbietet,
verleitet dagegen eher zu semantisch komplizierteren L"osungen
\cite[S.8]{SathMur94}. So stellt ein 
solcher Zeiger eben keine Iterationsabstraktion zur Verf"ugung sondern verlangt
die Positionierung. Er l"adt von vornherein eher zur parallelen
Modifikation des Beh"alters ein und verlangt somit auch mehr nach einer L"osung
der Stabilit"atsproblematik.

Die Frage nach der Konsistenz der Iterierung kann im Prinzip beliebig
ausgeweitet werden. Konsistenz sollte in jedem Fall bedeuten, da"s der Proze"s
nicht 'gewaltsam unterbrochen' wird oder einen anderen fehlerhaften Verlauf
nimmt, zum Beispiel die Fortsetzung der Iterierung in einem anderen
Beh"alter. Sie kann sich aber auch auf den Zustand der Elementmenge des
Beh"alters beziehen. Auf jeden Fall sollten alle Elemente des Beh"alters
erfa"st werden. Sind dies aber die Elemente zu Beginn des Prozesses oder werden
auch "Anderungen w"ahrend des Durchlaufens sichtbar? Werden dann alle
"Anderungen oder nur solche in dem noch nicht erfa"sten Bereich des Beh"alters
ber"ucksichtigt? Die Trennung von Anfrage und Modifikation mittels der
{\sf Stream}-Funktionalit"at einerseits und Ver"anderung der Beh"alterstruktur
durch Einf"uge- L"osch- und Reorganisationsaktionen "uber die
Beh"alterschnittstelle andererseits l"a"st diese Probleme jedoch in den
Hintergrund treten, sofern man diese Trennung einhalten will.

    \section{Zwischenergebnis}\label{BehFazit}Der folgende Abschnitt soll ein
kurzes Zwischenergebnis formulieren im Hinblick auf die am Anfang von
\ref{TBehBib} beschriebenen Zielsetzungen.

Zun"achst wurde am Beginn des Kapitels die Frage
aufgeworfen, ob sich eine Beh"alterklassenbibliothek unter den besonderen 
Randbedingungen der Sprache TooL entwerfen l"a"st. Besonders hervorgehoben
wurde in diesem Zusammenhang die strikte Typisierung, der Zwang zur
Schnittstellenvererbung, der keine Umbenennung und kein Verstecken von Methoden
erlaubt, sowie die Einf"uhrung der "Ahnlichkeitsrelation und des
diesbez"uglichen parametrischen Polymorphismus. Weiterhin sollte das Ziel hoher
Wiederverwendbarkeit und Kombinierbarkeit von Funktionalit"at nicht aus den
Augen verloren werden.

Der Ansatz, die Methoden der Beh"alterklassen so aufzuteilen, da"s eine
Umbenennung, Ausklammerung oder 'Entfunktionalisierung'\footnote{Damit soll die
"Uberschreibung einer Methode durch einen Implementierung gemeint sein, die nur
noch eine Fehlermeldung ausgibt}, wie es in vielen Bibliotheken praktiziert
wird\footnote{Siehe Abschnitte \ref{Cpp}, \ref{Nihcl}, \ref{Smlltlk} und \ref{Effl}}, vermieden werden kann, f"uhrt zwangsl"aufig zu einer feineren
Aufteilung. Es mu"s darauf geachtet werden, da"s die Methoden mit den
Eigenschaften eines konkreten Beh"alters harmonieren, damit Ver"anderung der
Schnittstellen gar nicht erst n"otig werden.

Das in Abbildung \ref{SchemaBild} skizzierte Entwurfsschema f"uhrt 
eine eigenschaftsbezogene Anordnung der Methoden durch. Dabei werden zun"achst
allgemeine Beh"altereigenschaften formuliert, deren korrespondierende Klassen
entsprechend allgemeines Protokoll aufnehmen. Diese Eigenschaften werden zur
besseren "Ubersichtlichkeit in Eigenschaftsgruppen zusammengefa"st.

Durch Kombination solcher Eigenschaften werden Beh"alterkategorien
gebildet. Die 
Zusammenfassung von allgemeinen Eigenschaften in einer Wurzelklasse einer
Beh"alterkategorie unterst"utzt die einfache Sicht auf kompliziertere
Beh"altervarianten einer solchen Sparte.

Diese Beh"altervarianten ergeben sich aus der
erneuten Unterscheidung von speziellen Eigenschaften innerhalb einer
Beh"alterkategorie, welche auch nur eine Konkretisierung von allgemeinen, in
der Wurzelklasse der Kategorie noch nicht integrierten Eigenschaften
darstellen k"onnen. Diesen speziellen Eigenschaften kann nun weiteres
beh"alterspezifisches Protokoll zugeordnet werden, welches dann zur Kombination
bereit steht.

Durch das beschriebene Verfahren kann die gew"unschte Aufteilung
und Kombinierbarkeit von Teilfunktionalit"at erreicht werden. Es entsteht
allerdings eine komplexere Klassifizierungsstruktur. Die Komplexit"at wird
durch die Gew"ahrleistung der Schnittstellenvererbung f"ur den Benutzer
gemildert, da er sich auch mit dem einfacheren Protokoll einer h"oheren
Abstraktionsstufe zufrieden geben kann.
Bei der Entwicklung neuer Subklassen
kann das Klassifizierungsschema als Orientierungshilfe dienen. Es sind aber
weitere Hilfsmittel zur Darstellung des Vererbungsgraphen, Anzeige von
Objektschnittstellen und zur Entwurfsunterst"utzung notwendig. Es wurden im
Rahmen der Arbeit auch bereits erste M"oglichkeiten zur Visualisierung der
Klassendefinition und der Vererbungsbeziehungen geschaffen, die im Abschnitt
\ref{Klssnbrwsr} vorgestellt werden. 

Die letzte der zu Anfang des Kapitels aufgeworfenen Fragen betraf die
Auswirkungen des speziellen Typsystems von TooL auf die
Beh"alterklassenbibliothek. 
Die "Ahnlichkeitsrelation erm"oglicht die Integration der Vererbung von
Methoden mit Parametern vom Objekttyp der Klasse selbst, der dann in der
Subklasse in typsicherer Art und Weise spezialisiert wird.
Dies erleichtert einen intuitiven Umgang mit diesen Methoden. Andere
Sprachen verlangen hier generell Subtypbeziehung\footnote{In \cite[S.6]{Mey89}
wird 
die kontravariante Subtypregel f"ur Methodenparameter als wenig intuitiv
kritisiert} und erlauben trotzdem die 
Spezialisierung, wie dies z.B. in Eiffel der Fall ist. Dadurch geht die
Substituierbarkeit der Implementierung in den Kontext der Oberklassen
prinzipiell verloren. Es wird eine Analyse dieses Kontexts ben"otigt, 
wodurch die Modularit"at der Typsicherheits"uberpr"ufung verloren
geht \cite[S.4]{GawMat96}. Dies kann in TooL vermieden werden. 

Die durch das Design der Beh"alterklassenbibliothek sichergestellte einfache
Sicht auf kompliziertere Objekte kann trotz 
Verlustes der Subtypbeziehung zwischen den Beh"alterklassen durch
Anwendungsprogramme genutzt werden, indem sie den "Ahnlichkeitspolymorphismus
zur Formulierung von generischen Methoden einsetzen (Siehe Abbildung
\ref{AhnlPolFig}). Dieser kann auch bereits innerhalb der
Beh"alterklassenbibliothek nutzbar gemacht werden. So zum Beispiel durch den
Einsatz von Typparametern zur Spezifikation einer generischen Klasse f"ur die
Implementierung einer Liste durch verkettete Zellen. Die einfache rekursive
Definition der Zellen unter Ausnutzung der Vererbung, die zum Verlust der
Subtypbeziehung f"uhrt, erlaubt dennoch die polymorphe Formulierung von
Algorithmen (Siehe auch Abschnitt \ref{ImplVar} und Abbildung
\ref{KettungAbstrakt}).

Die Verwendung der "Ahnlichkeitsrelation zur Beschreibung des
Elementtyps eines Be\-h"al\-ters als mit einer Gleichheitsrelation
ausgestattet, 
ist naheliegend. Sie ger"at jedoch in Konflikt mit der Forderung nach
Subtypheterogenit"at\footnote{Dies soll die F"ahigkeit eines Beh"alters
bezeichnen, auch Subtypen seines Elementtyps aufzunehmen.} der Beh"alter. Diese
spezifischen, mit der Implementierung der "Ahnlichkeitsrelation in TooL
zusammenh"angenden Probleme lassen sich aber auf einfache Weise umgehen
(Abschnitt \ref{GenBehKlas}),
soda"s die Funktionalit"at der Beh"alter trotzdem genutzt werden
kann.

%grunds"atzlichen Design-Entscheidungen f"ur die Massendatenklassen
%erl"autert. Die beiden folgenden Abschnitte stellen die Struktur der
%Bibliothek und einige ausgew"ahlte Implementierungsdetails vor.
%     \subsection{Designgrunds"atze}Es werden verschiedene
%Klassenbibliotheken f"ur Massendaten auf ihre Strukturentscheidungen hin
%untersucht\cite{Mey94a}\cite{GolRob89}\cite{Sha91}\cite{Har90}\cite{HKMN93}\cite{Lin88}.
%%\include{Smalltalk}
%        \subsubsection{Eiffel}
%        \subsubsection{Smalltalk}
%        \subsubsection{NIHCL}
%        \input{nihcl}
%        \subsubsection{(\dots)}
%        \subsubsection{Portabilit"at}
%     \subsection{Struktur}Die Struktur der TooL-Klassenbibliothek wird vorgestellt.
%        \subsubsection{abstrakte Klassen}
%        \subsubsection{realisierte Klassen}
%     \subsection{Implementierung}Es werden einige interessante
%Implementierungsdetails aufgegriffen. (z.B. Iteratoren \ldots)

