Grundlagen der Informatik I “Programmierung”

Grundlagen der Informatik I “Programmierung” Grundlagen der Informatik I “Programmierung”

22.08.2013 Aufrufe

Viel sinnvoller ist es, bei der Beschreibung einer Klasse noch nicht an die konkrete Implementierung zu denken sondern eine möglichst abstrakte Beschreibung derjenigen Informationen zu geben, die wirklich von Interesse sind. Die Klasse der Autoren, zum Beispiel, soll uns Namen, Vornamen, Nationalität, Geburts- und Todesjahr – falls vorhanden – liefern und umgekehrt zulassen, daß das Todesjahr nachgetragen wird. Alle anderen Informationen dürfen dagegen nicht verändert werden – namensrechtliche Probleme bei Heirat seien außer Acht gelassen. Wir stehen also vor der Aufgabe, einerseits eine vollständige, genaue und eindeutige Beschreibung einer Klasse von Objekten zu geben, gleichzeitig aber eine Überspezifikation zu vermeiden. Die Antwort auf dieses Problem liegt in der Theorie der abstrakten Datentypen. 3.2.1 Abstrakte Datentypen Ausgangspunkt der Theorie der abstrakten Datentypen ist die Feststellung, daß für ein Softwaresystem, welches die Objekte einer bestimmten Klasse benutzt, weniger die konkrete Realisierung relevant ist, als die Art der Dienstleistungen, welche es bietet. So bietet zum Beispiel die Klasse der Autoren an, Namen, Vornamen, Nationalität, Geburts- und Todesjahr, und ggf. auch das Alter eines Autors abzufragen und das Todesjahr zu verändern. Wie diese Dienste realisiert werden – also ob z.B. das Alter des Autors berechnet oder gespeichert wird – ist ziemlich unbedeutend. Wichtig ist dagegen, daß diese Dienstleistungen gewisse Eigenschaften erfüllen, auf die sich das System verlassen darf, wie zum Beispiel, daß das Alter eines Autors eine ganze Zahl ist, die größer als Null ist (wahrscheinlich wäre 8 sinnvoller, aber man kann ja nie wissen). Eine abstrakte Datentypspezifikation beschreibt daher eine Klasse nicht durch die konkrete Realisierung sondern durch eine Liste von Dienstleistungen, die für die Außenwelt verfügbar sein sollen, und durch die Eigenschaften dieser Dienstleistungen. 4 Auf diese Art wird sichergestellt, daß die Außenwelt auf die Objekte einer Klasse nur mithilfe der bekanntgegebenen Dienstleistungen zugreifen kann und nicht etwa über die Implementierung(, welche sich ja möglicherweise ändern kann). Durch diese Form der Datenkapselung wird sichergestellt, daß sich jede Komponente eines Softwaresystems ausschließlich um ihre eigenen Geschäfte kümmert und in die Aufgaben der anderen nicht hineinpfuscht. Nur dieses Geheimnisprinzip garantiert die Integrität eines Moduls in einer Umwelt ständiger Veränderungen. Für eine vollständige formale Spezifikation eines abstrakten Datentyps sind vier Fragen zu beantworten: • Welche Typen werden eingeführt? • Welche Funktionen (Dienstleistungen) werden eingeführt? • Was sind die Vorbedingungen für die Anwendbarkeit der Funktionen? • Welche Axiome (Eigenschaften) erfüllen die Funktionen? Typen und Funktionen beschreiben die Syntax des abstrakten Datentyps, Vorbedingungen und Axiome seine Semantik. Diese Beschreibung wird in einer rein mathematischen Form gegeben, um die gewünschte Genauigkeit und Eindeutigkeit sicherzustellen. Wir wollen die Bedeutung dieser vier Teile am Beispiel der vollständigen Spezifikation endlicher Listen (vgl. Abschnitt 2.3.5) illustrieren. Eine Liste wird als Struktur betrachtet, die folgende Dienste zur Verfügung stellt: trage ein neues Element ein (cons), greife auf das erste Element zu (head), entferne das erste Element (tail), prüfe ob die Liste leer ist (empty), erzeuge eine neue Liste (new), usw. Listen und ihre Dienstleistungen werden in sehr vielen Anwendungen benötigt und können auf viele verschiedene Arten implementiert werden, je nachdem, ob über die obengenannte Dienstleistungen hinaus noch weitere Dienstleistungen wie z.B. das Zusammensetzen von Listen (& in Abschnitt 2.3) angeboten werden sollen oder nicht. 4 Anstelle von “Dienste” sagt man auch “Operationen” oder “Merkmale” (in Englisch “features”).

