
\subsection{Die C++-Bibliothek NIHCL}\label{Nihcl}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Die Bibliothek NIHCL\footnote{{\bf N}ational {\bf I}nstitute of {\bf H}ealth
{\bf C}lass {\bf L}ibrary} ist eine Sammlung von Klassen, die denen der
Bibliothek von Smalltalk-80 "ahnlich sind \cite{NIH90}. Die Bibliothek enth"alt
sowohl allgemein n"utzliche Datentypen wie {\sf String, Date} und {\sf Time}
als auch die meisten der Smalltalk-80 Beh"alterklassen wie z.B. indizierte
Felder ({\sf OrderedCltn}) , einfach verkettete Listen ({\sf LinkedList}),
Hashtabellen ({\sf Set})  und assoziative Felder ({\sf Dictionary}). In dieser
Arbeit wurde die Version 3.1.4 der Bibliothek untersucht. Einen "Uberblick
"uber die Bibliothek bietet Abbildung \ref{nihclbib}.

\renewcommand{\epsfsize}[2]{1.0#1}
\begin{figure}[hbt]
\begin{center} 
\leavevmode
\epsfxsize=14cm
\epsffile{../Bilder/thorsten/Postscript/NIHCL-Ueberblick.ps}
\end{center}
\caption{Ausschnitt der NIHCL-Klassenbibliothek} \label{nihclbib}
\end{figure}

Die folgenden Abschnitte beschreiben die Organisation der Bibliothek.
In NIHCL wird von der M"oglichkeit der Mehrfachvererbung kein Gebrauch gemacht.
Alle Klassen haben ihren gemeinsamen Ursprung in der Klasse {\sf Object}.
Von besonderem Interesse ist, ob und auf welche Weise die Bibliothek
Wiederverwendung von Funktionalit"at und eine gemeinsame Sicht auf komplexere
Objekte verbindet.

Um erkennen zu k"onne, wie gut die Bibliothek diese Ziele der
objektorientierten 
Programmierung erreicht, m"ussen zun"achst die Beh"alterklassen der Bibliothek
analysiert werden. Eine wichtige Rolle bei dieser Analyse spielt die Frage, in
welcher Klasse der Beh"alterhierarchie welche Methoden eingef"uhrt werden und
ob andere Klassen von diesen Methoden durch Wiederverwendung profitieren. 

Abbildung \ref{nihcl-Methoden} gibt einen "Uberblick "uber die Verteilung der
in NIHCL implementierten Methoden auf die Klassen der Bibliothek. 
\renewcommand{\epsfsize}[2]{1.0#1}
\begin{figure}[hbt]
\begin{center} 
\leavevmode
\epsfxsize=14cm
\epsffile{../Bilder/thorsten/Postscript/NIHCL-MethodenVerteilung.ps}
\end{center}
\caption{Verteilung der Methoden in NIHCL}  \label{nihcl-Methoden}
\end{figure}

\pagebreak
\noindent {\bf Object} \newline
\nopagebreak[3]

\noindent In der Klasse {\sf Object} werden eine Vielzahl von allgemeinen
Definitionen vorgenommen. So findet sich hier die Definition von
Vergleichsmethoden ({\sf compare, isEqual}) und kopierenden Methoden ({\sf
copy, deepenShallowCopy} und {\sf shallowCopy}) . Auch Tests auf
Zugeh"origkeit eines Objekts zu einer bestimmten Klasse ({\sf isKindOf,
isMemberOf, isSame} und {\sf isSpecies}) werden bereits in {\sf Object}
definiert. "Uberraschend ist die bereits in dieser Klasse erfolgende
Einf"uhrung einer Kapazit"at ({\sf capacity}).

\vspace{3mm}
\noindent {\bf Collection} \label{Collection} \newline

\noindent {\sf Collection} ist eine abstrakte Basisklasse f"ur die
Beh"alterklassen der NIHCL. {\sf Collection} implementiert die virtuellen
Methoden, die auf alle Beh"alter angewendet werden k"onnen \cite[S. 37]{NIH90}.
In {\sf Collection} findet man deshalb Methoden zum Einf"ugen ({add}, {\sf
addAll}, {\sf  addContentsTo}) und L"oschen ({\sf  remove removeAll}, {\sf
removeCltn}) von Elementen. Mit Hilfe von {\sf printOn} kann der Inhalt
des Beh"alters auf einen {\sf Stream} ausgegeben werden. Zus"atzlich enth"alt
{\sf Collection} Methoden zum Vergleichen von Beh"altern ({\sf  compare}, {\sf
sameContentsAs}, {\sf  isEqual}). Einige weitere Methoden geben Informationen
"uber den Zustand des Beh"alters ({\sf  capacity}, {\sf  includes}, {\sf
occurrencesOf}, {\sf  isEmpty}, {\sf  size}).

