3 Implementation von UML

Werbung
Sächs. VWA
Fritzsche: Software-Engineering
Inhalt
1
1.1
1.2
Ziele und Arbeitsmethoden der Softwaretechnologie
Methodologie der Softwareentwicklung
Die Modellierungssprache UML
2
2.1
2.2
2.3
2.4
2.5
2.6
2.7
2.8
2.9
2.10
2.11
2.12
Objektorientierte Modellierung
Klassen-Instanzen-Abstraktion
Attribute und Operationen
Sichtbarkeit und Lebensdauer
Assoziationen und Verknüpfungen
Aggregation und Komposition
Generalisierung und Spezialisierung
Vererbung und Delegation
Polymorphie
Abstrakte und konkrete Klassen
Instanzen als Laufzeitobjekte
Statechart-Modelle
Aktivitäten-Diagramme
3
3.1
3.2
3.3
3.4
3.5
Implementation von UML-Modellen
Von UML nach Java
Ein Beispiel: Baum-Klassen
Interfaces und Mehrfachvererbung
Implementation von Assoziationen und Aggregationen
Dynamische Modelle und Event-Handling
4
4.1
4.2
4.3
Systemarchitekturen
Komponentenmodelle
Verteilungsmodelle
Objektserialisierung
5
5.1
5.2
5.3
5.4
5.5
Der Softwareentwicklungsprozess
Anwendungsfall-Analyse
Methodische Aspekte der Modellierung
Qualitätssicherung
Projektmanagement und Prozessmodellierung
Konfigurationsmanagement
6
6.1
6.2
6.3
6.4
Wiederverwendung
Komponentenbasierte Softwareentwicklung - Frameworks
Entwurfsmuster
Grafische Benutzeroberflächen
Die Model-View-Controller-Architektur
1
Sächs. VWA
Fritzsche: Software-Engineering
Literatur
H. Balzert
Lehrbuch der Objektmodellierung. Analyse und Entwurf mit der UML 2.
Spektrum Akademischer Verlag, 2004
M. Fowler, K. Scott
UML konzentriert. Eine Einführung in die Standard-Objektmodellierungssprache.
Addison-Wesley, 2. Aufl. 2000
C. Rupp, S. Queins, B. Zengler
UML 2 glasklar, Praxiswissen für die UML-Modellierung
Carl Hanser Verlag, 3. Aufl., 2007
B. Oestereich
Objektorientierte Softwareentwicklung mit der Unified Modeling Language.
Oldenbourg, 3. Aufl., 1997
W. Pree
Komponentenbasierte Softwareentwicklung mit Frameworks.
dpunkt.verlag, 1997
I. Sommerville
Software Engineering.
Addison-Wesley, 8. Aufl. 2007
Entwicklungsplattform Eclipse:
http://www.eclipse.org
Eclipse Dokumentation (Juno):
http://www.eclipse.org/indigo
Eclipse Dokumentation (Kepler):
http://www.eclipse.org/kepler
Entwicklungsplattform Topcased:
http://topcased.org
2
Sächs. VWA
Fritzsche: Software-Engineering
3
1 Einführung: Ziele und Arbeitsmethoden der Softwaretechnologie
1.1
Methodologie der Softwareentwicklung
Die Softwaretechnologie (Software Engineering) ist die Lehre vom Prozess der organisierten Softwareproduktion. Sie umfasst (die Erforschung von) Theorie, Methoden und Werkzeuge(n) zur Herstellung von Software. Das schließt Maßnahmen zur
Qualitätssicherung, die Nachnutzung von Software sowie das Projektmanagement
und das Konfigurationsmanagement ein.
Dem Prozess der Softwareentwicklung wird im konkreten betrieblichen Umfeld jeweils ein Lebenszyklusmodell (auch als Vorgehensmodell bezeichnet) zugrunde gelegt. Bekannte Lebenszyklusmodelle sind u.a. das Wasserfallmodell und das Spiralmodell (letzteres ist ein evolutionäres Modell). Ein sehr einfaches Modell ist das
V-Modell. Für kleinere Entwicklergruppen ist die „Agile Softwareentwicklung“ ein bevorzugtes Modell.
Im Entwicklungsprozess lassen sich Entwicklungsphasen abgrenzen:
• Analyse (Anforderungsanalyse (Pflichtenheft) – Anwendungsfallanalyse – Problembereichsanalyse) ,
• Entwurf (Softwareentwurf – Algorithmenentwurf – Komponentenentwurf – Modelloptimierung) ,
• Implementation (reduziert sich z.T. auf eine Generierung bei Vorliegen formaler Spezifikationen) und
• Test (Unit-Test, Integrationstest, Systemtest; teilweise auch entwicklungsbegleitend).
Es existiert nicht eine allgemein anerkannte Entwicklungsmethodik, sondern eine
Methodologie (Lehre von den Methoden ...) der Softwareentwicklung. Wichtige
Aspekte der Softwaretechnologie sind
die Entwicklung „großer“ Systeme (Entwicklergruppen über längere Zeit)
Rollenbindung beteiligter Personen
Erweiterung und Anpassung (Entwicklung endet nicht mit 1. Systemversion)
Wiederverwendung (Entwicklung beginnt nicht erst beim eigenen System)
Software-Architekturen (abhängig von eingesetzten Entwicklungsmethoden)
CASE (rechentechnische Unterstützung ist abhängig von angewandten Entwicklungsmethoden)
Zweckbindung führt auf Musterarchitekturen
1.2
Die Modellierungssprache UML
Die Unified Modeling Language (UML) ist eine grafische Modellierungs- und Entwurfssprache. Sie basiert auf Entwicklungen von G. Booch, J. Rumbaugh sowie I.
Jacobson und bildet seit Anfang der 1990er Jahre einen Quasi-Standard im Software Engineering. Mit der UML (aktuell: UML 2) werden Modelle entwickelt, die Ausschnitte einer zu modellierenden realen oder erdachten Welt widerspiegeln. Zur
Darstellung der Modelle unterschiedlicher Art dienen jeweils Diagramme. Diagramme visualisieren und formalisieren Ausschnitte aus bzw. Sichten auf Modelle.
Diagrammtypen:
• Use-Case-Diagramm (use case diagram)
• Klassen-Diagramm (static structure diagram)
Sächs. VWA
Fritzsche: Software-Engineering
•
•
•
•
•
•
•
•
•
•
•
•
Objekt-Diagramm (object diagram)
Paket-Diagramm (package diagram)
Kompositionsstruktur-Diagramm (composite structure diagram)
Profil-Diagramm (profile diagram)
Sequenz-Diagramm (sequence diagram)
Kommunikations-Diagramm (communication diagram)
Zustands-Diagramm (statechart diagram)
Aktivitäts-Diagramm (activity diagram)
Komponenten-Diagramm (component diagram)
Verteilungs-Diagramm (deployment diagram)
Zeitverlaufs-Diagramm (timing diagram)
Interaktionsübersichts-Diagramm (interaction overview diagram)
Modelltypen:
•
•
•
•
•
•
Use-Case-Modell
Klassenstrukturmodell
Interaktionsmodell (Sequenz- u. Kommunikations-Diagramm)
Zustandsmodell (Zustands- u. Aktivitäten-Diagramm)
Komponentenmodell
Verteilungsmodell
Charakterisierung der grafischen Modellierungssprache: In der UML-Notation werden 4 Arten grafischer Konstrukte verwendet: Icons, 2-dimensionale Symbole, Pfade
und Strings. Im Sinne eines Graphen bilden zweidimensionale Symbole Knoten, die
durch Pfade als Kanten verbunden sein können. Strings besitzen (mit Ausnahme
von Kommentaren) eine Syntax, sie können singulär auftreten oder anderen Sprachelementen zugeordnet sein.
Die UML ist eine (semi-)formale Sprache. Die Definition der Syntax (und evtl. der
Semantik) einer formalen Sprache erfolgt mit den Mitteln einer (formalen) Sprache.
Diese Sprache heißt Metasprache und dient zur Definition einer Objektsprache. Die
UML wird auch als Metasprache zur Modellierung von UML-Konzepten selbst eingesetzt (sog. Metamodellierung).
2 Objektorientierte Modellierung
2.1 Klassen-Instanzen-Abstraktion
Ein Objekt ist ein (abstrakter) Gegenstand oder ein Konzept mit klarer Abgrenzung
und präziser Bedeutung.
Beispiele: Kommissar Rex, das Fenster im Haus oben links, Herr Lutze, Mediatec
GmbH, ...
Eine Klasse beschreibt eine Menge von Objekten, die
• ähnliche Struktur und ähnliche Merkmale (Attribute) besitzen,
• ähnliches Verhalten zeigen (Operationen bzw. „Methoden“),
• in Relationen zu Objekten anderer Klassen oder der gleichen Klasse stehen.
Eine Klasse kann durch Aufzählung aller zugehörigen Objekte oder durch die Definition der Eigenschaften der Objekte (Klassendefinition) beschrieben werden. Zu ei-
4
Sächs. VWA
Fritzsche: Software-Engineering
ner Klasse gehörige Objekte werden alternativ auch als Instanzen, Instanzobjekte
oder Exemplare der Klasse bezeichnet. Klassen werden benannt.
Beispiele: Hund, Fenster, Person, Firma, ...
Objekte bilden bei der Realisierung auf einem Rechner Implementierungseinheiten.
Objekte sind immer Instanzen einer bestimmten Klasse und besitzen eine Identität
und eine Lebensdauer. Jedes Objekt kennt die Klasse, zu der es gehört. Eine Klassendefinition umfasst (evtl. implizit) die Beschreibung von Vorschriften zur Erzeugung von Instanzen. Klassenbildung ist Abstraktion (bei einer Abstraktion werden
unwesentliche Eigenschaften weggelassen; sprich: es wird von unwesentlichen Eigenschaften abstrahiert). Abstraktion ist in der Informatik ein mächtiges Mittel zur
Bewältigung von Komplexität.
2.2 Attribute und Operationen
Attribute beschreiben die betrachteten strukturellen Merkmale, die alle zu einer
Klasse gehörenden Instanzen in einer gewissen spezifischen Ausprägung besitzen.
In einer Klassendefinition sind diese Attribute benannt. Jedes einzelne Objekt der
Klasse besitzt für jedes Attribut (Merkmal) eine individuelle Ausprägung (Merke: Objekt - Merkmal -Ausprägung, also „OMA“), die sich allerdings bei einem Objekt im
Laufe der Zeit ändern kann. „Ausprägungen“ sind Datenwerte eines in einer Klassendefinition vorbestimmten Datentyps. Der Wertebereich ist für jedes Attribut
(eventuell impliziert) in der Klassendefinition durch Angabe eines Typnamens festgelegt.
Jedes existierende Objekt einer Klasse besitzt für jedes Attribut zu einem bestimmten Zeitpunkt einen Wert aus dem Wertebereich. Dieser Wert kann von den bei anderen Objekten zum selben Zeitpunkt geltenden Werten verschieden sein.
Die Gesamtheit der Werte (d.h. der Ausprägungen) aller Attribute eines Objektes zu
einem bestimmten Zeitpunkt bildet den Zustand des Objektes.
Operationen definieren das Verhalten von Objekten. Alle Instanzobjekte einer Klasse verhalten sich in einer gewissen Weise gleichartig. Das Verhalten eines Objektes
wird dabei von individuellen Ausprägungen der Attribute mitbestimmt. Die Verhaltensbeschreibung wird der Klassendefinition zugeordnet, und nicht jedem Objekt
einzeln. Sie existiert damit einmal unabhängig von der Anzahl vorhandener Instanzen, was bei der Implementation von Operationen in einer objektorientierten Programmiersprache genauso umgesetzt wird. Als „Methode“ bezeichnet man die Implementation einer Operation für eine Klasse. Eine Methode kann jeweils auf ein
Objekt angewendet werden.
Eine Klasse wird in der UML durch ein Rechteck mit maximal drei Feldern für den
Klassennamen, die Attribute und die Operationen dargestellt. Klassennamen sollen
fett gedruckt sein und mit Großbuchstaben beginnen, die Namen von Attributen und
Operationen beginnen mit Kleinbuchstaben.
Instanzobjekte werden ebenfalls als Rechtecke mit maximal zwei Feldern dargestellt. Instanzobjekte können einen Namen besitzen oder auch unbenannt sein. Im
obersten Feld wird – wenn vorhanden - der Instanzname gefolgt von Doppelpunkt,
gefolgt vom Klassennamen angegeben. In jedem Fall wird aber ein Doppelpunkt
und nachfolgend der Klassenname angegeben.
Klassen können in einem Klassenstruktur-Diagramm dargestellt werden. Objektstrukturen können in Objektdiagrammen dargestellt werden. Ein Objektdiagramm
stellt eine „Momentaufnahme“ zur Laufzeit eines Systems dar.
5
Sächs. VWA
Fritzsche: Software-Engineering
6
Notation einer Klasse:
klassenname
[visibility] attributname : typname [= default-wert]
…
…
[visibility] operationsname ( argumentliste) : ergebnistypname
…
…
Notation einer Instanz:
[instanznname] : klassenname
attributname = wert
…
…
Beispiel mit Angabe der Instanziierungsrelation:
Person
name:string
vorname:string
geschlecht:char
geburtsjahr:int
+alter:int
Max:Person
Moritz:Person
Beachte: 'Max' in 'Max:Person' benennt das Objekt. Diese Benennung ist vom Namen bzw. dem Vornamen einer Person zu unterscheiden. Das Objekt könnte auch
mit 'P1' benannt sein, dann wäre P1:Person anzugeben.
2.3 Sichtbarkeit und Lebensdauer
Benennungen ordnen Klassen, Objekten, Attributen und Operationen Namen zu.
Namen sind immer innerhalb einer gewissen Umgebung (Environment) sichtbar,
d.h. unter Verwendung der Namen können die jeweiligen Dinge angesprochen wer-
Sächs. VWA
Fritzsche: Software-Engineering
den. Außerhalb der Umgebung sind die entsprechenden Dinge nicht ansprechbar,
d.h. nicht referenzierbar. Es werden vier relative Sichtbarkeitsbereiche (sog. Visibility) abgegrenzt:
+
#
~
public
private
protected
package wide (Packages werden weiter unten beschrieben)
Konstruktoren sind spezielle Operationen, die der Erzeugung von Objekten dienen.
Objekte existieren solange, solange sie referenzierbar sind oder bis sie explizit aus
der Objektwelt entfernt werden.
Attribute können auf Instanzobjekte (instance scope) oder auf Klassen (class scope)
bezogen sein. Im Falle des Bezuges auf Klassen spricht man auch von „Klassenvariablen“.
Operationen können auf Instanzobjekte (instance scope) oder auf Klassen (class
scope) angewendet werden. Im Falle der Anwendung auf Klassen spricht man auch
von „Klassen-Methoden“.
2.4 Assoziationen und Verknüpfungen
Eine Assoziation ist eine abstrakte, d.h. nicht näher charakterisierte Beziehung zwischen zwei (binäre A.) oder mehr Klassen. In der grafischen Darstellung werden die
Symbole der beteiligten Klassen durch eine durchgezogene Linie verbunden. Die
Enden einer Assoziationslinie können auch mit demselben Klassensymbol verbunden sein.
Assoziationen höherer Ordnung (ternäre, ...) werden durch einen Rhombus dargestellt, der durch Linien mit den Klassensymbolen verbunden ist. Assoziationen höherer Ordnung sollten praktisch nach Möglichkeit vermieden werden. Sie sind schwerer zu verstehen, darzustellen und zu implementieren als binäre Assoziationen. Einer Assoziation kann im Klassenstrukturdiagramm ein Name oder sogar eine Klasse
zugeordnet sein. Weitere Eigenschaften können durch Constraints ausgedrückt werden.
Eine Verknüpfung (Link) ist ein Element einer Assoziation. Sie wird im Objektdiagramm dargestellt und setzt eine Anzahl von Objekten entsprechend der Assoziation
in Beziehung. Ist durch eine binäre Assoziation eine Klasse mit sich selbst verbunden, können unterschiedliche Objekte dieser Klasse miteinander verknüpft sein oder
ein Objekt mit sich selbst. Verknüpfungen verbinden im Klassenstrukturdiagramm
Instanzobjekte.
Beispiele:
7
Sächs. VWA
Fritzsche: Software-Engineering
In einer Assoziation können die beteiligten Klassen Rollen spielen. An den Enden
des die Assoziation kennzeichnenden Pfades können jeweils der Rollenname der
Klasse und eine Kardinalität notiert werden.
Durch die Angabe einer Kardinalität wird die Multiplizität beschrieben. Die Angabe
erfolgt durch die Aufzählung von Bereichen, die durch Komma getrennt werden.
Eine Bereichsangabe hat die allgemeine Form
untere-grenze .. obere-grenze. Ein * kann für eine nicht negative ganze Zahl zur
Kennzeichnung einer nach oben offenen Grenze gesetzt werden.
2.5 Aggregation und Komposition
Eine Aggregation ist eine Sonderform der Assoziation mit zusätzlicher Semantik und
bedeutet eine „Teil-Ganzes“-Beziehung. Objekte, die Komponenten einer Sache repräsentieren, sind mit einem Objekt verknüpft, das die Komponentengruppe (das
8
Sächs. VWA
Fritzsche: Software-Engineering
9
Aggregat) repräsentiert. Aggregation ist über eine beliebige Anzahl von Ebenen hinweg möglich.
Darstellung: hohle Raute an dem Ende der Assoziation, das dem Aggregat zugeordnet ist.
Class1
Class2
1..*
Ein Objekt der Klasse Class1 repräsentiert die Komponentengruppe, Objekte der
Klasse Class2 repräsentieren die Komponenten. Eine Komponentengruppe mit
Komponenten verschiedener Typen hat entsprechend viele Aggregationen.
Eine Aggregation ist transitiv und antisymmetrisch.
Die Komposition wird als "enge" Aggregation verstanden, die eine Verbindung der
Teile mit dem Ganzen auch hinsichtlich der Lebenslinie bedeutet. Attribute einer
Klasse können als Komposition zwischen der Klasse und den Klassen (bzw. Typen)
der Attribute verstanden werden.
Darstellung: Ausgefüllte Raute anstelle der hohlen Raute.
Beispiele:
Ein Dokument besteht aus Absätzen, die ihrerseits aus mindestens einem
Satz bestehen.
Dokument
Absatz
Satz
1..*
1
Polygon
1..*
3..*
{ordered}
Eckpunkt
1
1
Verbund
Punkt
y:real
x:real
GrafikVerbund
farbe:Farbe
texture:Texture
Ein Polygon hat mindestens drei Eckpunkte. Die Farbe und andere Eigenschaften sind dem Polygon fest zugeordnet. Ein Punkt existiert auch unabhängig vom Polygon, er kann z.B. mehreren Polygonen gleichzeitig zugeordnet
sein.
Sächs. VWA
Fritzsche: Software-Engineering
10
2.6 Generalisierung und Spezialisierung
Generalisierung und Spezialisierung sind Vorgänge, die eine Inklusions-Relation
zwischen (mindestens) einer allgemeineren und (mindestens) einer spezielleren Entität etablieren. Eine speziellere Entität besitzt alle Eigenschaften der allgemeineren
Entität (Inklusion) sowie zusätzliche und/oder anders ausgeprägte Eigenschaften
(sog. „is a“-Relation).
Generalisierung und Spezialisierung werden zunächst auf Klassen angewendet.
Die Inklusionsrelation ist gerichtet. Sie ist transitiv und antisymmetrisch. Eine an der
Relation beteiligte allgemeinere Klasse wird als Superklasse (Oberklasse), eine speziellere Klasse als Subklasse (Unterklasse) bezeichnet.
Sprechweise: Ein Hund "ist ein" (is-a) Säugetier.
Die Klasse Hund ist Subklasse zur Klasse Säugetier.
Ein Student "ist ein(e)" Person.
Die Klasse Person ist Superklasse zur Klasse Student.
Eine Subklasse hat gegenüber der zugeordneten Superklasse veränderte Eigenschaften. Dabei kann es sich um
zusätzliche Attribute,
zusätzliche Operationen,
Modifikationen bzw. spezielle Ausprägungen von Operationen,
Modifikationen von Festlegungen für Anfangswerte von Attributen
handeln.
Durch Generalisierung bzw. Spezialisierung entstehen bzgl. der Inklusionsrelation
zyklenfreie, gerichtete Graphen.
In einer Klassenhierarchie kann eine Klasse nur eine Superklasse haben. In einer
Klassenheterarchie kann eine Klasse mehrere Superklassen haben. Eine Klasse mit
mehr als einer Superklasse heißt Vereinigungsklasse.
Grafische Notation:
Class3
Class4
Die Spitze des Dreiecks zeigt zur Superklasse.
Class5
Sächs. VWA
Fritzsche: Software-Engineering
Constraints
Für eine Generalisierung können Constraints angegeben werden (neben dem Dreieck in geschweiften Klammern notiert). Vordefinierte alternativ verwendbare Angaben sind overlapping vs. disjoint sowie complete vs. incomplete.
Sind alle Subklassen angegeben (die Anordnung ist vollständig, es werden keine
weiteren Subklassen erwartet) wird complete angegeben, andernfalls incomplete. Der implizit angenommene Standardwert (d.h. falls die Angabe fehlt) ist incomplete.
Kann ein Nachkomme von mehr als einer Subklasse abgeleitet werden, kann dies
durch overlapping gekennzeichnet werden. Das Gegenteil kann durch disjoint gekennzeichnet werden.
Beispiel:
Fahrzeuge können sowohl nach der Antriebsart (motorgetrieben, windgetrieben) als
auch nach dem Medium, auf bzw. in dem sie sich bewegen (Luft, Wasser, Land),
spezialisiert werden (vgl. Abbildung Abschnitt 3.3). Ein Lastkraftwagen (LKW) ist
demnach ein Fahrzeug, das motorgetrieben ist und sich auf dem Land bewegt.
2.7 Vererbung und Delegation
Als Vererbung (inheritance) wird die Weitergabe von Eigenschaften (Attribute, Operationen, Standardinitialwerte) einer Klasse an die Subklassen bezeichnet. Die Beschreibungen von Eigenschaften der Instanzen der Klasse werden entlang der Inklusionsrelation (an die Subklassen) vererbt. Tatsächlich müssen bei einer Klasse
die Eigenschaften ihrer Superklasse(n) nicht noch einmal beschrieben werden, sie
gelten implizit. Von besonderem Interesse ist, dass das auch bzgl. der Implementation gilt.
Durch Mehrfachvererbung ist es möglich, dass eine Klasse, die mehrere Oberklassen hat, Merkmale von allen Oberklassen erbt. Ein Merkmal aus der gleichen Vorfahrenklasse, das in mehr als einem Pfad gefunden wird, wird nur einmal geerbt, es
handelt sich um das gleiche Merkmal. Konflikte zwischen parallelen Definitionen
führen zu Mehrdeutigkeiten, die bei der programmtechnischen Realisierung gelöst
werden müssen.
Delegation ist ein Implementierungsmechanismus, mit dessen Hilfe ein Objekt eine
Operation auffängt und an ein anderes Objekt zur Ausführung sendet.
Zum Beispiel hat eine Klasse A ein Attribut, dessen Wertebereich die Instanzen einer Klasse B umfasst. Ein Instanzobjekt der Klasse A verwaltet (eine Referenz auf)
ein Objekt der Klasse B. Eine auf ein Objekt von A angewendete Methode kann damit ihrerseits eine entsprechende Methode auf das verwaltete Objekt von B anwenden. Operationen werden aber nicht automatisch über die Aggregation hinweg vererbt!
Mittels Aggregation und Delegation kann fehlende Mehrfachvererbung umgangen
werden. Es bestehen folgende Möglichkeiten:

Delegation durch Verwendung von Rollenaggregation

Vererbung der wichtigsten Klasse und Delegation des Restes

Verschachtelte Generalisierung
11
Sächs. VWA
Fritzsche: Software-Engineering
2.8 Polymorphie
Polymorphie bedeutet Vielgestaltigkeit. Der Begriff wird hier verwendet, um hervorzuheben, dass mit demselben Namen zu unterschiedlichen Zeitpunkten unterschiedliche Methoden (d.h. unterschiedliche Implementationen von Operationen)
benannt werden können.
Beispiel:
Wir betrachten Unruhen (mobiles) und möchten mit einer Operation balancedp()
bestimmen, ob sich eine Unruhe im Gleichgewicht befindet. Abstrahiert man von
den physikalischen Gegebenheiten, handelt es sich bei den Unruhen um eine spezielle Art gewichtsbalancierter Bäume (im Unterschied zu höhenbalancierten
Bäumen). Wir modellieren eine Klasse Mobile mit den Attributen "linker Nachfolger" (lsucc) und "rechter Nachfolger" (rsucc). Die Attribute sind vom Typ Mobile,
d.h. entsprechende Attribute können Referenzen auf Objekte vom Typ Mobile aufnehmen. Die Armlängen (links bzw. rechts von der Aufhängung) spielen zunächst
keine Rolle. Es wird angenommen, sie sind für jede Unruhe links und rechts gleich
groß.
Jede Unruhe verwaltet ein Objekt vom Typ Node. Das Attribut key der Klasse Node
ist vom Typ int (ganze Zahl) und dient zur Identifikation einer Unruhe. Nur für Unruhen ohne Nachfolger (d.h. für Blattkelemente im Baum der Unruhen) enthält das
Attribut key das Gewicht. Bei Unruhen mit Nachfolgern (inneren Knoten) wird key
der Wert 0 zugewiesen. Wird die Operation weight auf ein Objekt vom Typ Mobile angewendet, liefert sie bei Blattelementen den Wert von key und sonst die
Summe der Gewichte der Nachfolgerknoten.
Die Klasse MobileA spezialisiert die Klasse Mobile in der Weise, dass die Arme
einer Unruhe unterschiedlich lang sein können. Zur Speicherung der Armlängen dienen die Attribute larm und rarm. Die Attribute lsucc und rsucc werden von Mobile an MobileA vererbt. Die Methode balancedp() kann sowohl auf Instanzen
von Mobile als auch von MobileA angewendet werden. Für jeden dieser Fälle
wird in Abhängigkeit vom Typ des aktuellen Objekts allerdings eine andere Methode
ausgeführt. Da in diesem Fall zur Laufzeit entschieden wird, welche Methode tatsächlich ausgeführt wird, heißt diese Art der Polymorphie "dynamische
Polymorphie". Bezogen auf die Implementation spricht man von „später Bindung“
oder auch „dynamischer Bindung“.
12
Sächs. VWA
Fritzsche: Software-Engineering
2.9 Abstrakte und konkrete Klassen
Eine abstrakte Klasse ist eine Klasse, die selbst keine direkten Instanzen besitzt,
deren Nachkommen aber direkte Instanzen besitzen.
Eine konkrete Klasse ist eine Klasse, die direkte Instanzen besitzen kann ("instanziierbare Klasse").
Nur konkrete Klassen können Blattklassen im Vererbungsbaum sein!
Eine abstrakte Klasse kann sowohl abstrakte Operationen als auch nicht abstrakte
Operationen definieren.
Eine Operation kann abstrakt sein. Eine abstrakte Klasse definieret in diesem Fall
nur die Signatur einer Operation, ohne eine entsprechende Methode zu implementieren. Eine Kennzeichnung im Klassensymbol erfolgt entweder durch den Zusatz
13
Sächs. VWA
Fritzsche: Software-Engineering
{abstract} oder dadurch, dass die Signatur der Operation in italics gesetzt wird. Ein
Auftreten der Signatur der Operation in einer abgeleiteten Klasse (ohne Kennzeichnung als abstrakte Operation) zeigt an, dass die abgeleitete Klasse eine Methode
für die Operation definiert.
2.10 Instanzen als Laufzeitobjekte
Ein Objekt ist als Instanz einer Klasse ein Laufzeitobjekt. Es belegt bei der programmtechnischen Realisierung Speicherplatz, hat eine Identität und besitzt eine
gewisse Lebensdauer. Objekte können benannt werden. Das bedeutet, dass eine
Assoziation zwischen einem Namen (einem Bezeichner) und einer Objektreferenz
aufgebaut wird. Namen sind einem Sichtbarkeitsbereich (scope) zugeordnet.
Wir unterscheiden:
- global
- Paket-lokal
- Klassen-lokal (evtl. inclusive Vererbung)
- Methoden-lokal
Im Laufe der Zeit können sich solche Assoziationen ändern, d.h. ein Name kann mit
einer Referenz auf ein anderes Objekt assoziiert werden.
Typkompatibilität bedeutet, dass einem Bezeichner, der mit einer Referenz auf ein
Objekt einer Klasse assoziiert ist, ein Objekt einer anderen Klasse ("Referenzklasse") zugeordnet werden kann. Typkompatibilität wird in UML nicht speziell unterstützt. Welche Typen kompatibel sind, hängt bei der programmtechnischen Realisierung von der verwendeten objektorientierten Programmiersprache ab.
Die Erzeugung eines Objektes kann auf zweierlei Weise erfolgen:
1. statisch, mit der Initialisierung des Anwendungssystems
2. dynamisch, durch Anwendung eines Konstruktors der entsprechenden
Klasse während der Ausführung einer Methode.
Objektzustände: vordefinierte Ausprägungen für Zustände von Objekten sind
•
nicht existent (Widerspruch!)
•
existent: Für ein Objekt wurde Speicher erfolgreich angefordert, die
Zuordnung der Methoden aus der Klassendefinition war erfolgreich.
•
initialisiert
•
deinitialisiert
•
gelöscht
Für persistente Objekte werden zusätzliche Zustände erklärt: ausgelagert, im-Speicher.
Das Erzeugen und Löschen von Objekten kann in Sequenzdiagrammen dargestellt
werden. In vielen objektorientierten Programmiersprachen kann der Zeitpunkt zum
Löschen eines Objektes vom Programmierer selbst geplant werden (z.B. C++).
Objekte können miteinander mittels Nachrichten kommunizieren (senden und empfangen). Ein Objekt kann seinen Zustand verändern infolge von Reaktionen auf
 Methodenaufrufe (invocation)
 Ereignisse
