Kapitel 4.1 - Abbildung von UML-Modellen auf Code



Ähnliche Dokumente
Software Engineering Klassendiagramme Assoziationen

Verhindert, dass eine Methode überschrieben wird. public final int holekontostand() {...} public final class Girokonto extends Konto {...

Java: Vererbung. Teil 3: super()

Einführung in die Programmierung

Vorkurs C++ Programmierung

Binäre Bäume. 1. Allgemeines. 2. Funktionsweise. 2.1 Eintragen

Objektorientierte Programmierung

5. Abstrakte Klassen. Beispiel (3) Abstrakte Klasse. Beispiel (2) Angenommen, wir wollen die folgende Klassenhierarchie implementieren:

Programmieren in Java

Typumwandlungen bei Referenztypen

Java Einführung Umsetzung von Beziehungen zwischen Klassen. Kapitel 7

Objektorientierte Programmierung für Anfänger am Beispiel PHP

Objektbasierte Entwicklung

Prinzipien Objektorientierter Programmierung

Objektorientierte Programmierung

Programmiersprache 2 (C++) Prof. Dr. Stefan Enderle NTA Isny

Übungen zur Softwaretechnik

Java Kurs für Anfänger Einheit 4 Klassen und Objekte

Wintersemester Maschinenbau und Kunststofftechnik. Informatik. Tobias Wolf Seite 1 von 22

Grundlagen von Python

5. Abstrakte Klassen

Java Kurs für Anfänger Einheit 5 Methoden

Software Engineering Klassendiagramme Einführung

Objektorientierte Programmierung. Kapitel 12: Interfaces

Fachdidaktik der Informatik Jörg Depner, Kathrin Gaißer

Software Engineering Interaktionsdiagramme

Fakultät Angewandte Informatik Lehrprofessur für Informatik

Einführung in die objektorientierte Programmierung mit Java. Klausur am 19. Oktober 2005

II. Grundlagen der Programmierung. 9. Datenstrukturen. Daten zusammenfassen. In Java (Forts.): In Java:

Vererbung & Schnittstellen in C#

Objektorientierte Programmierung OOP

Musterlösung zur Vorlesung Modellbasierte Softwareentwicklung Wintersemester 2014/2015 Übungsblatt 9

3 Objektorientierte Konzepte in Java

Große Übung Praktische Informatik 1

Assoziation und Aggregation

Übungen zu Einführung in die Informatik: Programmierung und Software-Entwicklung: Lösungsvorschlag

Grundbegriffe der Informatik

Kapitel 6. Vererbung

Folge 18 - Vererbung

Fachgebiet Informationssysteme Prof. Dr.-Ing. N. Fuhr. Programmierung Prof. Dr.-Ing. Nobert Fuhr. Übungsblatt Nr. 6

Probeklausur Softwareengineering SS 15

Klausur zur Einführung in die objektorientierte Programmierung mit Java

Ordner Berechtigung vergeben Zugriffsrechte unter Windows einrichten

Würfelt man dabei je genau 10 - mal eine 1, 2, 3, 4, 5 und 6, so beträgt die Anzahl. der verschiedenen Reihenfolgen, in denen man dies tun kann, 60!.

Kleines Handbuch zur Fotogalerie der Pixel AG

PeDaS Personal Data Safe. - Bedienungsanleitung -

Fachbericht zum Thema: Anforderungen an ein Datenbanksystem

Programmieren I. Strategie zum Entwurf von Klassen. Beispiele. Design von Klassen. Dr. Klaus Höppner. Beispiel: Bibliothek

Bedienung von BlueJ. Klassenanzeige

MCRServlet Table of contents

Einführung in die Informatik Tools

Benutzeranleitung Superadmin Tool

Kapitel 6. Vererbung

Seite 1 von 14. Cookie-Einstellungen verschiedener Browser

Klassendiagramm. Kurzer Überblick über UML - Stand BlaBla

Abschnitt 9: Schnittstellen: Interfaces

1. Man schreibe die folgenden Aussagen jeweils in einen normalen Satz um. Zum Beispiel kann man die Aussage:

Kapitel 6. Vererbung

Einführung in die Programmierung

Jederzeit Ordnung halten

Leichte-Sprache-Bilder

1. Bearbeite Host Netzgruppen

Einführung in die Java- Programmierung

SEP 114. Design by Contract

Über die Internetseite Hier werden unter Download/aktuelle Versionen die verschiedenen Module als zip-dateien bereitgestellt.

Systeme 1. Kapitel 6. Nebenläufigkeit und wechselseitiger Ausschluss

Professionelle Seminare im Bereich MS-Office

SWE5 Übungen zu Software-Engineering

4. AuD Tafelübung T-C3

EinfÅhrung in die objektorientiere Programmierung (OOP) unter Delphi 6.0. EDV Kurs 13/2

Einführung in die Java- Programmierung

Das große ElterngeldPlus 1x1. Alles über das ElterngeldPlus. Wer kann ElterngeldPlus beantragen? ElterngeldPlus verstehen ein paar einleitende Fakten

Arbeiten mit UMLed und Delphi

How to do? Projekte - Zeiterfassung

Drei-Schichten-Architektur. Informatik B - Objektorientierte Programmierung in Java. Vorlesung 16: 3-Schichten-Architektur 1 Fachkonzept - GUI

Programmieren Tutorium

7. Objektorientierte Softwareentwicklung/3. Informatik II für Verkehrsingenieure

ecaros2 - Accountmanager

INDEX. Öffentliche Ordner erstellen Seite 2. Offline verfügbar einrichten Seite 3. Berechtigungen setzen Seite 7. Öffentliche Ordner Offline

Es sollte die MS-DOS Eingabeaufforderung starten. Geben Sie nun den Befehl javac ein.

Daniel Warneke Ein Vortrag im Rahmen des Proseminars Software Pioneers

Dieses Tutorial gibt eine Übersicht der Form Klassen von Struts, welche Besonderheiten und Unterschiede diese aufweisen.

Softwaretests in Visual Studio 2010 Ultimate Vergleich mit Java-Testwerkzeugen. Alexander Schunk Marcel Teuber Henry Trobisch

Kapitel 4 Die Datenbank Kuchenbestellung Seite 1

Sichtbarkeit & statische Methoden. Einsatz von Sichtbarkeit Einsatz statischer Methoden programmatische Realisierung 2 Beispielaufgaben

Bedienungsanleitung für den Online-Shop

Software Engineering. Zur Architektur der Applikation Data Repository. Franz-Josef Elmer, Universität Basel, HS 2015

Was meinen die Leute eigentlich mit: Grexit?

ARCO Software - Anleitung zur Umstellung der MWSt

Von der UML nach C++

Umzug der abfallwirtschaftlichen Nummern /Kündigung

5.2 Neue Projekte erstellen

SJ OFFICE - Update 3.0

Hinweise zur Benutzung des Programms zur Berechnung der Abiturendnote

Beschreibung Regeln z.b. Abwesenheitsmeldung und Weiterleitung

AGROPLUS Buchhaltung. Daten-Server und Sicherheitskopie. Version vom b

Second Steps in eport 2.0 So ordern Sie Credits und Berichte

Folge 19 - Bäume Binärbäume - Allgemeines. Grundlagen: Ulrich Helmich: Informatik 2 mit BlueJ - Ein Kurs für die Stufe 12

.NET Code schützen. Projekt.NET. Version 1.0

Datenbank-Verschlüsselung mit DbDefence und Webanwendungen.

Transkript:

SWT I Sommersemester 2010 Walter F. Tichy, Andreas Höfer, Korbinian Molitorisz IPD Tichy, Fakultät für Informatik KIT die Kooperation von Forschungszentrum Karlsruhe GmbH und Universität Karlsruhe (TH)

Literatur Diese Vorlesung orientiert sich an Abschnitt 10.4.2 aus B. Bruegge, A.H. Dutoit, Object-Oriented Software Engineering: Using UML, Patterns and Java, Pearson Prentice Hall, 2004. Lesen! 2

Kapitel 4.1.1 - Abbildung von Klassendiagrammen IPD Tichy, Fakultät für Informatik KIT die Kooperation von Forschungszentrum Karlsruhe GmbH und Universität Karlsruhe (TH)

Abbildung von Klassen: oo-sprachen Bei oo-sprachen wird jede UML-Klasse auf eine Klasse in der Programmiersprache abgebildet (einschließlich Attributen und Methoden). class C { /* Attribute */ /* Methoden */ ; 4

Abbildung von Klassen: nicht oo-sprachen (1) Falls keine oo-sprache zur Verfügung steht, wird eine Klasse auf einen Verbund (record, structure) abgebildet; dieser enthält aber nur die Attribute. Für die Sprache C: struct C { int a1; /* Attribute */ ; struct C c1, c2, c3; /* Instanzen */ Der Zugriff auf das Attribut a1 der Instanz c3 geschieht folgendermaßen: c3.a1 5

Abbildung von Klassen: nicht oo-sprachen (2) Alternativ mit Typdefinition in C: typedef struct {int a1; /* Attribute */ C; C c1, c2, c3; /* Instanzen */ Alternativ kann der Speicher für eine Instanz auch zur Laufzeit angefordert werden: C * c4; /* Referenz! */ c4 = (C*)malloc(sizeof(C)); malloc() liefert void zurück, daher die Typumwandlung (engl. cast) nicht vergessen! Bei Referenzen geschieht der Attributzugriff mit Operator ->: c4->a1 6

Abbildung von Klassen: nicht oo-sprachen (3) Methoden werden auf Unterprogramme abgebildet, die den Verbundtyp als zusätzlichen Referenz-Parameter enthalten. Methode m(parameter) { attribut wird zu freistehender Funktion m(c * objekt, parameter) { objekt->attribut Der Aufruf c4.m(parameter) wird zu m(c4,parameter) Vererbung wird simuliert, in dem die Attribute der Oberklasse(n) dem Verbund hinzugefügt werden. Polymorphie kann man, falls nötig, über Funktionszeiger und Typumwandlung des ersten Parameters simulieren. 7

Abbildung von Assoziationen Selbst oo-sprachen bieten keine Assoziationen, nur Referenzen. Letztere benutzt man, um die verschiedenen Arten von Assoziationen (uni-/bidirektional, Kardinalitäten) zu implementieren. 8

Unidirektionale Eins-zu-Eins-Assoziation Benutze in der Klasse, in der zur anderen navigiert wird, eine Instanzvariable, die eine Referenz zur anderen Klasse enthält. Person 1 Gehaltskonto Konto class Person { private Konto gehaltskonto; public Person() { gehaltskonto=new Konto(); public Konto gibgehaltskonto() { return gehaltskonto; Privatisierung von gehaltskonto und zugehörige Zugriffsmethode verhindern versehentliches Ändern der Assoziation. 9

Bidirektionale Eins-zu-Eins-Assoziation Benutze in beiden Klassen eine Instanzvariable, die eine Referenz zur anderen enthält. Person 1 1 Besitzer Gehaltskonto Achtung: echte 1:1-Beziehung bedeutet gegenseitige Abhängigkeit! 10

Bidirektionale Eins-zu-Eins Assoziation class Person { private Konto gehaltskonto; public Person() { gehaltskonto=new Konto(this); public Konto gibgehaltskonto() { return gehaltskonto; class Konto { private Person besitzer; public Konto(Person besitzer) { this.besitzer=besitzer; public Person gibbesitzer() { return besitzer; Hier Lösung für initiale Konsistenz: sorge dafür, dass keine null-werte bei der Initialisierung entstehen können 11

Bidirektionale Eins-zu-Eins Assoziation class Person { private Konto gehaltskonto; public Person() { gehaltskonto=new Konto(this); public Konto gibgehaltskonto() { return gehaltskonto; class Konto { private Person besitzer; public Konto(Person besitzer) { this.besitzer=besitzer; public Person gibbesitzer() { return besitzer; Hier Lösung für initiale Konsistenz: sorge dafür, dass keine null-werte bei der Initialisierung entstehen können Wenn wir zwar die Zusicherung 1:1 garantieren aber auch Änderung des Assoziationspartners zulassen wollen, wird der Code komplizierter:? 12

1:N-Assoziationen Vielfache Referenzen müssen durch mengenwertige Instanzvariablen ausgedrückt werden. Person * 0..1 Angestellter Firma 13

1:N-Assoziationen class Person { private Firma firma; public Person() { public void setzefirma(firma f) { if (f==firma) return; firma = f; firma.stelleein(this); public Firma gibfirma() { return firma; Endlosschleife verhindern class Firma { private Collection<Person> angestellte=new ArrayList<Person>(); public Firma() { public void stelleein(person p) { if (angestellte.contains(p)) return; angestellte.add(p); p.setzefirma(this); Referenz hinzufügen Dieser Code hat noch einen Fehler! Welchen? 14

M:N-Assoziation Bei n:m Assoziationen müssen zwei mengenwertige Attribute verwendet werden. Person * * Angestellter Firma class Person { private Collection<Firma> arbeitgeber; class Firma { private Collection<Person> angestellte; 15

M:N-Assoziation class Person { public void hinzufügearbeitgeber(firma f) { if (arbeitgeber.contains(f)) return; arbeitgeber.add(f); f.stelleein(this); Endlosschleife verhindern class Firma { public void stelleein(person p) { if (angestellte.contains(p)) return; angestellte.add(p); p.hinzufügearbeitgeber(this); 16

Zusammenfassung A 0..1 Instanzvariable vom Typ A auf der gegenüberliegenden Seite A A 1 Instanzvariable vom Typ A auf der gegenüberliegenden Seite + Code der sicherstellt, dass die Referenz niemals null ist * Instanzvariable vom Typ Vielfachmenge<A> auf der gegenüberliegenden Seite Grundsätzlich gilt für den Assoziationen manipulierenden Code: Assoziationen als Ganzes betrachten Immer beide Seiten anpassen Transaktional denken Synchronisierung in nebenläufigen Programmen beachten (hier weggelassen!) 17

Sonderfälle A A * {ordered * {unique Instanzvariable vom Typ Liste<A> (mit Reihenfolge) auf der Gegenseite, also z.b. ArrayList<A> oder Vector<A> Instanzvariable vom Typ Menge<A> auf der Gegenseite, also z.b. HashSet<A> oder TreeSet<A> A Qualifiz. * Instanzvariable vom Typ Abbildung<Objekt, B> also z.b. HashMap<Object, B> + Methoden für Zugriff über den Qualifizierer 18

Qualifizierte Assoziation 1 * Buch Signatur Bibliothek class Bibliothek { private Map<String,Buch> bücher; public void hinzufügebuch(string signatur, Buch b) { if (!bücher.containskey(signatur)) { bücher.put(signatur,b); b.hinzufügebibliothek(signatur,this); public Buch gibbuch(string signatur) { return bücher.get(signatur); Zugriff über Qualifizierer 19

Assoziationsklassen Realisierung durch Modelltransformation: Ergebnis +gibplatzierung() : int Sportler * * nimmtteil Wettkampf Sportler Ergebnis +gibplatzierung() : int * * 1 1 Wettkampf Code muss sicherstellen, dass sich die Realisierung der zwei Assoziationen so verhalten, als würde es sich um eine Assoziation mit zusätzlichen Attributen handeln 20

Kapitel 4.1.2 - Abbildung und Implementierung von Zustandsautomaten IPD Tichy, Fakultät für Informatik KIT die Kooperation von Forschungszentrum Karlsruhe GmbH und Universität Karlsruhe (TH)

Speicherung des Zustands eines Objektes Implizite Speicherung Der Zustand des Objektes kann aus den Attributwerten eines Exemplars berechnet werden Keine dedizierten Instanzvariablen nötig, der Zustand muss aber jedes Mal neu berechnet werden Zustandsübergangsfunktion ist ebenfalls implizit Explizite Speicherung Der Zustand eines Objektes wird in dedizierten Instanzvariablen gespeichert und kann daher einfach gelesen und neu gesetzt werden Die Zustandsübergangsfunktion muss ebenfalls explizit angegeben werden 22

Beispiel für implizite Speicherung des Zustands log(string) Instantiiert init(printstream) Initialisiert public class Logger { private PrintStream log; public void init(printstream dst) { log = dst; public void log(string msg) { Berechnung des aktuellen Zustands aus den Attributwerten if (log==null) throw new IllegalStateException(); log.append(msg); aus java.lang 23

Beispiel für explizite Speicherung des Zustands log(string) Instantiiert init(printstream) Initialisiert 24 public class Logger { private enum Zustand { instanziiert, initialisiert ; private Zustand zustand = Zustand.instanziiert; private PrintStream log; public void init(printstream dst) { log = dst; zustand = Zustand.initialisiert; public void log(string msg) { if (zustand!=zustand.initialisiert) throw new IllegalStateException(); log.append(msg); Explizite Speicherung des Zustands Zustand kann direkt ausgelesen werden

Vergleich implizite/explizite Speicherung des Zustands Die implizite Speicherung spart Speicherplatz, die explizite (potentiell) Rechenzeit. Die implizite Speicherung ist potentiell komplizierter (trickreicher), die explizite umfangreicher. Die explizite Speicherung ist immer offensichtlich und wird daher bei Änderungen wahrscheinlicher berücksichtigt. Die implizite Speicherung ist nicht immer möglich, die explizite schon. 25

Alternativen der Implementierung expliziter Speicherung der Zustände Eingebettet Jede Methode kennt den kompletten Automaten Sie führt ihre Aufgabe kontextsensitiv (=dem aktuellen Zustand entsprechend) durch und Nimmt die Verwaltung der Zustände selbst vor Vorteil: kompakter, schneller Ausgelagert Die Methode fragt den aktuellen Zustand, was zu tun ist Der Code zur Verwaltung der Zustände befindet sich in dedizierten (ggf. automatisch erzeugten) Klassen Vorteil: flexibler, bei komplexen Automaten übersichtlicher 26

Beispiel für eingebettete explizite Speicherung 27 public class XYZ { private enum Zustand{ X, Y, Z ; private Zustand zustand = Zustand.X; public void a() { if (zustand==zustand.y) throw new IllegalStateException(); if (zustand==zustand.z) throw new IllegalStateException(); //... mach was... zustand = Zustand.Z; Nächster Zustand: Z public void b() { if (zustand==zustand.y) throw new IllegalStateException(); //... mach was... zustand = Zustand.Y; public void c() { if (zustand==zustand.z) throw new IllegalStateException(); //... mach was... if (zustand==zustand.x) zustand = Zustand.Z; if (zustand==zustand.y) zustand = Zustand.X; X Z a,c Die Methode a() darf im Zustand Y und Z nicht aufgerufen werden Was ist, wenn hier etwas passieren soll, das vom gegenwärtigen Zustand abhängig ist? b b Der nächste Zustand ist vom vorhergehenden abhängig c Y Der mach was -Teil muss also auch noch in die if-blöcke rein!

Beispiel für eingebettete explizite Speicherung public void a() { if (zustand==zustand.x) { //... mach was... zustand = Zustand.Z; return; if (zustand==zustand.y) throw new IllegalStateException(); if (zustand==zustand.z) throw new IllegalStateException(); public void b() { if (zustand==zustand.x) { //... mach was... zustand = Zustand.Y; return; if (zustand==zustand.y) throw new IllegalStateException(); if (zustand==zustand.z) { //... mach was anderes... zustand = Zustand.Y; return; public void c() { if (zustand==zustand.x) { //... mach was... Zustand = Zustand.Z; return; if (zustand==zustand.y) { //... mach was anderes... Zustand = Zustand.X; return; if (zustand==zustand.z) throw new IllegalStateException(); X und die entry- und exit- Aktionen müssen da eigentlich auch noch überall rein! Z a,c b b c Y 28

Ausgelagerte explizite Speicherung (engl. state pattern) Idee: Das eigentliche Objekt weiß nicht was genau in welchem Zustand zu tun ist. Es kennt nur seinen Zustand Und delegiert das, was zu tun ist, wenn eine Botschaft eintrifft, an den jeweiligen Zustand. Vorteil: Die Kontextsensitivität (=Zustandsabhängigkeit) der Methoden braucht nicht mehr explizit verwaltet zu werden, statt dessen wird dynamische Polymorphie verwendet Die Implementierungsarbeit wird auf verschiedene Klassen (=verschiedene Dateien in Java) aufgeteilt Bessere Parallelisierbarkeit der Implementierungsarbeit separation of concerns 29

Vorgehensweise Zu jeder Klasse C, für deren Verhalten ein endlicher Automat implementiert werden soll, erzeuge eine abstrakte Oberklasse CZustand, die für alle Zustände von C steht: C C obj aktuell 1 1 CZustand +m1():void +m2():void +m3():void +m1():void +m2():void +m3():void #entry():void #exit():void #m1():void #m2():void #m3():void #zustandswechsel():void #nächster():czustand 30

Vorgehensweise Jeder Zustand, den die Klasse C einnehmen kann wird durch einen eigenen Typ repräsentiert Zustandsübergangsdiagramm der Klasse C: X Z m1,m3 m2 m2 m3 Y C +m1():void +m2():void +m3():void obj CZustandX #m1():void #m2():void #m3():void #nächster():czustand aktuell 1 1 CZustand #entry():void #exit():void #m1():void #m2():void #m3():void #zustandswechsel():void #nächster():czustand CZustandY #m3():void #nächster():czustand CZustandZ #m2():void #nächster():czustand 31

Vorgehensweise: Delegation Die Implementierung der Methoden m1, m2 und m3 in C wird delegiert: class C { protected CZustand aktuell; public void m1() { aktuell.m1(); // delegiere // Zustandsänderung // fehlt noch C +m1():void +m2():void +m3():void obj aktuell 1 1 CZustand #m1():void #m2():void #m3():void 32

Implementierung der Methoden der abstrakten Klasse CZustand Standardverhalten: Tue nichts beim entry- und exit- Ereignis ein konkreter Zustand braucht nur da Implementierungen angeben, wo er das auch will. protected void entry() { //leer protected void exit() { //leer 33

Implementierung der Methoden der abstrakten Klasse CZustand Standardverhalten: In diesem Zustand ist das Aufrufen dieser Methode unzulässig ein konkreter Zustand braucht nur da Implementierungen angeben, wo er das auch will. protected void m1() { throw new IllegalStateException(); protected void m2() { throw new IllegalStateException(); protected void m3() { throw new IllegalStateException(); 34

Implementierung der Methoden der abstrakten Klasse CZustand Die abstrakte Methode nächster() ist eine Einschubmethode, die angibt, welcher Zustand der nächste Zustand wäre. Sie nimmt keinen Zustandswechsel vor und wird als Einschubmethode auch nicht von außen aufgerufen! Die Methode ist abstrakt, so dass jeder Zustand seine eigene Implementierung angeben muss. protected abstract CZustand nächster(); 35

Implementierung der Methoden der abstrakten Klasse CZustand Die Methode zustandswechsel() ist eine Schablonenmethode, die ggf. einen Zustandswechsel vornimmt. Sie muss nach jedem Aufruf einer Methode von C aufgerufen werden: protected void zustandswechsel() { CZustand n = nächster(); if( n!= this ) { this.exit(); n.entry(); obj.aktuell = n; Aufruf der Einschubmethode 36

Vorgehensweise Die Implementierung der Methoden m1, m2 und m3 in C sieht also folgendermaßen aus: class C { protected CZustand aktuell; public void m1() { aktuell.m1(); aktuell.zustandswechsel(); 37

Beispiel Sei für die Klasse M unten stehender Automat definiert. Dann ist class M { protected MZustand aktuell = new MZustandX(this); public void a() { aktuell.a(); aktuell.zustandswechsel(); public void b() { aktuell.b(); aktuell.zustandswechsel(); public void c() { aktuell.c(); aktuell.zustandswechsel(); X Z a,c b b c Y 38

39 Beispiel class MZustand { protected M obj; protected MZustand(M m) { obj = m; // wie beschrieben class MZustandX extends MZustand { private MZustand z; protected MZustandX(M m) { super(m); protected void a() { // mach was z = new MZustandZ(obj); protected void b() { // mach was z = new MZustandY(obj); protected void c() { // mach was z = new MZustandZ(obj); protected CZustand nächster() { return z; X Z a,c b b class MZustandY extends MZustand { prot. MZustandY(M m) { super(m); protected void c() { // mach was protected CZustand nächster() { return new MZustandX(obj); class MZustandZ extends MZustand { prot. MZustandZ(M m) { super(m); protected void b() { // mach was protected CZustand nächster() { return new MZustandY(obj); Hier mit new. Es könnten auch Einzelstücke verwendet werden. c Y