Auffallend ist die Implementierung von Methoden zur Konvertierung der Beh"alter
in einen anderen Beh"altertyp ({\sf  asArrayOb, asBag asHeap, asOrderedCltn,
asSet} und {\sf asSortedCltn}). F"ur jeden gew"unschten
Ziel-Datentyp mu"s eine eigene Methode f"ur die Konvertierung implementiert
werden. Die in NIHCL gew"ahlte L"osung unterscheidet sich deutlich von der in
der TooL-Bibliothek gew"ahlten (Abschnitt \ref{Iterationsabstraktion}). In der
TooL-Bibliothek werden f"ur die Konvertierung von Beh"altern Str"ome ({\it
streams}) von Elementen verwendet. Durch die Verwendung von Str"omen brauchen
in jeder Klasse nur zwei Methoden realisiert zu sein, um eine Konvertierung zu
erm"oglichen. Dies ist eine Methode, die einen Strom von Elementen des
Beh"alters erzeugt, sowie eine Methode, die aus einem Strom von Elementen einen
Beh"alter des jeweiligen Typs erzeugt. Durch diesen Mechanismus bleiben die
Klassen erweiterbar in Bezug auf die Methoden zur Konvertierung. Auch wenn neue
Klassen hinzukommen, braucht in bestehende Klassen keine weiter Methode zur
Konvertierung in die  neue Klasse eingef"ugt zu werden. 

Mit den bisher beschriebenen M"oglichkeiten liefert {\sf Collection} aus NIHCL
ungef"ahr die M"achtigkeit einer Kombination der TooL-Klassen {\sf Boxed} und
{\sf Accessible}. Es gibt jedoch auch deutliche Abweichungen. {\sf Collection}
definiert eine Methode zur Ver"anderung der Kapazit"at ({\sf reSize}).
Erg"anzend werden Faktoren deklariert ({\sf DEFAULT\_CAPACITY}, {\sf
EXPANSION\_INCREMENT}, {\sf EXPANSION\_FACTOR}), die auf {\sf reSize} Einflu"s
haben. Eine weitere Abweichung vom Design der TooL-Bibliothek stellt die in
{\sf Collection} erfolgende Einf"uhrung einer Methode zum indizierten Zugriff
auf die Elemente des Beh"alters dar ({\sf at}). 
In NIHCL sollen also alle Beh"alter
\begin{itemize}
\item eine Kapazit"at kennen. Dies ist eine recht "uberraschende Annahme,
denn beispielsweise eine durch Zeiger verbundene Liste ben"otigt keine
Kapazit"at. Ein Benutzer erwartet bei einer solchen Liste, da"s unabh"angig von
der Zahl der bereits enthaltenen Elemente stets neue eingef"ugt werden k"onnen.
Allein die Gr"o"se des vorhandenen Speichers begrenzt damit die Liste. Eine
durch Zeiger verbundene Liste hat also entweder keine oder eine unendliche
Kapazit"at. Eine solche Liste ist auch als Subklasse von {\sf Collection} in
NIHCL vorhanden. Durch die fr"uhzeitige Einf"uhrung von Kapazit"aten in der
Vererbungshierarchie ergibt sich in der Klasse {\sf LinkedList} ein
Widerspruch. 
\item in der Kapazit"at ver"anderlich sein. Die Einf"uhrung von
Kapazit"ats"anderungs-Faktoren unterbindet eine Unterscheidung zwischen
Beh"altern mit fester und solcher mit variabler Kapazit"at. 
\item einen indizierten Zugriff bieten. Es ist zweifelhaft, ob ein
indizierter Zugriff auf die Elemente bei jedem Beh"alter sinnvoll ist.
Zum Beispiel bei rekursiven Listen oder einer Hashtabelle scheint ein
solcher Zugriff nicht sinnvoll. 
\end{itemize} 

\vspace{3mm}
\noindent {\bf Set} \label{Set} \newline

\noindent "`Ein {\sf Set} ist eine ungeordnete Menge von Objekten, in der kein
Objekt doppelt enthalten ist. "`Doppelt"' vorhanden w"are ein Objekt, wenn zwei
Objekte 
von {\sf isEqual} als gleich erkannt w"urden. Mengen werden unter Verwendung
einer Hashtabelle realisiert. Die Methode {\sf capacity} gibt die H"alfte der
Kapazit"at der Hashtabelle zur"uck, {\sf size} liefert die Anzahl der aktuell
in der Menge enthaltenen Objekte. Aus Gr"unden der Effizienz ist die Kapazit"at
immer eine Potenz von 2. Die Kapazit"at wird automatisch verdoppelt,
wenn die Menge die Kapazit"atsgrenze erreicht"'\footnote{"Ubersetzung aus einem
Kommentar des Quelltextes.}. Wie in TooL werden auch in der NIHCL Methoden
f"ur die typischen Operationen auf Mengen implementiert. 

In NIHCL wird kein Unterschied zwischen {\sf Set} und {\sf Hashtable} gemacht.
Im Kommentar von {\sf Set.h} findet man: "`Set.h - declarations for hash
tables"'. Dies ist ein Unterschied zur TooL-Bibliothek. In TooL werden
sowohl {\sf Set} als auch {\sf HashTable} realisiert. Der Grund f"ur dieses
Vorgehen sind Methoden wie Vereinigung oder Durchschnitt, die man bei einer
Menge erwartet, nicht jedoch bei einer Hashtabelle. In TooL verwendet der
{\sf Set} die {\sf HashTable}. 