Die vollständige Spezifikation endlicher Listen ist in Abbildung 3.4 zusammengefaßt. Sie drückt alles aus, was für den Begriff der Liste von allgemeiner Bedeutung ist und läßt alles weg, was nur für bestimmte Repräsentationen von Listen gilt. TYPES: List[X] FUNCTIONS: empty: List[X] → BOOLEAN new: → List[X] cons: X×List[X] → List[X] head: List[X] → X tail: List[X] → List[X] PRECONDITIONS: pre head(L:List[X]) = (not empty(L)) AXIOMS: ∀x:X . ∀L:List[X] . empty(new()) not empty(cons(x,L)) head(cons(x,L)) = x tail(cons(x,L)) = L tail(new()) = new() Abbildung 3.4: Listen als abstrakter Datentyp • Die Namen der neuen Datentypen werden in einem Abschnitt TYPES der Spezifikation aufgelistet. Es kann sinnvoll sein, mehrere Datentypen zusammen zu spezifizieren. In unserem Fall kommt allerdings nur ein neuer Datentyp hinzu, die Liste. Dieser Typ wird eingeführt unter dem Namen “List[X]”. Das bedeutet, das es sich um einen parametrisierten oder generischen Datentyp handelt mit einem Parameter X, der einen beliebigen Datentyp darstellt, über dessen Elementen die Listen gebildet werden. 5 Die restliche Spezifikation beschreibt nun die Eigenschaften des Typs List[X], der mathematisch als Menge von Objekten (d.h. Listen) angesehen wird. • In einem Abschnitt FUNCTIONS sind die Namen der Dienstleistungen aufgeführt, die von den Exemplaren des soeben genannten Typs zur Verfügung gestellt werden. Diese werden einheitlich als mathematische Funktionen empty, new, cons, head, tail beschrieben. Zu jeder Funktion wird ihre Funktionalität (vgl. Abschnitt 2.1.3 – auch “Signatur” genannt) angegeben, in welcher der spezifizierte neue Datentyp mindestens einmal vorkommen muß. So wird zum Beispiel die Dienstleistung cons als Funktion spezifiziert, die ein Element von X und eine Liste aus List[X] in eine neue Liste abbildet: cons: X×List[X] → List[X] Die beabsichtigte Wirkung von cons, nämlich daß das Element vor die Liste gehängt werden soll, gehört zu den Eigenschaften des abstrakten Datentyps und wird im Abschnitt AXIOMS mathematisch beschrieben. Dabei interessiert sich die mathematische Beschreibung ausschließlich für das Ergebnis der Funktion, da nur auf diese Art eine präzise und überschaubare Formulierung von Eigenschaften der Dienstleistungen möglich ist. Eventuelle Seiteneffekte der Operation cons, wie zum Beispiel, daß cons in den meisten Implementierungen einem konkreten Objekt das berechnete Ergebnis zuweist, spielen hier keine Rolle. Sie sollten erst in der letzten Phase der Implementierung, nicht aber in der Spezifikation eingeführt werden. 5 Durch die Verwendung generischer Datentypen kann man sich ersparen, getrennte Spezifikationen für Listen von ganzen Zahlen, Buchstaben, oder komplexeren Datensätzen schreiben zu müssen, obwohl diese jeweils nur dieselben Dienstleistungen anbieten würden. Listen über ganzen Zahlen erhält man, indem man für X den Typ INTEGER einsetzt, also “List[INTEGER]” schreibt. Generische Datentypen werden wir in Abschnitt 3.6 ausführlicher besprechen.

Die vollständige Spezifikation endlicher Listen ist in Abbildung 3.4 zusammengefaßt. Sie drückt alles aus,<br />

