Technische Universität München Fakultät für Informatik Lehrstuhl IV: Software & Systems Engineering Markus Pister, Dr. Bernhard Rumpe WS 2002/2003 Lösungsblatt 14 28. Januar 2003 www4.in.tum.de/~rumpe/se Übungen zur Softwaretechnik Aufgabe 30 : Persistente Objekte a) Speichern von Objekten Zu den Objekten sollte eine ObjektID gespeichert werden, um diese in den Tabellen eindeutig identifizieren zu können. Spiel Spiel_ID Ort Datum Gegner b) Assoziationen mit mindestens einem nicht-mengenwertigen Ende Assoziationen, die mindestens ein nicht-mengenwertiges Ende besitzen, können auf zwei Weisen umgesetzt werden. Einerseits kann eine eigene Tabelle eingerichtet werden, die die Assoziation als Relation speichert, also Tupel bestehend aus Spiel_ID und Liga_ID enthält. Andererseits kann die Assoziation in der Tabelle der Klasse an dem mengenwertigen Ende der Assoziation festgehalten werden. Dazu muss lediglich eine Spalte mit der ID des gegenüberliegenden Objekts eingerichtet werden. In dem gegebenen Beispiel sähen die Tabellen folgendermaßen aus: Spiel Spiel_ID Ort Datum Gegner Liga_ID Die Navigationsrichtung der Assoziationen spielt bei der Erstellung der Tabellenstruktur keine Rolle, denn diese Information ist statisch im Klassendiagramm gespeichert und kann so jederzeit rekonstruiert werden. c) Mengenwertige Assoziationen Bei rein mengenwertigen Assoziationen ist es sinnvoll, eine eigene Tabelle anzulegen, die die Assoziation als Relation speichert. Es gibt auch andere Möglichkeiten, die aber meistens wesentlich aufwändiger sind. Die Tabellenstruktur könnte folgendermaßen aussehen: Spiel Spiel_ID Ort Datum Gegner Spiel_Liga Spiel_ID Liga_ID Seite 1 von 5
d) Vererbung Bei der Assoziation im Klassendiagramm ist nicht angegeben, welche Kardinalität gültig ist. Normalerweise müsste hier eine Rücksprache mit dem Kunden stattfinden. Wir gehen hier von einer 1:1 Assoziation aus. Die Vererbung kann auf drei Weisen realisiert werden: Tabelle für jede Klasse Spieler Rolle_ID Antritt_stärke Berater Rolle_ID erfahrung Rolle Rolle_ID Einfluss Der Nachteil dieser Umsetzung liegt darin, dass es viele Tabellen gibt, und dementsprechend Zugriffe auf diese komplexer sind. Der Vorteil ist, dass Anpassungen im Klassendiagramm einfach übernommen werden können, da jedes Element explizit durch eine Tabelle repräsentiert wird. Tabelle für jede konkrete Klasse Spieler Rolle_ID Antritt_stärke Einfluss Berater Rolle_ID erfahrung Einfluss Der Vorteil dieser Methode ist, dass die Daten eines Objektes einfach ausgelesen werden können. Änderungen in der Klassendeklaration der Oberklasse müssen aber in mehreren Tabellen nachgezogen werden. Eine Tabelle für alle Klassen Rolle Rolle_ID Art Einfluss Antritt_stärke erfahrung Bei dieser Methode hat gibt es keinen Datensatz, der nicht ein Null-Feld enthält. Diese Tabellen sind schwer zu handhaben, da nur aus den Daten geschlossen werden kann, ob der Datensatz ein Objekt der Klasse Spieler oder Berater beschreibt. Aufgabe 31 : OCL a) Wertebeschränkung(1) context Student inv: self.semester <= 16 Seite 2 von 5
b) Wertbeschränkung (2) (self.bereich >= 0) && (self.bereich <= 2) c) Auflösen von qualifizierten Assoziationen context Dozent inv: (forall v in self.prüft[1000].vorlesung:!(exists w in self.prüft[500].vorlesung: v == w)) && (forall v in self.prüft[1000].vorlesung:!(exists w in self.prüft[123].vorlesung: v == w)) && (forall v in self.prüft[500].vorlesung:!(exists w in self.prüft[123].vorlesung: v == w)) Es gibt auch andere effizientere Möglichkeiten, diese Bedingung auszudrücken. Die hier gegebene Lösung ist nur ein Vorschlag. d) Einteilung context Student inv: (exists v in self.vorlesung: v.bereich == 0) && (exists v in self.vorlesung: v.bereich == 1) && (exists v in self.vorlesung: v.bereich == 2) && (self.vorlesung->size == 3) Auch diese Bedingung lässt sich auf verschiedenste und evtl. einfachere Weisen ausdrücken. e) Eindeutigkeit forall Vorlesung v: forall Vorlesung w: (( v == w) ((v!= w) && (v.titel!= w.titel))) Alternatives Constraint mit gleicher Aussage: forall Vorlesung v: forall Vorlesung w: ((w.titel == v.titel) implies (w == v)) f) Mindesangabe self.student.prüft->size > 0 Seite 3 von 5
Aufgabe 32 : Kontrollflussdiagramme a) Zeichnen des Diagramms 1 2 7 3 4 5 6 b) Anweisungsüberdeckung Um eine Anweisungsüberdeckung zu erhalten, müssen alle Anweisungen einmal aufgerufen werden, also im Kontrollflussdiagramm alle Knoten einmal besucht werden. Eine Beispieleingabe, die Anweisungsüberdeckung erreicht, wäre: Die Anweisungsfolge wäre dann: 1-2-3-4-5-6-3-7 c) Zweigüberdeckung Um eine Zweigüberdeckung zu erhalten, müssen alle Ablaufzweige einmal beschritten worden sein, also im Kontrollflussdiagramm alle Kannten einmal besucht worden sein. In Teil b) der Aufgabe wurde der Zweig 4-6 nicht besucht. Die kann erreicht werden, indem neben der Eingabe aus Teil b) zusätzlich folgende Eingabe gemacht wird: Die Anweisungsfolge ist hier: 1-2-3-4-6-3-7 Somit sind zusammen mit b) alle Zweige überdeckt. Seite 4 von 5
ANMERKUNG: For-Schleifen spalten auch neue Zweige auf. Eine for-schleife besteht aus drei Anweisungen, für die jeweils ein Knoten im Kontrollflussgraphen gemacht werden sollte:! "# $ % & ' ( ( ) $ $ * +++ Seite 5 von 5