In der Klasse {\sf Set} finden sich einige Hinweise auf zweifelhafte
Design-Entscheidungen. So sind f"ur das Einf"ugen von Elementen nun zwei
Methoden vorhanden ({\sf addToSet} und {\sf add}). Die Methode {\sf add} wurde
bereits in {\sf Collection} definiert. Aus nicht ersichtlichen Gr"unden wird
ihr nun {\sf addToSet} hinzugef"ugt. Unverst"andlich bleibt diese zus"atzliche
Methode besonders dadurch, da"s {\sf add} nur als Aufruf von {\sf addToSet}
definiert wird. Die Funktionalit"at beider Methoden ist also absolut gleich.
Deshalb h"atte man auch gleich {\sf add} mit der gew"unschten Funktionalit"at
"uberschreiben k"onnen.

V"ollig isoliert von anderen Design-Entscheidungen wird in Set.c noch
der Begriff des Schl"ussels eingef"uhrt ({\sf findObjectWithKey}). Dies ist
doppelt irref"uhrend, da von {\sf findObjectWithKey} keine Schl"ussel verwendet
werden. Es wird lediglich die Menge nach einem Objekt durchsucht, das die
Eigenschaft {\sf isEqual(ob)} erf"ullt. 

Einen Hinweis auf Designfehler liefert auch die "Uberschreibung von
{\sf compare}. Um den Aufruf von geerbten Methoden zu unterbinden,
die in einer Klasse nicht mehr vorhanden sein sollen, benutzt der
Autor von NIHCL die Methode {\sf shouldNotImplement}. Diese Methode gibt
eine Fehlermeldung aus. Die in einer Klasse st"orende, weil nicht mehr
passende oder schwer zu implementierende Methode wird dann einfach als
Aufruf von {\sf shouldNotImplement} realisiert: 
\begin{xple}
int Set::compare(const Object\&) const
\{ shouldNotImplement("'compare"');
   return 0;
\}
\end{xple}
Gleichzeitig wird die Methode noch von einer "offentlichen in eine
private Methode umgewandelt. In {\sf Collection.h} war {\sf compare} noch als
"offentliche Methode eingef"uhrt worden. Wie in Abschnitt
\ref{UeberschreibenVonMethoden} beschrieben, wird {\sf compare} nun in {\sf
Set.h} in eine private Methode umgewandelt:
\begin{xple}
\begin{bf}private\end{bf}:   // shouldNotImplement()
  virtual int compare(const Object\&) const;
\end{xple}

\vspace{3mm}
\noindent {\bf Arraychar}\label{Arraychar} \newline

\noindent {\sf Arraychar} implementiert Byte-Felder. Der gr"o"ste Teil des
Codes ist "uber eine Makroschablone realisiert. Diese Makroschablone definiert
Makros, die f"ur Felder von eingebauten Typen {\sf char, int, short, long,
unsigned, float} und {\sf double} verwendet werden k"onnen. Arraychar bietet
eine Methode zum Sortieren der Elemente an. Dabei stammt die Funktionalit"at
der Vergleichsfunktion nicht wie bei TooL direkt aus den Elementen des
Arrays, sondern wird in {\sf Arraychar} selbst implementiert.
Auch in {\sf Arraychar} werden Methoden in private umgewandelt. Im einzelnen
sind dies {\sf add, at, doNext, occurrencesOf} und {\sf remove}.

\vspace{3mm}
\noindent {\bf ArrayOb} \newline

\noindent {\sf ArrayOb} realisiert eine Klasse, deren Elemente Zeiger auf
Objekte sind. Bei der Initialisierung wird das Feld mit Zeigern auf
das Nil-Objekt gef"ullt. In {\sf ArrayOb} wird auch {\sf reSize} implementiert,
so da"s das Feld in der Kapazit"at angepa"st werden kann.
Eine Methode zum Entfernen aller im Array enthaltenen Elemente kann in TooL
durch die Verwendung von Streams bereits in der allgemeineren Klasse Accessible
definiert werden. Bei NIHCL wird sie erst in ArrayOb implementiert ({\sf
removeAll}).
Wie viele andere Klassen bleibt auch ArrayOb nicht vom "`Privatisieren"'
von Methoden verschont. Hier sind es die Methoden {\sf add, occurrencesOf} und
{\sf remove}. 

\vspace{3mm}
\noindent {\bf SeqCltn} \newline