Ein Sequenzdiagramm zeigt das Verhalten von Objekten und berücksichtigt dabei
die Interaktion mit anderen Objekten durch den Austausch von Nachrichten. Mit Hilfe von Sequenzdiagrammen werden Szenarios beschrieben.
14
Sächs. VWA
Fritzsche: Software-Engineering
15
Szenario: Folge von Ereignissen, die bei einer ganz bestimmten Ausführung eines
Systems auftritt. Es kann alle Ereignisse eines Systems betreffen oder Ereignisse,
die bestimmte Objekte eines Systems beeinflussen oder von bestimmten Objekten
erzeugt werden.
Ein Szenario erhält man durch Aufzeichnung bei der Ausführung eines Systems
oder durch gedankliche Vorausplanung der Aufzeichnung.
Im Sequenzdiagramm ist eine Aufteilung der Lebenslinie eines Objekts in parallele
Zweige möglich. Parallele Lebenslinien können an einem späteren Punkt wieder zusammengeführt werden.
Object1
Object2
1: nachricht()
1.1: antwort()
2.11 Statechart-Modelle
Ein Zustandsautomat (das ist ein endlicher Automat) ist ein Graph, bestehend aus
Zuständen und Transitionen, der die Reaktion eines Objektes einer Klasse auf den
Sächs. VWA
Fritzsche: Software-Engineering
16
Empfang von "äußeren Stimuli" beschreibt. Ein Zustandsautomat ist einer Klasse
oder einer Methode zugeordnet.
Ein Zustand (state) ist die Verfassung (im Verlaufe des Lebens) eines Objektes, in
der es einer Bedingung genügt, eine Aktion ausführt oder auf ein Ereignis wartet.
Ein Objekt verweilt eine endliche Zeit in einem Zustand.
Eine Transition ist eine durch ein Ereignis verursachte Zustandsänderung eines Objektes.
Notation:
event(argument ...) [ bedingung ]/ operation(argument ...)
Ereignisse (events) sind bemerkenswerte Vorkommnisse. In Bezug auf Statecharts
ist ein Ereignis ein Vorkommnis, das eine Transition auslöst. Es hat keine Dauer.
Der Zustand eines Objektes bestimmt die Reaktion des Objektes auf ankommende
Ereignisse. Reaktionen können Aktionen und/oder Zustandsänderungen sein.
Aktionen (actions) sind atomar und nicht unterbrechbar. Ein Zustand kann mit einer
andauernden Aktivität verbunden sein. Eine solche Aktivität wird selbst als Zustandsautomat ausgedrückt. Eine andauernde Aktivität kann als Paar von Aktionen
ausgedrückt werden.
Notation:
Ein Statechart (Zustands-Diagramm) repräsentiert einen Zustandsautomaten. Zustände werden durch Zustandsymbole (Rechteck mit abgerundeten
Ecken) repräsentiert. Sie können einen Namen beinhalten und optional durch horizontale Linien in bis zu drei Bereiche geteilt werden. Spezielle Symbole existieren
für den Startzustand und Endzustände:
Transitionen werden durch Pfeile dargestellt, die Zustandssymbole verbinden. Ereignisse, die Zustandsübergänge auslösen, werden als Beschriftung an die zugehörigen Pfeile geschrieben.
Interpretation:
•
wenn sich ein Objekt in einem Zustand befindet, und ein Ereignis tritt auf, mit dem
eine seiner Transitionen beschriftet ist, geht das Objekt in den Zustand am Ende der
Transition über: Die Transition „feuert“.
•
wenn ein Ereignis auftritt, für das es keine vom aktuellen Zustand ausgehende Transition gibt, wird das Ereignis ignoriert.
Übergänge ohne Ereignisbeschriftung werden automatisch ausgelöst, sobald die mit
dem Zustand verbundenen Aktionen/Aktivitäten abgeschlossen sind.
Ereignisse können mit Bedingungen verknüpft sein. Die an ein Ereignis geknüpften
Bedingungen müssen erfüllt sein, damit der erwartete Zustandswechsel erfolgen
kann.
Sächs. VWA
Fritzsche: Software-Engineering
Beispiel:
Zustände können auch Subdiagramme enthalten. Zustände können in
sequentielle
parallele
Unterzustände dekomponiert werden. Eine Verfeinerung ist jeweils nur auf einem
dieser beiden Wege möglich.
2.12 Aktivitäts-Diagramme
Das Aktivitäts-Diagramm ist eine spezielle Art des Zustandsdiagramms, das ausschließlich Aktivitäten und Übergänge zwischen diesen zeigt. Eine Aktivität ist einem
Zustand zugeordnet und repräsentiert eine andauernde interne Aktion. Mehrere von
einer Aktivität ausgehende Transitionen werden durch Bedingungen unterschieden:
17
Sächs. VWA
Fritzsche: Software-Engineering
18
Activity3
[x > 0]
Activity1
Activity2
[x = 0]
[x < 0]
Activity4
Activity2
Activity3
[x = 0]
Activity4
[x > 0]
[x < 0]
Activity5
Start- und Endzustand werden wie im Zustandsdiagramm dargestellt.
Ereignisse werden nicht dargestellt. Transitionen können geteilt und synchronisiert
werden (Parallelität):
Activity1
Activity2
Activity4
Activity3
Sächs. VWA
Fritzsche: Software-Engineering
3 Implementation von UML-Modellen
3.1 Von UML nach Java
Applikationen und Applets
Eine Java-Applikation ist ein Programm in einer virtuellen Maschinensprache (Java
Virtual Machine Specification). Ein solches Programm wird interpretativ durch den
Java-Interpreter java verarbeitet. Um z.B. das Programm MyApplication abzuarbeiten, ist in der Kommandozeile einzugeben:
java MyApplication
Der Name des auszuführenden Programmes wird dem Interpreter java als Kommandozeilenparameter übergeben.
Durch diese Art der Verarbeitung wird Plattformunabhängigkeit gewährleistet, die
Verfügbarkeit eines Interpreters auf jeder Plattform vorausgesetzt. Java-Applikationen besitzen eine Klassenstruktur, d.h. sie bestehen aus einer Anzahl zusammenwirkender Klassen.
Ein Java-Programm in der virtuellen Maschinensprache liegt in einer Datei vor. Dateiextension ist .class. Eine .class-Datei wird durch den Java-Compiler aus einer .java-Datei erzeugt, die den Programmtext enthält.
Beispiel: Die Anwendung MyApplication besteht aus einer Klasse, der Hauptklasse MyApplication. Der Programmtext könnte wie folgt aussehen:
public class MyApplication {
public static void main (String args[]){
System.out.println("Kommandozeilenparameter:");
for (int i = args.length - 1; i>=0; i--)
System.out.println(args[i]);
}
}
Die Hauptklasse einer Anwendung (z.B. MyApplication) muß die Methode
main() implementieren. Mit static gekennzeichnete Methoden oder Variablen
beziehen sich auf eine Klasse als Objekt, und nicht auf ein Instanzobjekt der Klasse.
Wir nennen sie Klassenmethoden bzw. Klassenvariablen. Für jede Methode ist ein
Ergebnistyp festzulegen. Wird dieser mit void angegeben, liefert die Methode keinen Ergebniswert.
Beim Programmaufruf können Kommandozeilen-Parameter an eine Applikation
übergeben werden. Im Beispiel kann über das String-Array args in der main-Methode auf solche Parameter zugegriffen werden.
Zur Verwaltung der Länge eines Arrays besitzt jedes Array das Feld length. Auf
dieses Feld wird wie auf eine Instanzvariable eines Objektes zugegriffen.
Strings sind immer Objekte, also keine Character-Arrays. Die Klasse String wird in
einer Klassenbibliothek bereitgestellt. Bei der Erzeugung von String-Objekten kann
eine Initialisierung mittels String-Literalen vorgenommen werden:
String s = new String("Kommandozeilenparameter:")
19
Sächs. VWA
Fritzsche: Software-Engineering
int, float, char, boolean bezeichnen elementare Datentypen (keine Klassen).
Zu jedem elementaren Datentyp gibt es eine korrespondierende Klasse.
Java-Programme können auf die Standard-Ein-/Ausgabe zugreifen. System ist eine
abstrakte Klasse. System.in ist eine Variable für die Standard-Eingabe. Analog ist
System.out eine Variable für die Standard-Ausgabe.
Beispiel für einen Aufruf:
java MyApplication huhu haha hoho
Kommandozeilenparameter:
hoho
haha
huhu
Applets
Applets sind Java-Anwendungen, die in HTML-Dokumente mittels eines AppletTags eingebunden werden können. Die gängigen Browser verfügen über eine JVM
zur Interpretation solcher Java-Anwendungen.
Beispiel:
<html>
<head>
<title>Applet-Demonstration</title>
<!-- (c)Hartmut Fritzsche, 20-Sept-1998-->
</head>
<body background=back_ms.gif text=#0000cc>
<h1>Lehrveranstaltung "Software Engineering"</h1>
<applet
codebase="file:/home/fritzsch/java/SE_LV"
code="ChboxDemo.class"
alt="Applet!!!"
width=500 height=300 align=bottom>
The Browser doesn't know the applet-tag.
</applet>
</body>
</html>
Ein Browser, der das Applet-Tag nicht kennt, überliest es. Alternative HTML-Elemente können in die Applet-Umgebung eingefügt werden. Kennt ein Browser das AppletTag im obigen Beispiel nicht, erscheint stattdessen "The Browser doesn't know the
applet-tag". Das Attribut ALT wird verwendet, um bei Textbrowsern anstelle des Applets alternativen Text zu zeigen. Mit dem Attribut CODE wird die Datei spezifiziert, in
der die Hauptklasse des Applets liegt.
Jede Klasse, die ein Applet realisiert, muss von der Klasse Applet abgeleitet sein,
d.h. von dieser Klasse erben (extends …). Jedes Applet besitzt die Methoden
init(), start(), stop() und destroy(), die standardmäßig keinen Code enthalten. Die Methoden stehen im Zusammenhang mit dem Lebenszyklus eines Applets.
Beispiel:
import java.applet.Applet;
import java.awt.*;
20
Sächs. VWA
Fritzsche: Software-Engineering
public class AppletDemo extends Applet{
String text;
public void init(){
System.out.println("init");
if ((text = getParameter("text")) == null)
text = "kein text-Parameter vorhanden";
System.out.println(text);
}
}
public void start(){
System.out.println("start");
}
public void stop(){
System.out.println("stop");
}
public void destroy(){
System.out.println("destroy");
}
public void paint(Graphics g){
g.drawString("Hello world !",90,25);
}
Ein Browser gibt Ausgaben auf der Standardausgabe über die "Java-Console" aus.
Ist das Applet während der Präsentation geändert worden, d.h es ist ein neues
.class-File erzeugt worden, muss der Applet-Viewer neu gestartet werden, um das
geänderte Applet zu präsentieren.
3.2 Ein Beispiel: Baum-Klassen
Als Beispiel sollen die im Abschnitt über Polymorphie betrachteten und modellierten
Unruhen nun implementiert werden. Getreu dem Klassenmodell programmieren wir
die Klassen Mobile, MobileA und Node.
public class Mobile{
Node root = new Node();
BinWTree lsucc,rsucc;
void insKeyWeight(int pkey,int pweight){
root.setKey(pkey);
root.setWeight(pweight);
}
void insLeft(Mobile tree){
lsucc = tree;
}
void insRight(Mobile tree){
rsucc = tree;
}
int weight(){
if (root.selWeight() == 0)
return( lsucc.weight() + rsucc.weight() );
21
Sächs. VWA
Fritzsche: Software-Engineering
else
return( root.selWeight());
}
}
boolean balancedp(){
if (root.selWeight() == 0)
return(
lsucc.balancedp()
&& rsucc.balancedp()
&& (lsucc.weight() == rsucc.weight()));
else
return(true);
}
void makebalance(){
}
class MobileA extends Mobile{
int larm,rarm;
void insLarm(int parm){
larm = parm;
}
void insRarm(int parm){
rarm = parm;
}
boolean balancedp(){
if (root.selWeight() == 0)
return(
lsucc.balancedp()
&& rsucc.balancedp()
&& (larm * lsucc.weight()
== rarm * rsucc.weight()));
else
return(true);
}
void makebalance(){
int s = larm + rarm;
if (root.selWeight() == 0){
lsucc.makebalance();
rsucc.makebalance();
if (!(this.balancedp())){
rarm = lsucc.weight()*s/this.weight();
larm = s - rarm;}
System.out.println(larm);
System.out.println(rarm);
}
}
}
class Node{
int key,weight;
int selWeight(){
return(weight);
}
int selKey(){
return(key);
}
void setWeight(int pweight){
weight = pweight;
22
Sächs. VWA
Fritzsche: Software-Engineering
}
}
void setKey(int pkey){
key = pkey;
}
Die Klasse UseMobile bietet eine beispielhafte Anwendung:
public class UseMobile {
public static void main(String args[]){
System.out.println("Hello world!");
Mobile m1 = new Mobile();
m1.insKeyWeight(1,0);
Mobile m2 = new Mobile();
m2.insKeyWeight(2,4);
Mobile m3 = new Mobile();
m3.insKeyWeight(3,0);
Mobile m4 = new Mobile();
m4.insKeyWeight(4,0);
Mobile m5 = new Mobile();
m5.insKeyWeight(5,1);
Mobile m6 = new Mobile();
m6.insKeyWeight(6,1);
Mobile m7 = new Mobile();
m7.insKeyWeight(7,2);
m4.insLeft(m5);m4.insRight(m6);
m3.insLeft(m4);m3.insRight(m7);
m1.insLeft(m2);m1.insRight(m3);
System.out.println(m1.weight());
System.out.println(m1.balancedp());
MobileA ma1 = new MobileA();
ma1.insKeyWeight(1,0);
MobileA ma2 = new MobileA();
ma2.insKeyWeight(2,3);
MobileA ma3 = new MobileA();
ma3.insKeyWeight(3,0);
MobileA ma4 = new MobileA();
ma4.insKeyWeight(4,0);
MobileA ma5 = new MobileA();
ma5.insKeyWeight(5,2);
MobileA ma6 = new MobileA();
23
Sächs. VWA
Fritzsche: Software-Engineering
ma6.insKeyWeight(6,1);
MobileA ma7 = new MobileA();
ma7.insKeyWeight(7,1);
ma4.insLeft(ma5);ma4.insRight(ma6);
ma4.insLarm(1);ma4.insRarm(2);
ma3.insLeft(ma4);ma3.insRight(ma7);
ma3.insLarm(1);ma3.insRarm(3);
ma1.insLeft(ma2);ma1.insRight(ma3);
ma1.insLarm(4);ma1.insRarm(3);
System.out.println(ma1.weight());
System.out.println(ma1.balancedp());
ma4.insLarm(4);
System.out.println(ma1.weight());
System.out.println(ma1.balancedp());
ma1.makebalance();
System.out.println(ma1.weight());
System.out.println(ma1.balancedp());
System.out.println("Bye world!");
}
}
Abarbeitung des (zuvor übersetzten) Programmes:
C:\WorkStation\SE>java UseMobile
Hello world!
8
true
7
true
7
false
2
4
1
3
4
3
7
true
Bye world!
3.3 Interfaces und Mehrfachvererbung
In Java gibt es (z.B. im Unterschied zu C++) keine Mehrfachvererbung. Statt dessen
gibt es sog. Interfaces, die aber reine Schnittstellen darstellen und keinerlei Implementierung enthalten. Interfaces definieren ausschließlich abstrakte Methoden und
Konstanten.
Eine Klasse kann ein oder mehrere Interfaces implementieren. Wenn eine Klasse
ein Interface implementiert, dann muss sie alle seine Methoden überschreiben. Die
24
Sächs. VWA
Fritzsche: Software-Engineering
Eigenschaft einer Klasse, ein Interface zu implementieren, wird an ihre Nachfahren
vererbt.
3.4 Implementation von Assoziationen und Aggregationen
Zur Implementation von Assoziationen und Aggregationen mit 1:n – Beziehungen
eignen sich Vektoren und Hash-Tabellen.
Ein Vektor ist in Java (als Instanz der Klasse Vector) ein eindimensionales dynamisches Array. „Dynamisch“ bedeutet hier, dass die Anzahl der Elemente zur Laufzeit
des Programms vergrößert werden kann. Der Klass Vector zugeordnete Methoden
sind addElement, insertElement, removeElement. Die Methode size liefert
als Wert die Anzahl der Elemente eines Vektors.
Hash-Tabellen bieten den statistisch gesehen schnellsten Zugriff auf Elemente einer
Elementsammlung und werden deshalb häufig eingesetzt. In ca. 70 – 90 % aller Fälle wird ein Direktzugriff möglich sein. In Java ist eine entsprechende Klasse Hashtable verfügbar.
3.5 Dynamische Modelle und Event-Handling
Ziel ist hier die Umsetzung von Zustandsdiagrammen in Java-Programme. Bei jeder
Mausbetätigung (auch Mausbewegung!) oder Tastatureingabe wird ein Objekt der
Klasse Event bzw. einer Subklasse dieser Klasse erzeugt. Den Programmkomponenten, die auf Events reagieren sollen, werden zur jeweiligen Event-Art passende
Listener hinzugefügt.
Die Programmierung der gewünschten Aktionen bei Eintreten bestimmter Ereignisse
erfolgt in sog. Handlern. Listener-Interfaces definieren solche Handler zur Behandlung von Events. Ein Listener kann mehrere Event-Quellen haben. Zu einer EventQuelle kann es andererseits auch mehrere Listener geben.
25
Sächs. VWA
Fritzsche: Software-Engineering
26
import java.applet.*;
import java.awt.event.*;
import java.awt.*;
public class AcEvDemo2 extends Applet implements ActionListener {
public void init() {
System.out.println("Hello world!");
Button bopen = new Button("open");
Button bclose = new Button("close");
bopen.addActionListener(this);
bclose.addActionListener(this);
add(bopen);
add(bclose);
System.out.println("I am waiting for events.");
}
public void actionPerformed(ActionEvent evt) {
if (evt.getActionCommand().equals("open")){
System.out.println("action in open");
}
if (evt.getActionCommand().equals("close")){
System.out.println("action in close");
}
}
}
4 Systemarchitekturen
4.1 Komponentenmodelle
Betrachtet man die logische Struktur eines objektbasierten Systems, so sieht man
Klassenstrukturen. Bei der Systemarchitektur wird dagegen häufig eine nicht objektbasierte Komponentenstruktur zugrunde gelegt. Zur Darstellung der Komponentenstruktur werden Komponentenmodelle verwendet. Komponentenmodelle werden in
der UML mit Komponentendiagrammen repräsentiert. Eine Komponente stellt eine
physikalische Programmeinheit dar, die als Quellcode, Objektcode oder ausführbares Programm vorliegen kann. Komponenten werden in Subsystemen (Paketen) organisiert.
Pakete (packages) werden zur Gruppierung von Modellelementen verwendet.
In Java umfasst ein Paket eine beliebige Anzahl von Compilationseinheiten. Pakete
können hierarchisch gegliedert sein. Dabei korrespondieren Paketnamen mit
Pfad-/Dateinamen.
Darstellung :
Sächs. VWA
Fritzsche: Software-Engineering
27
Subsystem1
Component1
Component2
4.2 Verteilungsmodelle
Das Verteilungsdiagramm ermöglicht die Modellierung expliziter physischer Strukturen. Es enthält Knoten, auf denen Prozesse ablaufen. Knoten werden durch Quader
dargestellt.
Client1
Server1
Component1
Client2
Component2
4.3 Objektserialisierung
Die Objektserialisierung dient der persistenten Speicherung von Laufzeitobjekten einer Java-Applikation zu einem bestimmten Zeitpunkt. Das Speichern in eine Datei
wird als „Serialisieren“ bezeichnet. Im Paket java.io existiert eine Klasse ObjectOutputStream, auf die die Methode writeObject anzuwenden ist. Zu serialisierende Objekte sind dieser Methode als Parameter zu übergeben. Das Wiederherstellen einer Objektwelt durch Lesen aus der zuvor serialisierten Objektwelt wird als
„Deserialisieren“ bezeichnet. Dazu ist die Methode readObject der Klasse ObjectInputStream anzuwenden.
Sächs. VWA
Fritzsche: Software-Engineering
5 Der Softwareentwicklungsprozess
5.1 Anwendungsfall-Analyse
Ein Anwendungsfall (use case) beschreibt die Interaktionen zwischen Anwendern
und dem Anwendungssystem, die notwendig sind, um einen Arbeitsgang durchzuführen. Im Wesentlichen sind Anwendungsfälle und Akteure zu identifizieren. Das
Darstellungsmittel der UML für Anwendungsfälle sind UseCase-Diagramme. Ein
UseCase-Diagramm zeigt die Beziehungen zwischen Akteuren (actors) und Anwendungsfällen in einem System. Das System wird durch ein Rechteck dargestellt, das
die Systemgrenzen zeigt.
Im UseCase-Diagramm können auch Import-Beziehungen (<<include>>) und Erweiterungen (<<extend>>) zwischen Anwendungsfällen gezeigt werden. Auch Generalisierung/Spezialisierung zwischen Anwendungsfällen kann modelliert werden.
5.2 Methodische Aspekte der Modellierung
In der Analysephase sind folgende Aktivitäten erforderlich:
• Zerlegung des Anwendungsbereiches in Unterbereiche
• Analyse und Spezifikation des geforderten Systemverhaltens
28
Sächs. VWA
Fritzsche: Software-Engineering
29
Während der Problembereichsanalyse werden zunächst „Geschäftsklassen“ modelliert. „Fachklassen“ beschreiben im Unterschied dazu implementierungs-technische
Sachverhalte.
Zur Entwicklung eines Objektmodells wird von RUMBAUGH folgendes Vorgehen empfohlen:
1. Objektklassen identifizieren
2. ein Data Dictionary vorbereiten
3. Assoziationen zwischen Objektklassen identifizieren
4. Attribute identifizieren und zu Objektklassen hinzufügen (Operationen erst spät beim
Spezifizieren des Zustandsmodells hinzufügen)
5. Klassen mittels Vererbung organisieren
6. Zugriffspfade testen
7. das Gesamtmodell in einem iterativen Prozess verfeinern
8. Klassen zu Paketen (Teilsystemen) gruppieren
5.3 Qualitätssicherung
Die Qualitätssicherung umfasst Planung/Durchführung von Qualitätssicherungsmaßnahmen (QSM) , die Kontrolle der Einhaltung von Standards (ISO 9000, ... )
und die Qualitätsbewertung anhand von Metriken. Es werden konstruktive und analytische QSM unterschieden. Zu den analytischen QSM zählen statische Analysen,
der symbolische Test und dynamische Analysen („Testen“). Zu den statischen Analysen zählen Kontrollfluss- und Datenflussanalyse sowie die Programmverifikation.
5.4 Projektmanagement und Prozessmodellierung
Das Projektmanagement (PM) umfasst alle Maßnahmen zur Planung und Verfolgung einzelner Projekte und von Projektfamilien. Zur Projektplanung zählen:
• Festlegung der Projektorganisation
• Personalplanung
• Meilenstein-/Terminplanung für alle Aktivitäten und Zuordnung zu Bearbeitern.
Die Projektverfolgung umfasst alle technisch-organisatorischen Maßnahmen zur Erreichung der Projektziele. Dazu zählen die Verfolgung von Meilensteinen, Terminen
und (Rest-) Aufwänden sowie die Kontrolle der Aktivitäten der Bearbeiter.
Grundlage der Projektmanagement-Aktivitäten bilden Dokumente spezieller Typen,
z.B. Aktivitätengraphen, Balkendiagramme usw. Gegenstand der Prozess-modellierung ist die Formalisierung und Computerunterstützung des Software-entwicklungsprozesses selbst. Neben Bausteinen und Ergebnissen müssen Aufgaben und Ressourcen verwaltet werden. Wichtig ist dabei die Konsistenz-sicherung.
5.5 Konfigurationsmanagement
Das Konfigurationsmanagement umfasst Aufgaben wie
• die Kontrolle der entwickelten Quellprogramme
• die Bereitstellung von „build“-Funktionalität
•
das Release-Engineering
Das Concurrent Versions System (CVS) ist ein Versionsverwaltungssystem, das das
Versionsmanagement auf der Ebene von Quellprogrammen unterstützt. Es ermöglicht die Aufzeichnung der Entwicklungsgeschichte von Programmdokumenten in
Projekten und unterstützt die Gruppenarbeit (check out –check in).
Sächs. VWA
Fritzsche: Software-Engineering
Neuere Versionsverwaltungssysteme sind Subversion und Mercurial. In Eclipse wird
Versionsverwaltung durch spezielle Plug-ins unterstützt (z.B. Mercurial:
http://www.javaforge.com/project/HGE).
Weitere Werkzeuge wie Ant und Maven dienen der Unterstützung des Build-Prozesses.
6 Wiederverwendung
6.1 Komponentenbasierte Softwareentwicklung - Frameworks
Klassen realisieren „Abstrakte Datentypen“. Sie verkörpern Objektfabriken, weil sie
Operationen zum Erzeugen von Exemplaren zur Verfügung stellen.
Wiederverwendung individueller Komponenten ist nicht kostenlos. Es entsteht Aufwand für das Ausfindigmachen nachnutzbarer Komponenten. OO-Sprachen allein
garantieren keine Verbesserung der Wiederverwendbarkeit.
Ein Framework ist eine Sammlung verschiedener individueller Komponenten
mit definiertem Kooperationsverhalten zur Lösung einer Aufgabe. Frameworks definieren in der Regel einen Großteil der Architektur. Wieder-verwendbare Architekturansätze standardisieren langfristig Anwendungs-gebiete.
Whitebox-Frameworks bestehen aus einer Anzahl unvollständig spezifizierter
Klassen, d.h. Klassen mit abstrakten Methoden. Diese abstrakten Methoden
heißen Einschubmethoden. Um ein Whitebox-Framework anzupassen, muß
der Programmierer die Implementation des Frameworks weitgehend kennen.
Blackbox-Frameworks gehen von einer Anzahl fertiger Komponenten aus.
Anpassungen des Frameworks werden durch Kompositionen der Komponenten erreicht, nicht durch Vervollständigung von Klassen.
6.2 Entwurfsmuster
Ein wesentlicher Beitrag zur Thematik der Entwurfsmuster wurde von E. Gamma
geleistet. Gamma et al. Haben einen Katalog mit 23 Entwurfsmustern beschrieben.
Bekannte Entwurfsmuster sind das „Beobachter“-Muster, das „Kompositum“-Muster
und das „Strategie“-Muster. Sie finden u.a. in der Model-View-Controler-Architektur
Anwendung.
Beobachter-Muster: Definiere eine 1-zu-n-Abhängigkeit zwischen Objekten, so dass
die Änderung des Zustandes eines Objektes dazu führt, dass alle abhängigen Objekte benachrichtigt und automatisch aktualisiert werden.
Kompositum-Muster: Füge Objekte zu Baumstrukturen zusammen, um Teil-GanzesHierarchien zu repräsentieren. Das Kompositionsmuster ermöglicht es Klienten, einzelne Objekte sowie Kompositionen von Objekten einheitlich zu behandeln.
Strategie-Muster: Definiere eine Familie von Algorithmen, kapsele jeden einzelnen
und mache sie austauschbar. Das Strategie-Muster ermöglicht es, den Algorithmus
unabhängig von ihn nutzenden Klienten zu variieren.
30
Sächs. VWA
Fritzsche: Software-Engineering
6.3 Grafische Benutzeroberflächen
In Java existiert eine sehr gute Unterstützung für die Entwicklung von Oberflächen
durch das „Abstract Window Toolkit“ (AWT) und das Paket „Swing“. Der Aufbau der
AWT-Klassenbibliothek ist ein Beispiel für die Anwendung des Entwurfsmusters
„Kompositum“.
Layout-Manager nehmen dem Anwender die Arbeit der absoluten Positionierung
von Komponenten in Containern ab. Sie definieren Regeln, nach denen Komponen-ten in einem Container platziert werden. Es gibt eine Vielzahl von einfach handhab-baren bis hin zu komfortablen Layouts: BorderLayout, FlowLayout, GridLayout, GridBagLayout, usw.
6.4 Die Model-View-Controller-Architektur
Das Model-View-Controller-Prinzip bietet einen Ansatz für die Architektur von Anwendungen, die aus einer grafischen Benutzeroberfläche, einem funktionalen Kern
und einer Datenverwaltung bestehen sollen. Ein Model-Objekt stellt das Anwendungsobjekt dar, das View-Objekt seine Bildschirmrepräsentation und das Controller-Objekt bestimmt die Möglichkeiten, mit denen auf Benutzereingaben reagiert
werden kann. View und Model werden durch den Aufbau eines Protokolls zur Benachrichtigung entkoppelt. Der Antwortmechanismus der Oberfläche wird in einem
Controller gekapselt.
Die MVC-Architektur verwendet die Entwurfsmuster Beobachter und Strategie und
Kompositum. Ein oder mehrere Beobachter melden sich beim Model-Objekt an und
werden von diesem benachrichtigt, sobald das Model-Objekt seinen Zustand ändert.
Das Model-Objekt liefert keine Daten an vorhandene Beobachter, diese holen sich
die Informationen vom Model-Objekt, die sie jeweils benötigen.
31
Herunterladen