was für den Begriff <strong>der</strong> Liste von allgemeiner Bedeutung ist und läßt alles weg, was nur für bestimmte<br />

Repräsentationen von Listen gilt.<br />

TYPES: List[X]<br />

FUNCTIONS: empty: List[X] → BOOLEAN<br />

new: → List[X]<br />

cons: X×List[X] → List[X]<br />

head: List[X] → X<br />

tail: List[X] → List[X]<br />

PRECONDITIONS: pre head(L:List[X]) = (not empty(L))<br />

AXIOMS: ∀x:X . ∀L:List[X] .<br />

empty(new())<br />

not empty(cons(x,L))<br />

head(cons(x,L)) = x<br />

tail(cons(x,L)) = L<br />

tail(new()) = new()<br />

Abbildung 3.4: Listen als abstrakter Datentyp<br />

• Die Namen <strong>der</strong> neuen Datentypen werden in einem Abschnitt TYPES <strong>der</strong> Spezifikation aufgelistet. Es<br />

kann sinnvoll sein, mehrere Datentypen zusammen zu spezifizieren. In unserem Fall kommt allerdings<br />

nur ein neuer Datentyp hinzu, die Liste. Dieser Typ wird eingeführt unter dem Namen “List[X]”. Das<br />

bedeutet, das es sich um einen parametrisierten o<strong>der</strong> generischen Datentyp handelt mit einem Parameter<br />

X, <strong>der</strong> einen beliebigen Datentyp darstellt, über dessen Elementen die Listen gebildet werden. 5<br />

Die restliche Spezifikation beschreibt nun die Eigenschaften des Typs List[X], <strong>der</strong> mathematisch als<br />

Menge von Objekten (d.h. Listen) angesehen wird.<br />

• In einem Abschnitt FUNCTIONS sind die Namen <strong>der</strong> Dienstleistungen aufgeführt, die von den Exemplaren<br />

des soeben genannten Typs zur Verfügung gestellt werden. Diese werden einheitlich als mathematische<br />

Funktionen empty, new, cons, head, tail beschrieben. Zu je<strong>der</strong> Funktion wird ihre Funktionalität<br />

(vgl. Abschnitt 2.1.3 – auch “Signatur” genannt) angegeben, in welcher <strong>der</strong> spezifizierte neue<br />

Datentyp mindestens einmal vorkommen muß.<br />

So wird zum Beispiel die Dienstleistung cons als Funktion spezifiziert, die ein Element von X und eine<br />

Liste aus List[X] in eine neue Liste abbildet:<br />

cons: X×List[X] → List[X]<br />

Die beabsichtigte Wirkung von cons, nämlich daß das Element vor die Liste gehängt werden soll,<br />

gehört zu den Eigenschaften des abstrakten Datentyps und wird im Abschnitt AXIOMS mathematisch<br />

beschrieben. Dabei interessiert sich die mathematische Beschreibung ausschließlich für das Ergebnis <strong>der</strong><br />

Funktion, da nur auf diese Art eine präzise und überschaubare Formulierung von Eigenschaften <strong>der</strong><br />

Dienstleistungen möglich ist. Eventuelle Seiteneffekte <strong>der</strong> Operation cons, wie zum Beispiel, daß cons<br />

in den meisten Implementierungen einem konkreten Objekt das berechnete Ergebnis zuweist, spielen hier<br />

keine Rolle. Sie sollten erst in <strong>der</strong> letzten Phase <strong>der</strong> Implementierung, nicht aber in <strong>der</strong> Spezifikation<br />

eingeführt werden.<br />

5 Durch die Verwendung generischer Datentypen kann man sich ersparen, getrennte Spezifikationen für Listen von ganzen<br />

Zahlen, Buchstaben, o<strong>der</strong> komplexeren Datensätzen schreiben zu müssen, obwohl diese jeweils nur dieselben Dienstleistungen<br />

anbieten würden. Listen über ganzen Zahlen erhält man, indem man für X den Typ INTEGER einsetzt, also “List[INTEGER]”<br />

schreibt. Generische Datentypen werden wir in Abschnitt 3.6 ausführlicher besprechen.

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!