\noindent {\sf SeqCltn} ist eine abstrakte Klasse, die Beh"alter
repr"asentiert, 
deren Elemente geordnet sind und "uber ganzzahlige Indizes zugegriffen
werden k"onnen\footnote{"Ubersetzung eines Kommentars aus {\sf SeqClt.c}}.
Obwohl bereits in {\sf Collection} {\sf at} zum indizierten Zugriff auf die
Elemente des Beh"alters enthalten ist, soll {\sf SeqCltn} gegen"uber dem
Vorg"anger {\sf Collection} Indizes als Eigenschaft hinzubekommen. Darum werden
in {\sf SeqCltn}  allgemeine, mit einem Index zusammenh"angenden Methoden
implementiert ({\sf indexOf, replaceFrom, first} und {\sf last}). 
Die Eigenschaften von {\sf SeqCltn} kollidieren nicht mit den
geerbten Methoden. Deshalb ist es hier nicht notwendig, den Aufruf von Methoden
durch Einordnung als private Methode zu erschweren.  

\vspace{3mm}
\noindent {\bf Bag} \newline

\noindent Ein {\sf Bag} entspricht einem {\sf Set}, nur da"s in Bags gleiche 
Elemente 
auch mehrfach auftreten k"onnen. Bei der Implementierung von {\sf Bag} wird ein
{\sf Dictionary} verwendet, um jedes Objekt in {\sf Bag} mit der Anzahl seines
Auftretens zu assoziieren\footnote{"Ubersetzung aus dem
Quelltext von {\sf Bag.c}}. Die Gleichheit von Objekten wird dabei
von {\sf isEqual} festgestellt. Beim Einf"ugen eines bereits vorhandenen
Objekts oder beim L"oschen eines Objekts wird der entsprechende Z"ahler
aktualisiert \cite[S. 19]{NIH90}.  

{\sf Bag} f"uhrt keine wesentlichen Erweiterungen gegen"uber seiner Oberklasse
{\sf Collection} durch. Lediglich eine Methode zum Einf"ugen mehrerer Elemente,
die beim Einf"ugen den Z"ahler nicht auf 1, sondern gleich auf einen
vorgegebenen Wert erh"oht, kommt hinzu ({\sf addWithOccurrences}). Unklar ist,
warum die Methode {\sf compare} nicht implementiert, sondern als private
Methode "uberschrieben wird.

\vspace{3mm}
\noindent {\bf LinkedList} \newline

\noindent Verkettete Listen sind durch die Reihenfolge des Einf"ugens und
L"oschens der Elemente geordnet. Die Elemente sind "uber Indizes
zugreifbar\footnote{"Ubersetzung aus dem Quelltext von {\sf LinkedList.c}}.
{\sf LinkedList} ist eine einfach vorw"artsverkettete Liste. Jedes in ihr
enthaltene Objekt mu"s ein Exemplar einer von {\sf Link} abgeleiteten Klasse
sein. Benutzer k"onnen eine solche Klasse selbst implementieren oder
die Klasse {\sf LinkOb} verwenden, um Zeiger auf Objekte in die {\sf
LinkedList} einzuf"ugen \cite[S. 105]{NIH90}. Diese Wahlm"oglichkeit f"uhrt
dazu, da"s einige Methoden in zwei Versionen vorhanden sind, die sich durch
den Typ ihres Parameters unterscheiden ({\sf Link} bzw. {\sf Object}).
Die Methoden {\sf addFirst, addLast addAfter, removeFirst} und {\sf removeLast}
werden in LinkedList neu eingef"uhrt.

Der in {\sf Collection} eingef"uhrte indizierte Zugriff auf die Elemente der
Beh"alter wird in {\sf LinkedList} aufrechterhalten. Unverst"andlich ist
jedoch, weshalb die geerbte Methode {\sf at} in eine private umgewandelt wird
und statt dessen ein Operator eingef"uhrt wird ({\sf operator[](int i)}).
Da durch diesen Operator aber ebenfalls das Element mit dem als Parameter
"ubergebenen Index zur"uckgegeben wird, bleibt die Ver"anderung der Bezeichnung
der Methode unverst"andlich. 

Auch die im direkten Vorg"anger {\sf SeqCltn} eingef"uhrte Methode {\sf
atAllPut}, die alle Elemente gegen ein anderes austauscht, wird in {\sf
LinkedList} privat. Es ist unklar, warum diese Methode hier nicht implementiert
werden soll. Auch bei den ebenfalls in private Methoden umgewandelten {\sf
indexOfSubCollection} und {\sf replaceFrom} scheint eine Implementierung
in {\sf LinkedList} ohne Schwierigkeiten m"oglich.  

Die bereits bei der Beschreibung von {\sf Collection} in Abschnitt
\ref{Collection} ge"au"serte Vermutung bez"uglich der Kapazit"at best"atigt
sich in {\sf LinkedList}. In einer verketteten List gibt es in NIHCL keine
oder unendliche Kapazit"at, so da"s {\sf reSize} keine Funktionalit"at erh"alt.
Aus nicht ersichtlichen Gr"unden verwendet NIHCL hierzu nicht die bereits an
zahlreichen Stellen verwendete Umwandlung in eine private Methode, sondern
reduziert die Funktionalit"at von {\sf reSize} einfach auf eine
Nicht-Operation. 

\vspace{3mm}
\noindent {\bf OrderedCltn} \newline

\noindent Geordnete Beh"alter sind durch die Reihenfolge geordnet, in der
Objekte in sie eingef"ugt oder aus ihnen gel"oscht werden. Die Elemente einer
{\sf OrderedCltn} sind "uber einen Index zugreifbar\footnote{"Ubersetzung aus
dem Quelltext von {\sf OrderedCltn.c}}.

