Analyse des Ist-Standes 6. Vom Klassendiagramm zum Programm 6.1 6.2 6.3 6.4 6.5 6.6 CASE-Werkzeuge Übersetzung einzelner Klassen Übersetzung von Assoziationen Spezielle Arten der Objektzugehörigkeit Aufbau einer Software-Architektur Weitere Schritte zum lauffähigen Programm OOAD WS 09/10 Prof. Dr. Stephan Kleuker 139 • bekannter Weg: Kundenwünsche, Anforderungsformulierung, Analyse-Modell • Analysemodell kann realisiert werden, aber: – Klassen kaum für Wiederverwendung geeignet – Programme meist nur aufwändig erweiterbar – viele unterschiedliche Lösungen zu gleichartigen Problemen • deshalb: fortgeschrittene Designtechniken studieren • aber: um fortgeschrittenes Design zu verstehen, muss man die Umsetzung von Klassendiagrammen in Programme kennen (dieses Kapitel) • aber: um fortgeschrittenes Design zu verstehen, muss man einige OO-Programme geschrieben haben OOAD WS 09/10 Prof. Dr. Stephan Kleuker UML-Toolsuiten / CASE-Werkzeuge Übersetzung einfacher Diagramme (1/3) 6.1 6.2 Theorie: • UML-Werkzeuge unterstützen die automatische Umsetzung von Klassendiagrammen in Programmgerüste (Skelette) • Entwickler müssen die Gerüste mit Code füllen • viele Werkzeuge unterstützen Roundtrip-Engineering, d.h. Änderungen im Code werden auch zurück in das Designmodell übernommen (wenn man Randbedingungen beachtet) • Roundtrip beinhaltet auch Reverse-Engineering Praxis: • sehr gute kommerzielle Werkzeuge (z. B. IBM Rational, Borland Together); allerdings muss man für Effizienz Suite von Werkzeugen nutzen; d. h. auf deren Entwicklungsweg einlassen • ordentliche nicht kommerzielle Ansätze für Teilgebiete; allerdings Verknüpfung von Werkzeugen wird aufwändig OOAD WS 09/10 Prof. Dr. Stephan Kleuker 141 140 Anmerkung: auch bei Realisierung kann vereinbart werden, dass getund set-Methoden in Übersichten weggelassen (und damit als gegeben angenommen) werden Klassenmethoden sind unterstrichen OOAD WS 09/10 Prof. Dr. Stephan Kleuker 142 Übersetzung einfacher Diagramme (2/3) Übersetzung einfacher Diagramme (3/3) public class Mitarbeiter { /** * @uml.property name="minr" */ private int minr; /** * Getter of the property <tt>minr</tt> * @return Returns the minr. * @uml.property name="minr" */ public int getMinr() { return minr; } /** * Setter of the property <tt>minr</tt> * @param minr The minr to set. * @uml.property name="minr" */ public void setMinr(int minr) { this.minr = minr; } OOAD WS 09/10 Prof. Dr. Stephan Kleuker private String vorname = ""; public String getVorname() { return vorname;} public void setVorname(String vorname) { this.vorname = vorname; } private String nachname = ""; public String getNachname() {return nachname;} public void setNachname(String nachname) { this.nachname = nachname; private static int mitarbeiterzaehler; public static int getMitarbeiterzaehler() { return mitarbeiterzaehler; } public static void setMitarbeiterzaehler (int mitarbeiterzaehler) { Mitarbeiter.mitarbeiterzaehler = mitarbeiterzaehler; } } = evtl. notwendige Korrekturen, bei CASE-Werkzeug 143 Notwendige Code-Ergänzung durch Entwickler OOAD WS 09/10 Prof. Dr. Stephan Kleuker 144 Umgang mit Assoziationen im Design 6.3 • Assoziationen zunächst nur Strich mit Namen (und Multiplizitäten) • für Implementierung jede Assoziation konkretisieren (Richtung der Navigierbarkeit, Multiplizitäten sind Pflicht) public Mitarbeiter(String vorname, String nachname){ this.vorname=vorname; this.nachname=nachname; this.minr=Mitarbeiter.mitarbeiterzaehler++; } @Override public String toString() { return minr+": "+vorname+" "+nachname; } = vom Entwickler ergänzt OOAD WS 09/10 Prof. Dr. Stephan Kleuker 145 public class Projektaufgabe { /** werkzeugspezifische Kommentare weggelassen */ private Mitarbeiter bearbeiter; public Mitarbeiter getBearbeiter() { return bearbeiter; } public void setBearbeiter(Mitarbeiter bearbeiter) { this.bearbeiter = bearbeiter; } } OOAD WS 09/10 Prof. Dr. Stephan Kleuker 146 Multiplizität 1 Multiplizität n (1/2) • Objekreferenz darf nie null sein • Umsetzung als Collection (Sammlung, Container) private Mitarbeiter bearbeiter = new Mitarbeiter(); • oder im Konstruktor setzen • man sieht, default-Konstruktoren sind auch hier hilfreich; deshalb, wenn irgendwie möglich definieren • Gleiche Problematik mit der Werte-Existenz, bei Multiplizität 1..n OOAD WS 09/10 Prof. Dr. Stephan Kleuker 147 Multiplizität n (2/2) OOAD WS 09/10 Prof. Dr. Stephan Kleuker 148 Arten der Zugehörigkeit (Aggregation 1/2) 6.4 • Zum Codefragment der letzten Zeile passt besser folgendes Klassendiagramm • nicht exklusiver Teil eines Objekts (Mitarbeiter kann bei mehreren Projektaufgaben Bearbeiter sein) * • Hinweis: Standardhilfsklassen z. B. aus der JavaKlassenbibliothek oder der C++-STL werden typischerweise in Klassendiagrammen nicht aufgeführt • Anmerkung: man sieht die UML-Notation für generische (oder parametrisierte) Klassen • UML-Werkzeuge unterscheiden sich bei der Generierung und beim Reverse-Engineering beim Umgang mit Collections OOAD WS 09/10 • Umsetzung hängt von Art der Collection ab – sollen Daten geordnet sein – sind doppelte erlaubt – gibt es spezielle Zuordnung key -> value • Entwickler muss zur Typwahl spätere Nutzung kennen • eine Umsetzung für 1..* import java.util.List; import java.util.ArrayList; public class Projektaufgabe { private List<Mitarbeiter> bearbeiter = new ArrayList<Mitarbeiter>(); • bitte, bitte in Java nicht alles mit ArrayList realisieren (!!!) • Multiplizität 0..7 als Array umsetzbar Prof. Dr. Stephan Kleuker 149 • in C++: Mitarbeiter *bearbeiter; Mitarbeiter* Projektaufgabe::getBearbeiter(){ return bearbeiter;} oder Mitarbeiter bearbeiter; Mitarbeiter& Projektaufgabe::getBearbeiter(){ return bearbeiter;} • Realisierungsproblem: Projektaufgabe kann Namen des Bearbeiters ändern bearbeiter->setNachname("Meier"); • Kann als Verstoß gegen Kapselung (Geheimnisprinzip) angesehen werden • Designansatz: Klasse erhält Interface, die Methoden enthält, die bestimmte andere Klassen nutzen können OOAD WS 09/10 Prof. Dr. Stephan Kleuker 150 Arten der Zugehörigkeit (Aggregation 2/2) Arten der Zugehörigkeit (Komposition 1/2) • Designansatz: Verhindern unerwünschten Zugriffs durch Interface (generell gute Idee !) • Konkretisierung der Zugehörigkeit: existenzabhängiges Teil, Exemplarvariable gehört ausschließlich zum Objekt (Mitarbeiter kann [unrealistisch] nur exakt eine Projektaufgabe bearbeiten; niemand anderes nutzt dieses Objekt) • Realisierung in C++ Mitarbeiter bearbeiter; Mitarbeiter Projektaufgabe::getBearbeiter (){ return bearbeiter; } Kurzdarstellung Interfacerealisierer: OOAD WS 09/10 • Bei Rückgabe wird Kopie des Objekts erstellt und zurück gegeben Prof. Dr. Stephan Kleuker 151 OOAD WS 09/10 Prof. Dr. Stephan Kleuker 152 Arten der Zugehörigkeit (Komposition 2/2) Kurzzeitige Klassennutzungen • Java arbeitet nur mit Zeigern (unschöne Ausnahme sind Elementartypen), wie realisiert man • Klassen nutzen andere Klassen nicht nur für Exemplar- (und Klassen-) Variablen • Klassen erzeugen Objekte anderer Klassen lokal in Methoden, um diese weiter zu reichen public class Projektverwaltung { private Projekt selektiertesProjekt; public void projektaufgabeErgaenzen(String name){ Projektaufgabe pa= new Projektaufgabe(name); selektiertesProjekt.aufgabeHinzufuegen(pa); } • Klassen nutzen Klassenmethoden anderer Klassen • In der UML gibt es hierfür den „Nutzt“-Pfeil • (Omondo: <<include>>) @Override // in Mitarbeiter.java public Mitarbeiter clone(){ // echte Kopie Mitarbeiter ergebnis= new Mitarbeiter(); ergebnis.minr=minr; ergebnis.nachname=nachname; //Strings sind ergebnis.vorname=vorname; //Konstanten return ergebnis; } // in Projektaufgabe public Mitarbeiter getBearbeiter() { return bearbeiter.clone(); } • Variante: bei Realisierung überall doll aufpassen OOAD WS 09/10 Prof. Dr. Stephan Kleuker • Wenn zu viele Pfeile im Diagramm, dann mehrere Diagramme mit gleichen Klassen zu unterschiedlichen Themen • UML-Werkzeuge unterstützen Analyse von Abhängigkeiten 153 OOAD WS 09/10 Prof. Dr. Stephan Kleuker 154 Erstellen einer Softwarearchitektur Systematische Entwicklung komplexer Systeme 6.5 • Ziel des Design ist ein Modell, welches das Analysemodell vollständig unter Berücksichtigung implementierungsspezifischer Randbedingungen umsetzt • allgemeine Randbedingungen: Es gibt ingenieurmäßige Erfahrungen zum gutem Aufbau eines Klassensystems; dieses wird auch SW-Architektur genannt • Ziele für die Architektur – Performance – Wartbarkeit – Erweiterbarkeit – Verständlichkeit – schnell realisierbar – Minimierung von Risiken OOAD WS 09/10 Prof. Dr. Stephan Kleuker 155 • Für große Systeme entstehen viele Klassen; bei guten Entwurf: • Klassen die eng zusammenhängen (gemeinsame Aufgabengebiete) • Klassen, die nicht oder nur schwach zusammenhängen (Verknüpfung von Aufgabengebieten) • Strukturierung durch SW-Pakete; Pakete können wieder Pakete enthalten OOAD WS 09/10 Prof. Dr. Stephan Kleuker Typische 3-Schichten-SW-Architektur Beispiel: grobe Paketierung (eine Variante) • Ziel: Klassen eines oberen Pakets greifen nur auf Klassen eines unteren Paketes zu (UML-“nutzt“Pfeil) • Änderungen der oberen Schicht beeinflussen untere Schichten nicht • Analysemodell liefert typischerweise nur Fachklassen • Datenhaltung steht für Persistenz • typisch Varianten von 2 bis 5 Schichten • Klassen in Schicht sollten gleichen Abstraktionsgrad haben • Schicht in englisch „tier“ • obere und untere Schichten können stark von speziellen Anforderungen abhängen (später) • Anmerkung: Datenverwaltung noch nicht konzipiert OOAD WS 09/10 Prof. Dr. Stephan Kleuker 157 OOAD WS 09/10 Prof. Dr. Stephan Kleuker 156 158 Beispiel: grobe Paketierung (zweite Variante) OOAD WS 09/10 Prof. Dr. Stephan Kleuker Forderung: azyklische Abhängigkeitsstruktur 159 OOAD WS 09/10 Prof. Dr. Stephan Kleuker 160 Umsetzung von Paketen in Java und C++ Paketabhängigkeiten optimieren package fachklassen.projektdaten; import fachklassen.projektmitarbeiter.Mitarbeiter; public class Projektaufgabe { private Mitarbeiter bearbeiter; /* ... */ } • Ziel ist es, dass Klassen sehr eng zusammenhängen; es weniger Klassen gibt, die eng zusammenhängen und viele Klassen und Pakete, die nur lose gekoppelt sind • Möglichst bidirektionale oder zyklische Abhängigkeiten vermeiden • Bei Paketen können Zyklen teilweise durch die Verschiebung von Klassen aufgelöst werden • Wenig globale Pakete (sinnvoll für projektspezifische Typen (z. B. Enumerations) und Ausnahmen) • Es gibt viele Designansätze, Abhängigkeiten zu verringern bzw. ihre Richtung zu ändern #include "Mitarbeiter.h" //evtl. mit Dateibaum using namespace Fachklassen::Mitarbeiterdaten; namespace Fachklassen{ namespace Projektdaten{ class Projektaufgabe{ private: Mitarbeiter *bearbeiter; // ... }; } } OOAD WS 09/10 Prof. Dr. Stephan Kleuker 161 OOAD WS 09/10 Prof. Dr. Stephan Kleuker 162 Architektursichten Trick: Abhängigkeit umdrehen 6.6 • generell können Interfaces häufiger in anderen Paketen liegen, als ihre Implementierer • Java-Klassenbibliothek Swing fordert häufig die InterfaceImplementierung bei der Ereignisbehandlung • Paket- und Klassendiagramme geben einen guten Überblick über die Ergebnisse des statischen SWEntwurfs • Es gibt aber mehr Sichten (Betrachtungsweisen), die für eine vollständige SW-Architektur relevant sind • z. B. wurde die HW des zu entwickelnden Systems noch nicht berücksichtigt • Diese Sichten müssen zu einem System führen; deshalb müssen sich Sichten überlappen • z. B. eigenes Diagramm mit Übersicht über eingesetzte Hardware und Vernetzung; dazu Information, welche SW wo laufen soll OOAD WS 09/10 OOAD WS 09/10 Prof. Dr. Stephan Kleuker 163 164 4+1 Sichten mit (Teilen der) UML 4+1 Sichten Logische Sicht - funktionale Analyseergebnisse - Klassenmodell Logische Sicht Implementierungssicht - Subsysteme - Schnittstellen - Klassendiagramme - Paketdiagramme Ablaufsicht - Prozesse - Nebenläufigkeit - Synchronisation Szenarien -Use Case-Diagramme - Aktivitätsdiagramme Ablaufsicht - Sequenzdiagramme Physische Sicht - Kommunikations- Deploymentdiagramme - Zustandsdiagramme diagramme Physische Sicht - Zielhardware - Netzwerke Prof. Dr. Stephan Kleuker Implementierungssicht - Komponentendiagramme Szenarien OOAD WS 09/10 Prof. Dr. Stephan Kleuker 165 OOAD WS 09/10 Prof. Dr. Stephan Kleuker 166 Ablaufsicht Implementierungssicht • wichtig für verteilte Systeme; bzw. Systeme, die verteilt (auch auf einem Rechner) laufen • Festlegen der Prozesse • Festlegen etwaiger Threads • so genannte aktive Klassen; werden Objekte dieser Klassen gestartet, so starten sie als eigenständige Prozesse/Threads • Das Designmodell muss physikalisch realisiert werden; es muss eine (ausführbare) Datei entstehen • Pakete fassen als Komponenten realisiert Klassen zusammen • häufig werden weitere Dateien benötigt: Bilder, Skripte zur Anbindung weiterer Software, Installationsdateien • Komponenten sind austauschbare Bausteine eines Systems mit Schnittstellen für andere Komponenten • Typisch ist, dass eine Komponente die Übersetzung einer Datei ist • Typisch ist, dass eine Komponente die Übersetzung eines Pakets ist; in Java .jar-Datei aktivesObjekt: AktiveKlasse AktiveKlasse • Prozessverhalten u. a. durch Sequenzdiagramme beschreibbar • (übernächste VL etwas mehr; gibt eigenes Modul dazu) OOAD WS 09/10 Prof. Dr. Stephan Kleuker 167 Komponentendiagramm Prof. Dr. Stephan Kleuker Prof. Dr. Stephan Kleuker 168 Physische Sicht: vorgegebene HW mit Vernetzung • Einsatz- und Verteilungsdiagramm (deployment diagram) • Knoten steht für physisch vorhandene Einheit, die über Rechenleistung oder/und Speicher verfügt • <<executable>> (ausführbare Datei) und <<artifact>> (Datei) müssen zur HW-Beschreibung nicht angegeben werden • Bilder zeigen zwei alternative Darstellungen • Komponenten bieten Schnittstellen(realisierungen) (Kreis) und benötigen Schnittstellen(realisierungen) (Halbkreis) • Komponenten können über Schnittstellen in Diagrammen verknüpft werden • in die Komponenten können die zugehörigen Klassen eingezeichnet werden • Ports erlauben den Zugriff auf bestimmten Teil der Klassen und Interfaces (nicht im Diagramm) OOAD WS 09/10 OOAD WS 09/10 169 OOAD WS 09/10 Prof. Dr. Stephan Kleuker 170