{\sf OrderedCltn} implementiert ein Feld ver"anderlicher Gr"o"se, das Zeiger
auf Objekte enth"alt. Die Zeiger sind "uber einen bei Null beginnenden
Index zugreifbar, wobei Bereichs"uberschreitungen durch Tests entdeckt werden.
Mit {\sf add} werden Objekte am Ende des Feldes beim Index {\sf size}
abgelegt \cite[S. 169]{NIH90}.

{\sf OrderedCltn} erweitert die Funktionalit"at gegen"uber dem Vorg"anger {\sf
SeqCltn} um Methoden zum Einf"ugen nach zu suchenden Objekten ({\sf addBefore,
addAfter}) und hinter allen Elementen ({\sf addAllLast, addLast}). Mit {\sf
after} bzw. {\sf before} werden die Elemente hinter bzw. vor einem anderen
gesucht. Die zum L"oschen eingef"uhrte Methode {\sf removeId} verwendet zur
Identifikation des Zielelements nicht {\sf isEqual}, sondern die Identit"at.
Ein L"oschen des letzten Elements bietet {\sf removeLast}. Zus"atzlich zum
geerbten indizierten Zugriff ({\sf at}) wird ein Operator ({\sf operator[](int
i)}) mit gleicher Funktionalit"at angeboten. Weitere Operatoren bieten ein
funktionales Anf"ugen aller Elemente einer anderen {\sf OrderedCollection}
sowie diese Funktionalit"at mit Seiteneffekt. Mit {\sf sort} ist eine
Sortierung der Elemente in aufsteigender Reihenfolge m"ogliche.

Unklar bleibt der Grund f"ur die Aufteilung in {\sf SeqCltn} und {\sf
OrderedCltn}, da die in {\sf OrderedCltn} gegen"uber {\sf SeqCltn}
hinzugekommenen Methoden nicht im Widerspruch zu den Eigenschaften einer {\sf
SeqCltn} stehen. Diese Methoden h"atte man auch in der Klasse {\sf SeqCltn}
bereits einf"uhren k"onnen. Es werden in {\sf OrderedCltn} keine geerbten
"offentlichen Methoden in private umgewandelt.

Auch der Begriff einer geordneten Sammlung von Objekten ist
etwas irref"uhrend, da von der {\sf OrderedCltn} keine Reihenfolge der
Objekte erzwungen wird, die in einem Zusammenhang mit den
Eigenschaften der Objekte steht. Es stimmt auch nicht, da"s die
Reihenfolge der Elemente der {\sf SortedCltn} der Reihenfolge ihres
Einf"ugens entspricht. Die Methoden {\sf addBefore, addAfter, removeId} und
{\sf sort} bieten dem Benutzer der {\sf OrderedCltn} die M"oglichkeit, eine
beliebige Reihenfolge der Elemente unabh"angig von der Reihenfolge des
Einf"ugens zu erreichen. Eigentlich handelt es sich deshalb bei der {\sf
OrderedCltn} nicht um einen geordneten, sondern um einen sortierbaren
Beh"alter.

\pagebreak
\vspace{3mm}
\noindent {\bf SortedCltn} \newline
\nopagebreak[3]

\noindent Eine SortedCltn ist ein Beh"alter, dessen Elemente gem"a"s der
Funktion {\sf compare} geordnet sind. Die Methode {\sf compare} mu"s
von den einzuf"ugenden Objekten selbst bereitgestellt werden. Die
Methode {\sf add} stellt durch eine bin"are Suche den Index fest, an
dessen Position ein einzuf"ugendes Objekt positioniert werden mu"s.
Anschlie"send ruft {\sf add} die private Methode {\sf OrderedCltn::addAtIndex}
auf, um das Objekt an der entsprechenden Stelle einzuf"ugen. Um an der
gew"unschten Stelle Platz zu schaffen, schiebt {\sf addAtIndex} alle dahinter
liegenden Elemente im Feld einem Index weiter nach hinten.  Aus diesem Grund
ist {\sf SortedCltn} f"ur gro"se Datenmengen ineffizient\footnote{"Ubersetzung
aus dem Quelltext von {\sf SortedCltn.c}}. 

{\sf SortedCltn} f"uhrt eine neue "offentliche Methoden ein ({\sf
findIndexOf}), die durch eine bin"are Suche den Index eines Objekts im
Beh"alter sucht. Da in {\sf SortedCltn} gleiche Objekte mehrfach vorkommen
d"urfen, wird nicht immer das erste entsprechende Element gefunden. Eine andere
neue Methode ({\sf findRangeOf}) liefert einen Bereich von Objekten, die dem
Suchkriterium gen"ugen. 

Wegen der Ordnung der Elemente ist es unzul"assig, Elemente an beliebigen
Positionen einzuf"ugen. Diese Sortiertheit ist mit zahlreichen geerbten
Methoden unvertr"aglich. Aus diesem Grund wurden die Methoden {\sf addAfter,
addAllLast, addBefore, addLast, atAllPut, indexOfSubCollection, replaceFrom}
und {\sf sort} in die Kategorie der privaten Methoden verschoben. 

\vspace{3mm}
\noindent {\bf KeySortCltn} \label{KeySortCltn}\newline

\noindent Eine {\sf KeySortCltn} unterscheidet sich von der {\sf SortedCltn}
dadurch, da"s die Elemente nach einem separaten Schl"ussel sortiert werden.
Jedes Element ist ein Paar aus Schl"ussel und Wert. Die Sortierung der Elemente
erfolgt jedoch unter ausschlie"slicher Ber"ucksichtigung der Schl"ussel
\cite[S. 95]{NIH90}. Wenn die Kapazit"at durch sukzessives Einf"ugen ersch"opft
ist, wird die Kapazit"at durch {\sf resize} automatisch erh"oht, so da"s 
der Benutzer sich nicht um die Kapazit"at zu k"ummern braucht.

In KeySortCltn werden neue Methoden eingef"uhrt, die den Umgang mit
Kombinationen aus Schl"ussel und Wert in einem sortierten Beh"alter
erm"oglichen. Dies sind Methoden zum Einf"ugen und Suchen ({\sf addAssoc,
addValuesTo, addKeysTo, addContentsBeforeTo, atKey, assocAt, keyAt} und {\sf
valueAt}).

In KeySortCltn werden keine geerbten "offentlichen Methoden in private Methoden
umgewandelt. Dies ist erstaunlich, da deshalb auch die geerbte Methode {\sf
add(Object\& ob)} noch zur Schnittstelle geh"ort. Bei {\sf add} wird jedoch nur
ein Parameter "ubergeben, w"ahrend die {\sf KeySortCltn} beim Einf"ugen
Schl"ussel und Wert erwartet. 

\vspace{3mm}
\noindent {\bf Dictionary} \newline

\noindent {\sf Dictionary} unterscheidet sich von {\sf Set} dadurch, da"s die Elemente
Assoziationen aus Schl"ussel und Wert sind. Das {\sf Dictionary} gibt zu einem
gegebenen Schl"ussel den Wert zur"uck\footnote{"Ubersetzung aus dem Quelltext
von {\sf Dictionary.c}}. Die Gleichheit von Schl"usseln wird durch die
Anwendung der virtuellen Methode {\sf isEqual} festgestellt \cite[S.
53]{NIH90}.

Die geerbte Methode {\sf add} erwartet als Parameter einen Zeiger auf ein
Objekt. Diese Signatur darf nicht ver"andert werden. Da aber in {\sf
Dictionary} nur Elemente eingef"ugt werden d"urfen, die Kombinationen aus
Schl"ussel und Wert sind, mu"s die Vertr"aglichkeit des Arguments zur Laufzeit
getestet werden. Dies stellt eine Schw"ache von C++ gegen"uber TooL dar. In
TooL h"atte man bereits bei der Definition der Vererbungsbeziehung den Typ
der Elemente spezifiziert. In {\sf add} wird deshalb eine Zusicherung
eingebaut, die diesen Test zur Laufzeit "ubernimmt.

Da sich der Elementtyp gegen"uber der Oberklasse {\sf Set} ge"andert hat,
werden in {\sf Dictionary} einige neue Methoden eingef"uhrt. Diese Methoden
realisieren das Einf"ugen ({\sf addAssoc, addKeysTo} und {\sf addValuesTo}),
L"oschen ({\sf removeAssoc, removeKey}) und Suchen ({\sf assocAt, atKey,
keyAtValue} und {\sf includesAssoc}) im Zusammenhang mit Schl"usseln.  
Die Methoden {\sf addKeysTo} und {\sf addValuesTo} wurden auch in {\sf
KeySortCltn} eingef"uhrt. Somit mu"s hier Code doppelt implementiert werden. 
Wenn {\sf atKey} als zweiter Parameter noch ein neuer Wert "ubergeben wird,
"uberschreibt die Methode den alten mit dem neuen Wert. Diese Methode ist damit
ein Beispiel f"ur die Anwendung der in Abschnitt \ref{OptArg} beschriebenen 
optionalen Parameter.
Die Methode {\sf compare} wird aus nicht ersichtlichen Gr"unden in eine private
Methode umgewandelt.  

\vspace{3mm}
\noindent {\bf Stack}\newline

\noindent {\sf Stack} implementiert einen Stapel, dessen Elemente Zeiger
auf Objekte sind. Elemente k"onnen mit {\sf push} auf den Stapel
gepackt werden. Durch {\sf pop} wird das oberste Element entfernt, dessen Index
0 ist. Die Methode {\sf top} liefert das oberste Element. Auch Elemente, die
innerhalb des Stapels liegen, k"onnen "uber ihren Index direkt zugegriffen
werden \cite[S. 215]{NIH90}.  

In {\sf Stack} werden weitere Methoden eingef"uhrt, die jedoch lediglich
bereits vorhandene Funktionalit"at unter einem anderen Namen anbieten. Im
einzelnen sind dies {\sf removeLast} (wie {\sf pop}), {\sf operator[](int i)}
(wie {\sf at}) und {\sf last} (wie {\sf top}).
Auch in Stack m"ussen wieder einige geerbte Methoden in private umgewandelt
werden ({\sf atAllPut, indexOfSubCollection, remove, replaceFrom} und {\sf
startAt}). 

\subsection{Bewertung der NIHCL} \label{NIHCL-Fazit}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Verwirrend bei der Untersuchung der Bibliothek ist, da"s in den
C++-Deklarationsdateien ({\it header files}) die Schl"usselworte {\sf public},
{\sf protected} und {\sf private} mehrfach auftreten d"urfen. Leider verzichtet
C++ hier auf die "Ubersichtlichkeit der Sprache TooL, die entsprechende
Schl"usselworte nur einmal zul"a"st.

\vspace{3mm}
\noindent {\bf "Ubersichtlichkeit der Bibliothek}\newline

\noindent In den Kapiteln \ref{SoftBibs} und \ref{ObjBib} wurden als Ziele des
Entwurfs einer klassenorientierten Softwarebibliothek "Ubersichtlichkeit und
Verst"andlichkeit besonders betont. Bibliotheken sollten danach durch ihr
Angebot einer Hierarchie von Klasse dem Benutzer ein einfache Sicht auch auf
die Schnittstellen der komplizierteren Klassen erlauben.

Verst"andlichkeit und "Ubersichtlichkeit einer Bibliothek setzen beispielsweise
voraus, da"s die Eigenschaften der Klasse in der Bibliothek in einer klar
gegliederten Form durch Spezialisierung entwickelt sind. Nur wenn diese
Bedingung erf"ullt ist, kann de Benutzer durch ein Absteigen in der
Vererbungshierarchie eine Klasse mit den gew"unschten Eigenschaften finden.
Um zu "uberpr"ufen, wie weit die vorliegende Bibliothek dieses Ziel erreicht,
zeigt Abbildung \ref{nihcl-Kategorisierung}, in welche Kategorien man die
Klassen der NIHCL einteilen kann. Bei der Betrachtung wird deutlich, da"s die
Gliederung der Bibliothek dem Benutzer an vielen Stellen nur geringe
Hilfestellungen anbietet.

Zwischen den unterhalb der Klasse {\sf Collection} liegenden Klassen {\sf
ArrayChar, ArrayOb} und {\sf SeqCltn} kann der Benutzer auf den ersten Blick
keine Unterscheidung feststellen. Alle 3 Klassen greifen mit Hilfe von Indizes
auf die Elemente der Klasse zu. Ung"unstig scheint auch die Unterscheidung
unterhalb der {\sf SeqCltn}, da hier auf den unterschiedlichen Elementtyp ({\sf
Link} bzw. {\sf Object}) zwischen {\sf LinkedList} auf der einen und {\sf
Stack} bzw. {\sf OrderedCltn} auf der anderen Seite abgestellt wird. Eine
ebensolche Unterscheidung nach dem Elementtyp erfolgt auch zwischen {\sf
IdentSet} und {\sf IdentDict}.

\renewcommand{\epsfsize}[2]{1.0#1}
\begin{figure}[hbt]
\begin{center} 
\leavevmode
\epsfxsize=14cm
\epsffile{../Bilder/thorsten/Postscript/NIHCL-Kategorisierung.ps}
\end{center}
\caption{Kategorisierung der Klassen in NIHCL}  \label{nihcl-Kategorisierung}
\end{figure}

\vspace{3mm}
\noindent {\bf Einfache Sicht auf komplexe Schnittstellen} \newline

\noindent Auff"allig ist der Verzicht auf die Verwendung der von der Sprache
angebotenen Mehrfachvererbung. In Anlehnung an die Smalltalk-Bibliothek, das
Vorbild von NIHCL, wurde NIHCL als Klassenbaum realisiert. Jede Klasse aus der
Bibliothek hat also genau einen Vorg"anger.

Um den Grad der Wiederverwendung innerhalb der Bibliothek zu erh"ohen,
liegt es nahe, Methoden so dicht wie m"oglich an der Wurzel des
Klassenbaums zu implementieren. Allerdings st"o"st diese Vorgehensweise auch
schnell auf ein Problem. Die Summe der "offentlichen Methoden eines Objekts
bestimmt n"amlich gerade die Eigenschaften eines Objekts. Die Eigenschaften
eines Objekts sind also untrennbar mit der Funktionalit"at verbunden.
Eine Implementierung dicht an der Wurzel eines Klassenbaums 
bedeutet also gleichzeitig eine fr"uhzeitige Festlegung der
Eigenschaften der darunter liegenden Klassen. 

Gerade in dieser fr"uhzeitigen Festlegung von Eigenschaften liegt das
Problem beim Design einer Bibliothek aus erbenden Klassen. Durch den
Verzicht auf die Verwendung von Mehrfachvererbung wird dieses Problem
noch versch"arft. Je fr"uher eine Eigenschaft in der Hierarchie f"ur
alle erbenden Klassen festgelegt wird, um so gr"o"ser ist die Gefahr,
bei der Realisierung erbender Klassen mit dieser dann geerbten Eigenschaft in
Konflikt zu geraten. 

Oft zeigt sich dann bei der Entwicklung speziellerer Klassen im
fortgeschrittenen Stadium der Bibliotheksentwicklung, da"s "offentliche
Methoden geerbt werden, die nicht mehr zu den geplanten Eigenschaften der
tieferliegenden Klassen passen. In der Bibliothek NIHCL ist dies in zahlreichen
Klassen zu beobachten. Es handelt sich dabei um folgende bereits
besprochenen (1.) bzw. hier nicht beschriebene Klassen (2.):
\begin{itemize}
\item[1. ] {\sf Set, Arraychar, Array\underline{  }c.m4 und Array\underline{
}h.m4} (Schablonen f"ur Felder), {\sf ArrayOb, Bag, LinkedList, SortedCltn,
Dictionary} und {\sf Stack} 
\item[2. ] {\sf Iterator, Nil, Random, Range, Rectangle, Regex, BitBoard,
Bitset, Class, FDSet} und {\sf Heap}
\end{itemize}
Alle diese Klassen erben "offentliche Methoden, die im Widerspruch zu ihren
Eigenschaften stehen. Abbildung \ref{nihcl-ShouldNotImplement} zeigt, an
welchen Stellen in der Bibliothek geerbte "offentliche Methoden mit den
Eigenschaften der Klasse kollidieren. 

\renewcommand{\epsfsize}[2]{1.0#1}
\begin{figure}[hbt]
\begin{center} 
\leavevmode
\epsfxsize=14cm
\epsffile{../Bilder/thorsten/Postscript/NIHCL-ShouldNotImplement.ps}
\end{center}
\caption{Verstecken geerbter Methoden in NIHCL} \label{nihcl-ShouldNotImplement}
\end{figure}

Nicht mehr "`passende"' geerbte "offentliche Methode k"onnen in C++ durch
Redefinition in eine private Methode umgewandelt und dadurch aus der
Schnittstelle der betreffenden Klasse entfernt werden. 
Es ist jedoch nicht unbedenklich, beim Design einer Klassenbibliothek
von diesem Werkzeug Gebrauch zu machen. Es zeigt sich ein Zielkonflikt
zwischen den beiden Zielen der klassenorientierten
Bibliotheksentwicklung, der Erh"ohung der Wiederverwendung und der
gew"unschten gemeinsamen einfachen Schnittstelle f"ur Objekte erbender
Klassen:
\begin{itemize}
\item Einerseits bietet die M"oglichkeit der nachtr"aglichen
Einordnung als private Methode den Vorteil, auch Klassen beerben zu k"onnen,
deren Eigenschaften nicht vollst"andig zu denen der erbenden Klasse passen,
was die  Wiederverwendung auch an dieser Stelle der Bibliothek erm"oglicht. 
\item Andererseits verliert der Benutzer der Bibliothek die gemeinsame
Schnittstelle f"ur verschiedene kompliziertere Objekte. Eine
gemeinsame Sicht auf Objekte verschiedener Klassen ist nur gegeben,
wenn der Benutzer bei der Verwendung einer Klasse darauf vertrauen
kann, auch alle "offentlichen Methoden der dar"uber liegenden
Oberklassen aufrufen zu k"onnen. In NIHCL kann der Benutzer sich
angesichts der massiven Verwendung des "`Versteckens"' von geerbten
Methoden aber gerade nicht mehr auf die Anwendbarkeit einer Methode
aus einer Oberklasse verlassen. Der Benutzer mu"s sich vor der
geplanten Verwendung einer Methode einer Oberklasse vergewissern,
da"s diese Methode nicht auf dem Weg des Vererbungsgraphen von der
einf"uhrenden Klasse zur aktuellen Klasse "`versteckt"' wurde. 
\end{itemize}
Die Sprache TooL bietet keine M"oglichkeit, geerbte "offentliche Methoden in
private umzuwandeln. Geerbte Funktionalit"at bleibt damit auch immer
Bestandteil der Schnittstelle einer erbenden Klasse. 
Durch diese Eigenschaft erzwingt TooL eine Gleichrangigkeit der Ziele
"`Wiederverwendung"' und "`gemeinsame Schnittstelle f"ur Objekte
verschiedener Klassen"'. Die Bibliothek NIHCL lie"se sich in TooL
nicht implementieren. Dies zeigt, wie stark die Auswirkungen des
Sprach-Designs auf das Design und den Stil einer in dieser Sprache
verwirklichten klassenorientierten Softwarebibliothek sind. 

