Software Engineering - Fakultät Informatik/Mathematik

Werbung
Software Engineering II
Bachelor-/Diplomstudiengang Medieninformatik
Sommersemester 2015
► 2 SWS Vorlesung + 2 SWS Praktikum
► APL (BGA)
Alternative Prüfungsleistung (Belegarbeit)
→ Anfertigung, Dokumentation und Verteidigung des Gruppenbelegs
Prof. Dr. Hartmut Fritzsche
Fakultät Informatik/Mathematik
Büro: Z 342
Sprechzeit: Mittwoch 12.00 -13.00 Uhr
Tel. (0351) 462 2606
[email protected]
www.informatik.htw-dresden.de/~fritzsch
Aufbau der Lehrveranstaltung
►
umfasst die Module „SE I“ und „SE II“ (zwei Semester)
►
orientiert sich an den Phasen des
Softwareentwicklungsprozesses (SEP)
►
Nutzung einer Softwareentwicklungsumgebung (SEU) im Praktikum
Eclipse + TOPCASED + Mercurial + ...
►
Beginn mit thematischen Praktikumsveranstaltungen
►
Gruppenprojekt (2 – 4 Studierende) >> Dez. 2013 – Juli 2014
mit dem Ziel, eine lauffähige Anwendung zu entwickeln,
zu dokumentieren und zu verteidigen.
Inhalt
1.
Einführung: Ziele und Arbeitsmethoden der Softwaretechnik
2.
Der Softwareentwicklungsprozess (Überblick)
3.
Anforderungsanalyse / -definition
4.
Objektorientierte Modellierung
Unified Modeling Language (UML 2)
5.
von UML nach Java ...
6.
Entwurf und Implementation
7.
Konfigurationsmanagement
8.
Wiederverwendung und Evolution
9.
Musterarchitekturen
SE II
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
W. Pree
Komponentenbasierte Softwareentwicklung mit Frameworks.
dpunkt.verlag, 1997
I. Sommerville
Software Engineering.
Addison-Wesley, 8. Aufl. 2007
G. Popp
Konfigurationsmanagement mit Subversion, Ant und Maven
dpunkt.verlag, 2. Aufl. 2008
7
Konfigurationsmanagement
► Ziele des KM:
●
Im SEP entstehende Ergebnisse (Artefakte: Dokumente, Modelle, Code, ...)
sicher verwalten
●
Zugriffskontrolle für verteilt arbeitende Entwickler
●
Kontrolle über Veränderungen an Artefakten im Laufe der Entwicklung
► Das KM umfasst Aufgaben wie
● die Kontrolle der entwickelten Quellprogramme
● die Bereitstellung von „Build“-Funktionalität
● das Release-Engineering
► KM = Regelwerk, mit dem KM-Prozess beschrieben wird
Der KM-Prozess (Kernprozess)
► Auswahl der Konfigurationselemente
•
Betrachten von Typen von Konfigurationselementen (z.B. Quelltext)
•
Alle Instanzen der Konfigurationselemente zusammen bilden das
Softwareprodukt
Beispiel: Build-Skripte sind Konfigurationselemente,
JavaDoc-Dokumentationen (API) sind eher keine,
können aus kommentierten Quelltexten erstellt werden.
•
Typische Konfigurationselemente:
Quelltext
UseCases
Architektur-/Designdokumente
Schnittstellenverträge
Testspezifikationen und Testdaten
Build-Skripte
Installationsanleitung, Benutzerdokumentation
...
► Festlegung der Projektstruktur
•
Ist gleichbedeutend mit der Hierarchie der Verzeichnisse im Projekt
•
Empfehlung: separaten Ast für jedes Konfigurationselement
im Verzeichnisbaum
•
Verzeichnisse, die keine Konfigurationselemente enthalten,
sollen nur temporäre Dateien enthalten, die neu generiert werden können
Beispiel:
enthält temporäre Dateien
► Verwaltung der Konfigurationselemente
•
Instanzen der Konfigurationselemente werden im Repository gespeichert
( ≈ spezialisierte Datenbank)
•
Aufbau eines Repository entspricht der Projektstruktur, aber ohne
temporäre Ordner
•
Eine effektive Arbeit mit Werkzeugen ist nur möglich, wenn
herstellerspezifische Formate im Repository verwaltet werden können.
Repositories werden über eine Schnittstelle direkt in die Entwicklungswerkzeuge integriert.
•
Repositories setzen intern die Versionierung ein:
- nach jeder Änderung an einer Datei wird eine neue Version
im Repository gespeichert
- nach und nach entsteht eine Versionshistorie, alle jemals
vorgenommenen Änderungen werden dokumentiert
(Löschen als Spezialfall einer Änderung)
- der Prozess heisst Versionskontrolle
- Versionen einer Datei werden vom Repository durchnummeriert
•
Deltabildung:
- Werkzeuge ermitteln nur ein Delta zwischen zwei Versionen
und legen ein Delta im Repository ab (zur Erinnerung: diff-Befehl!)
- als „Anker“ dient eine komplette Dateiversion (erste oder letzte)
- es wird zwischen Vorwärtsdeltas und Rückwärtsdeltas
unterschieden
- moderne Systeme wie Subversion beherrschen auch
eine Deltabildung auf Byte-Ebene (alternativ werden
Komplettversionen gespeichert, was sehr speicherintensiv ist)
•
Check-out / check-in:
- im Projekt arbeitet man nicht mit Dateien im Repository,
sondern mit Arbeitskopien in einem lokalen Arbeitsbereich
(ebenfalls vom Versionsverwaltungssystem verwaltet)
- Repository liefert auf Anforderung eine Arbeitskopie (Check-out),
aktualisiert die Arbeitskopie bei Bedarf (Update)
liest Änderungen in das Repository ein (Check-in, Commit)
•
Parallele Änderungen an Dateien:
-
das Repository kontrolliert, ob mehrere Teammitglieder
parallel an derselben Datei arbeiten wollen oder gearbeitet
haben
-
Überprüfung vor Änderung: Lock-Modify-Unlock
Die Sperre erfolgt beim Check-out oder
(wie bei Subversion) durch separaten Lock-Befehl
Die Freigabe erfolgt beim Check-in oder
durch separaten Unlock-Befehl
- Überprüfung nach Änderung: Copy-Modify-Merge
Beim Check-in überprüft das Repository, ob eine Datei zwischenzeitlich von einem anderen Nutzer verändert wurde.
Wenn ja → Konflikt
Der Nutzer entscheidet bei Konflikten, ob seine Änderungen
mit der Version im Repository zusammenpassen.
Wenn Ja → Merge + Check-in
Merges funktionieren nur für zeilenbasierte Textdateien !
•
Tags und Baselines:
- „Schnappschüsse“: Versionsnummern schlecht zu merken
-
ein Tag markiert die zu einem Zeitpunkt gültige Version aller
Dateien im Repository mit frei wählbarem Bezeichner
Der Zustand des Repositories kann durch Angabe des Tags
abgerufen werden.
- eine Baseline (Bezugskonfiguration) bezeichnet einen
hervorgehobenen Tag.
(= freigegebenes Zwischenergebnis des Systems,
es muss ein gesicherter Status vorliegen)
Die Vorbereitungsphase einer Baseline wird mit einem
Code Freeze begonnen.
- als Release wird der Zustand des Systems bezeichnet, in dem
es in den produktiven Einsatz geht.
Anwender arbeiten mit einem Release.
Für jedes Release wird eine Baseline erstellt.
•
Branches:
- Projekte mit überschaubarem Zeitraum können
lineare Entwicklungspfade haben.
→ Schwierige Ressourcenplanung bei größeren Projekten
-
größere Projekte sollten mit verzweigten oder parallelen
Entwicklungspfaden (Branches) arbeiten.
- Releases werden in einem separaten Relese-Branch
vorbereitet, ein Teil des Teams arbeitet im Hauptentwicklungspfad (Trunk ) weiter.
Relese-Branch und Trunk werden nach dem Release
wieder zusammengeführt.
Abbildung nach G. Popp
► Aufbau eines Build-Prozesses
Automatisierung der Schritte zur Erstellung eines Produkts:
1. Quellelemente ermitteln
2. Produkt aus den Quellelementen erstellen
→ Aufrufe Compiler, Linker, Generatoren
3. Produkt prüfen
→ automatisierte Modultests
(noch kein Integrationstest möglich)
4. Produkt ausliefern
→ Erstellen eines Auslieferungspakets (ear-/war-Dateien)
5. Ergebnisse dokumentieren
→ Schritte des Build in Log-Datei dokumentieren
Unterscheidung: Entwickler-Build, Integrations-Build, Release-Build
Umsetzung des Build-Prozesses:
• Basis der Automatisierung bilden Skripte, die interpretativ
verarbeitet werden (Ant, Maven)
• Es werden Shell-Skripte zum Starten/Stoppen von Web- oder
Applikationsservern verwendet (Nachteil: Plattformabhängigkeit)
• Integrierte Umgebungen bieten Build & Run-Funktionalität:
→ Die Funktionalität ist komfortabel, aber kein Ersatz für
Projektautomatisierung mit Skripten!
Versionsverwaltungssysteme (KM-Werkzeuge)
► Versionsverwaltungssysteme stellen dem KM-Prozess ein Repository
zur Verfügung
► ermöglichen die Aufzeichnung der Entwicklungsgeschichte von
Programmdokumenten in Projekten und unterstützen die Gruppenarbeit
(check-out – check-in).
► Das Concurrent Versions System (CVS) ist ein System, das das VersionsManagement auf der Ebene von Quellprogrammen unterstützt (Open Source).
→
→
→
keine Deltas auf der Ebene von Binaries!
nur Dateien versionierbar, keine Verzeichnisse
keine Unterstützung von Transaktionen
► Subversion (Open Source) ist ein seit 2004 verfügbares Nachfolgesystem zu CVS.
Client-Server-Architektur von Subversion:
Abbildung nach G. Popp
Beispiel: Windows-Explorer als svn-Client (mit tortoisesvn)
Eclipse mit
subclipse als svn-Client
► Mercurial (Open Source) ist als Plug-in zu Eclipse verfügbar.
●
Dezentrale Verwaltung eines Repositorys:
→ Das Repository liegt als Clone auf dem lokalen Rechner
→ Jedes Repository (.hg) verwaltet die gesamte Historie
→ Arbeitsverzeichnis enthält aktuelle Verzeichnisse/Dateien + .hg
→ Clone überträgt Repositorien komplett
→ Änderungen an Dateien werden zu Changeset zusammengefasst,
ein Changeset wird bei Commit zu neuer Revision
→ Das Anpassen unterschiedlicher Repositorien erfolgt mittels
Push/Pull und Merge
●
Ein Topcased- oder Java-Projekt kann zusätzlich unter Mercurial gestellt werden.
→ HgEclipse
Quelle: http://mercurial.selenic.com/wiki/GermanUnderstandingMercurial
Wenn Alice jetzt ein Pull ausführt, sind beide Repositorien synchron.
EclipseMercurial - Installation mittels Update-Manager
Projekt unter Mercurial stellen:
Projekt unter Mercurial gestellt:
Im X-Verzeichnis
wurde ein .hg angelegt
(nicht sichtbar)
Commit:
erzeugt neues
changeset
Historie nach dem „Befüllen“:
Ändern im Arbeitsverzeichnis + Historie:
Neuer Branch:
Ant
http://ant.apache.org
►
dient zur Umsetzung eines Build-Prozesses
►
Nachfolger von make, Open Source
►
als plattformunabhängiges Werkzeug konzipiert
►
basiert als Werkzeug auf Java, benötigt zur Ausführung ein JDK
►
Ant-Skripte werden als XML-Dateien geschrieben
►
passt plattformspezifische Angaben im Skript an
(z.B. Dateipfade)
►
beherrscht inkrementelle Builds
Architektur von Ant:
Abbildung nach G. Popp
Aufbau eines Ant-Build-Skriptes
●
Oberstes Element beschreibt ein Projekt
●
Es folgen Schritte in Form von Zielen (Targets)
●
Name des auszuführenden Zieles wird Ant als Parameter übergeben
●
Jedes Ziel besteht aus einer oder mehreren Funktionen (Tasks)
●
Die Funktionen werden von Ant oder externen Bibliotheken bereitgestellt.
●
Datentypen (Types) stellen Variablen dar, mit denen Ziele und Variablen
parametrisiert werden
●
Datentypen sind einfache Name – Wert – Paare … bis ... komplexe Typen
Beispiel:
Properties definieren
●
Fest kodierte Werte vermeiden
●
Konstanten in Form von Properties definieren
●
Name – Wert – Paare, Werte können nicht mehr geändert werden
●
Properties gelten global im gesamten Skript
●
Es gibt sechs verschiedene Arten, Properties zu definieren,
hier Beschränkung, z.B.
<property file= «dateiname» />
●
Werte werden mittels ${ ...
●
Es gibt vordefinierte Properties
} zugegriffen
lädt Properties
aus Datei
Vordefinierte Properties:
${basedir}
Wert des basedir-Attributs aus
project-Element
${ant.file}
Pfad des Build-Skriptes
${ant.version}
Version von Ant
${ant.project.name} Name des Projekts im project-Element
${ant.java.version} Version der JVM, die Ant ausführt
Alle Java-System-Properties, z.B ${user.home}
Init-Ziel aus dem Jamus-Build-Script:
Die Auswahl von Dateien erfolgt über Filesets.
Fielesets enthalten Patternsets und/oder Selektoren
Ein Patternset-Element selektiert Dateien mittels Einschluss- oder
Ausschlussbedingungen
<patternset>
<include name = «suchmuster» />
<exclude name = «suchmuster» />
</patternset>
Kein javac, zuvor schon übersetzt !
Maven
►
Produkt der Apache Software Foundation (Jakarta-Projekt)
►
Werkzeug zur Durchführung des Build-Prozesses
►
Modellbasierter deklarativer Ansatz:
Metadaten des Projekts werden in einem Modell beschrieben
→ Projektmodell (POM), Datei pom.xml im Projektverzeichnis
►
legt automatisch den Build-Prozess fest,
trifft Annahmen über dessen Ablauf,
nur auf oberster Stufe anstoßen (hoher Automatisierungsgrad!)
►
Verwaltung der Abhängigkeiten zu externen Bibliotheken
→ Maven-Repositorien (keine Versionierung)
►
unterstützt die Erstellung der Projektdokumentation
Architektur von Maven:
Abbildung nach G. Popp
Benutzung von der Kommandozeile:
► Download zip-Archiv von http://maven.apache.org/download
und in Verzeichnis entpacken
► Version Maven 3.0.3
► Umgebungsvariable MAVEN_HOME definieren
→ Ref. auf Maven-Verzeichnis
► Umgebungsvariable PATH um $MAVEN_HOME/bin ergänzen
► Umgebungsvariable JAVA_HOME setzen
► Funktionsfähigkeit mit mvn -version prüfen
Benutzung in Eclipse:
► Plug-in bereitstellen von http://m2eclipse.sonatype.org/sites/m2e
Umsetzung eines Build-Prozesses mit Maven
► Erfassung des Projektmodells in pom.xml
<!-- Projektmodell für MyProject -->
<project>
<!-- allgemeine Angaben zum Projekt -->
<groupID> HTWD </groupID>
<artifactID>myproject</artifactID>
<packaging>jar</packaging>
<name> MyProject</name>
<url>http://xyz </url>
<!-- Properties -->
<!-- Anpassung des Standard- Build-Prozesses -->
<!-- Einbindung externer Bibliotheken -->
< dependencies>
</dependencies>
</project>
► Das POM enthält keine aufrufbaren Ziele
► Ein Maven Build-Prozess besteht aus einer Reihe von
standardisierten Build-Phasen
► Namen der Phasen und Bedeutung
→ Build Lebenszyklus
► Die Abarbeitung der Pasen erfolgt immer von oben nach unten
→ meistens nur Teil der Phasen ausgeführt
► Den einzelnen Phasen müssen Build-Ziele zugeordnet werden
(Lifecycle-Mapping)
► Ausgangspunkt ist der Artefakt aus <packaging>--Element
► Es gibt eine vollständige Referenz der Lifecycle-Mappings
► Aufruf des Compilers:
mvn
compile
► Maven führt alle übergeordneten Phasen des Lebenszyklus aus.
→ Process Resources
→ laden des Plug-ins maven-compiler-plugin und Ausführen
des zugeordneten Build-Zieles compile
► Plug-ins werden im Maven-Repository verwaltet und von dort in den
Build-Prozess eingebunden
Zustandsbasiertes Testen mit Junit und JUnitDoclet
Blackboxtest
→ Unit-Test
→ Klassentest
→ Spezifikationsbasierter (funktioale)r Test
→ Äquivalenzklassen-Bildung
Testziel: Jede Operation (Methode) in jedem Zustand wenigstens einmal
Ausführen.
→ Generalisierung von Zuständen notwendig
r
Integrationstest
[
]
Javadoc – Generieren von Dokumentationen
► Homepage:
http://www.oracle.com/technetwork/java/javase/
documentation/javadoc-137458.html
► Software-Dokumentationswerkzeug, kommt mit JDK (Kommandozeile)
►
javadoc generiert aus Java-Quelltexten standardmäßig
HTML-Dateien (API)
►
erhält beim Aufruf Angaben über die zu dokumentierenden Quelltexte
►
parst Quelltexte und erkennt Javadoc-Kommentare
/**
*
*
*/
►
Javadoc-Kommentare können Javadoc-Tags enthalten
/**
* @author max moritz
* @version 1.0
*
*/
► mittels Taglets kann der Tag-Wortschatz von Javadoc erweitert werden
► ein Doclet erzeugt die Ausgabe, es existieren Doclets für die
Ausgabe in HTML, RTF, XML, PDF, ...
Tag & Parameter
Ausgabe
Verwendung in
@author name
beschreibt Autor
Klasse, Interface
@version version
erzeugt einen Versionseintrag, max. 1 x
pro Klasse/Interface
Klasse, Interface
@see reference
erzeugt link auf anderes Element der
Dokumentation
Klasse, Interface,
Instanzvariable, Methode
@param name description
Parameterbeschreibung
Methode
@return description
Returnwert
Methode
@exception classname description
Beschreibung einer Exception
Methode
@throws classname description
Beschreibung einer Exception
Methode
@depricated description
veraltete Methode
Methode
{@inheritDoc}
Kopiert Beschreibung aus überschriebener Überschreibende
Methode
Methode
{@link reference}
Link zu einem anderen Symbol
Klasse, Interface,
Instanzvariable, Methode
{@value
…
}
Gibt den Wert eines konstanten Feldes
zurück
Statisches Feld
{@code
…
}
formatiert Text buchstabengetreu mit dem
Quelltextzeichensatz entsprechend
<code>
Klasse, Interface,
Instanzvariable, Methode
… }
unterdrückt die Interpretation von HTMLoder Javadoc-Tags
Klasse, Interface,
Instanzvariable, Methode
{@literal
Beispiel:
Generieren der Dokumentation:
javadoc [options] [packagenames] [sourcefiles] [@files]
Beispiel:
Zusätzlich:
-version -author
Erzeugte Dateien:
Doclets
► sind in Java geschriebene Programme
► nutzen die Doclet-API
(lib/tools.jar des SDK in den classpath aufnehmen,
enthält Implementierungen der Doclet-API-Interfaces)
http://docs.oracle.com/javase/1.4.2/docs/tooldocs/javadoc/doclet/index.html
► spezifizieren Inhalt und Format der Ausgaben des Javadoc-Tools
(Standard: Generierung der API-Dokumentation in HTML
► Schritte, um ein eigenes Doclet zu erzeugen:
- Java-Programm MyDoclet erstellen
(Interfaces der Doclet-API bereitstellen:
import com.sun.javadoc.*,
Eintrittspunkt in MyDoclet ist eine Methode
public static boolean start(RootDoc root) { … } )
- Doclet-Programm MyDoclet übersetzen mit javac
- javadoc -doclet MyDoclet ...
Beispiel:
import com.sun.javadoc.*;
public class ListClass {
public static boolean start(RootDoc root) {
ClassDoc[] classes = root.classes();
for (int i = 0; i < classes.length; ++i) {
System.out.println(classes[i]);
}
return true;
}
}
aus:
http://download.oracle.com/javase/1.4.2/docs/tooldocs/javadoc/overview.html
8
Wiederverwendung und Evolution
8.1
Individuelle Komponenten: Module und Klassen
8.2
Komponentenbasierte Softwareentwicklung:
Frameworks
8.3
Entwurfsmuster
8.1
Individuelle Komponenten: Module und Klassen
►
Module repräsentieren Abstrakte Datenstrukturen (ADS)
►
Klassen repräsentieren Abstrakte Datentypen (ADT)
►
ADT erweitern ADS um Mittel zur Objekterzeugung (Objektfabriken)
►
Module werden bei der Wiederverwendung leicht modifiziert
►
Klassen können abgeleitet werden (Vererbung – keine Änderung
des bestehenden Quelltextes)
►
►
Objektbasierte
ObjektbasierteSprachen
Sprachen (z.B.
(z.B.Java)
Java)
verbessern
verbesserndas
dasModulkonzept
Modulkonzept (z.B.
(z.B.MODULA
MODULA2)2)
►
W. individueller Komponenten ist nicht kostenlos
(Ausfindigmachen, Schnittstellen verstehen, Wartung der Bibliotheken)
►
Objekt-basierte Sprachen allein garantieren keine Verbesserung
der W.
Studie zu NASA-Projekten:
12 % Änderung verursachen 55 % der Kosten
relativ zu Neuentwicklung
Bibliotheken:
1)
B. mit Top-down-Routinen bzw. Klassen
Anwendungsarchitektur
...
2)
Anwendungsprogramm
Bibliotheksroutinen
B. mit Routinen im Callback-Verfahren
...
Anwendungsarchitektur
Anwendungsprogramm
Bibliotheksroutinen
8.2
Komponentenbasierte Softwareentwicklung:
Frameworks
Framework:
Sammlung individueller Komponenten mit definiertem
Kooperationsverhalten zur Lösung einer Aufgabe
Whitebox-Framework:
Anpassung durch Subklassenbildung + Compilation
Blackbox-Framework:
Anpassung zur Laufzeit durch unterschiedliche
Instanziierung
Whitebox-Framework
Einschubmethode
in der Klasse A,
„abstract“
Der Programmierer muss die
Implementation des
Frameworks bis zu einem
gewissen Grade kennen
Blackbox-Framework
Es existiert eine Anzahl fertiger Komponenten
Änderungen durch Komposition der Komponenten (nicht durch Programmierung)
Beispiel:
Beispiel: Framework
Frameworkvor
vorund
undnach
nachder
derSpezialisierung
Spezialisierung
Instanzen einsetzen
►
► Aus
Auseinem
einemWhitebox-Framework
Whitebox-Frameworkentwickelt
entwickeltsich
sich
mit
mitzunehmendem
zunehmendemReifegrad
Reifegradein
einBlackbox-Framework
Blackbox-Framework
►
► Gängige
GängigeFrameworks
Frameworkssind
sind
weder
wederreine
reineWhiteboxWhitebox-noch
nochreine
reineBlackbox-Frameworks
Blackbox-Frameworks
Wie konstruiert man Frameworks ?
→
am Beispiel (nach Wolfgang Pree):
- Framework „Diskrete Simulation“ entwerfen
- Anwendung zur Simulation einer Kasse in einem Supermarkt
- Anwendung zur Simulation eines Parkhauses
Beispiel: Diskrete Simulation von Ereignissen
●
●
●
Zentrale Elemente: Ereignisse mit zugeordneter Zeit
(Beispiel Supermarkt: Eintreffen eines Kunden)
Ereignisse werden durch Zufallsgenerator erzeugt
Die Simulation entwickelt sich in Richtung der Zeitachse und
sammelt statistische Informationen
Actor:
Paar Ereignis – Aktion
Aktoren wissen, wie sie auf erhaltene Nachrichten zu
reagieren haben.
In time ist der Zeitpunkt des Ereignisses gespeichert
commit() kapselt die Funktionalität des Actors.
Die Simulation ruft commit() auf, wenn die Eintrittszeit des Ereignisses
erreicht ist.
simulate
iteriert über actors
- der aktuelle Zeitpunkt wird auf Zeitpunkt des Actors eingestellt
- commit() des Actors wird aufgerufen
Simulation endet, wenn Simulationszeit duration verbraucht ist.
schedule
fügt einen Actor entsprechend Eintrittszeitpunkt seines Ereignisses
in SortedQueue ein.
reset
SortedQUeue wird gelöscht, Simulationszeit zurückgesetzt (time=0).
...
...
Die
DieKlasse
Klasse Simulation
Simulation realisiert
realisierteine
eineabstrakte
abstrakteSimulation
Simulation
auf
der
Basis
des
Protokolls
der
Klasse
Actor
auf der Basis des Protokolls der Klasse Actor
Beispiel:
Whitebox-Framework → Blackbox-Framework
Registrierkasse im Supermarkt (convenience store)
Kunden
Customer
Kundengenerator
CustomerGenerator
Kasse
SimpleServiceStation
public class SimpleServiceStation {
public class SimpleServiceStation {
...
...
public void requestService(Customer c){
public void requestService(Customer c){
if (Warteschlange ist leer )
if (Warteschlange ist leer )
c.activate()
c.activate()
// Bediener verarbeitet die Kundenanfrage
// Bediener verarbeitet die Kundenanfrage
else
else
waitingLine.enqueue(c);
waitingLine.enqueue(c);
// Erstellen von Statistiken über die Warteschlange
// Erstellen von Statistiken über die Warteschlange
...
...
}
}
public void free(){
public void free(){
Actor actor;
Actor actor;
// Erstellen von Statistiken über die Warteschlange
// Erstellen von Statistiken über die Warteschlange
...
...
if (Warteschlange enthält Kunden )
if (Warteschlange enthält Kunden )
actor = waitingLine.dequeue();
actor = waitingLine.dequeue();
if (actor instanceof Customer)
if (actor instanceof Customer)
((Customer)actor).activate();
((Customer)actor).activate();
}
}
}
}
...
...
}
}
...
...
...
...
...
...
schedule
public class ConvenienceStoreSim {
public class ConvenienceStoreSim {
...
...
public void simulate(int avrgServiceDuration,
public void simulate(int avrgServiceDuration,
int arrivalRate, int duration){
int arrivalRate, int duration){
SimpleServiceStation station;
SimpleServiceStation station;
Simulation simulation;
Simulation simulation;
CustomerGenerator generator;
CustomerGenerator generator;
simulation = new Simulation();
simulation = new Simulation();
station = new SimpleServiceStation(simulation,
station = new SimpleServiceStation(simulation,
arrivalRate,
arrivalRate,
AvrgServiceDuration, …)
AvrgServiceDuration, …)
generator = new
generator = new
CustomerGenerator(0,station,simulation);
CustomerGenerator(0,station,simulation);
simulation.schedule(generator,0);
simulation.schedule(generator,0);
// mit Erzeugung von Kunden beginnen
// mit Erzeugung von Kunden beginnen
simulation.simulate(duration);
simulation.simulate(duration);
}
}
}
...
...
}
station.provideStatistics();
station.provideStatistics();
Entwurfsüberlegungen
►
Schwachstelle: enge Kopplung zwischen CustomerGenerator, Customer
und SimpleServiceStation.
→
→
►
Service-Station mit zwei Bedienern ?
Ausfall eines Bedieners?
Mittel, um Frameworks flexibler gestalten zu können
→
→
→
→
Schablonenmethoden und Einschubmethoden
Entkoppeln CustomerGenerator – Customer
Flexibilität durch Komposition
Skalierbarkeit von Einschubmethoden
►
Platzierung von Einschubmethoden
→ Schablonenmethoden rufen Einschubmethoden auf.
Schablonenmethode
Einschubmethode
Klasse MySimulation in der Anwendung DiskSim2
►
Entkopplung der Klassen CustomerGenerator und Customer
→ Das Verhalten kann durch die Definition von Unterklassen
verändert werden.
→ CustomerGenerator wird durch ActorGenerator ersetzt
Originalentwurf:
Originalentwurf:
public class CustomerGenerator extends Actor {
public class CustomerGenerator extends Actor {
...
...
public void commit(){
public void commit(){
Customer c= new Customer( … );
Customer c= new Customer( … );
station.requestService(c);
station.requestService(c);
...
...
}
}
...
...
}
}
Entwurf mit Einschubmethode:
Entwurf mit Einschubmethode:
public class ActorGenerator extends Actor {
public class ActorGenerator extends Actor {
...
...
public void commit(){
public void commit(){
Actor a= makeActor();
Actor a= makeActor();
station.requestService(a);
station.requestService(a);
...
...
}
}
public void makeActor(){
public void makeActor(){
Return new Customer( … );
Return new Customer( … );
}
}
...
...
}
}
►
Wenn Schablonen- und Einschubmethoden sich in einer Klasse
befinden, kann Verhalten nur durch die Definition weiterer
Unterklassen verändert werden.
→ Damit sind Anpassungen zur Laufzeit nicht möglich.
Lösung: Flexibilität durch Komposition
Einschubmethoden
Einschubmethodenerlauben
erlaubenflexible
flexibleAnpassungen
Anpassungenzur
zurLaufzeit,
Laufzeit,
wenn
ihre
Klasse
mit
der
Klasse
abstrakt
gekoppelt
ist,
wenn ihre Klasse mit der Klasse abstrakt gekoppelt ist,
die
diedie
diezur
zurEinschubmethode
Einschubmethodegehörende
gehörendeSchablonenmethode
Schablonenmethodeenthält
enthält
Beispiel:
Beispiel:Im
ImOriginalansatz
Originalansatzwurde
wurdedie
dieabstrakte
abstrakteMethode
Methode
enqueue()
der
Klasse
Queue
in
Unterklassen
enqueue() der Klasse Queue in Unterklassenüberschrieben,
überschrieben,
die
auf
diese
Weise
verschiedene
Warteschlangen
die auf diese Weise verschiedene Warteschlangenrealisieren.
realisieren.
→
Schablonenmethode
enqueue()
in
Queue,
→
Schablonenmethode enqueue() in Queue,
die
dieAuswahl
Auswahlwird
wirdQPolicy-Objekt
QPolicy-Objektübertragen
übertragen
→
Beim Umschalten der QPolicy-Instanz muss explizit für
Konsistenz gesorgt werden!
Wird z.B. von FIFOQueue auf SortedQueue umgeschaltet,
müssen Objekte entsprechend Zeitattribut neu geordnet werden,
die ursprüngliche Ordnung muss gespeichert werden, um sie
ggf. wieder herzustellen.
Einfachste Art der Konsistenzhaltung: Schlange leer!
►
Skalierbarkeit von Einschub-Methoden
→ was Schablonenmethode und was Einschub-Methode ist, ist relativ
Schablonenmethode
Einschubmethode
commit() von
ActorGenerator
→
makeActor()
simulate() von
Simulation
→
commit()
→ Im Idealfall nur elementarste Einschubmethoden überschreiben,
um Verhalten der alles umfassenden Schablonenmethode zu
beeinflussen
Muster für Kombinationen von Einschubmethoden:
H
-
Hook-Klasse = Klasse, die Einschubmethode enthält
T
-
Template-Klasse = Klasse die Schablonenmethode enthält
TH
Vereinigungsmuster =
Schablonenklasse u. Einschubklasse in einer Klasse vereinigt
T–H
Trennungsmuster =
abstrakte Kopplung der Klassen
→ Das Verhalten von T-Objekten kann durch das Einsetzen
unterschiedlicher H-Objekte geändert werden
→ Ein T-Objekt verweist auf ein H-Objekt
(Nachrichtensenden ist notwendig)
8.3
Entwurfsmuster
• Entwurfsmuster sind typischerweise in Anwendungen vorkommende Kombinationen
von Klassen/Objekten zu größeren Einheiten
•
aus Erfahrungen abstrahiert
•
zur Nachnutzung bestimmt
•
unabhängig von der Programmiersprache
• Gamma et al. haben einen Katalog von 23 Entwurfsmustern beschrieben.
→
●
Alphabetische Auflistung /Klassifikation
Anwendungsbeispiel: MVC-Architektur
→
verstehen, welche Muster eingesetzt werden
Grundlegende Elemente von Mustern
• Muster-Name
1-2 Wörter, erweitert das Entwurfsvokabular
Zweck.
Zweck.
• Problembeschreibung
Problem und Anwendungskontext werden erklärt
• Lösungsbeschreibung
abstrakte Beschreibung eines Entwurfsproblems,
kein konkreter Entwurf, keine konkrete Implementierung
• Konsequenzen
Kosten-Nutzen-Verhältnis von Mustern abwägen
Auswirkungen auf Flexibilität, Erweiterbarkeit, Portabilität
Erzeugungsmuster
Strukturmuster
Verhaltensmuster
Fabrikmethode
Adapter
Interpreter
Klassen-basiert
Abstrakte Fabrik
Brücke
Schablonenmethode
Instanzen-basiert
Erbauer
Kompositum
Zuständigkeitskette
Prototyp
Dekorierer
Kommando
Singleton
Fassade
Iterator
Fliegengewicht
Vermittler
Stellvertreter
Memento
Beobachter
Zustand
Strategie
Besucher
Beobachter (Observer)
[ Verhaltensmuster, objektbasiert ]
Definiere eine 1-zu-n-Abhängigkeit zwischen Objekten, so dass die Änderung
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
des Zustandes eines Objektes dazu führt, dass alle abhängigen Objekte
benachrichtigt und automatisch aktualisiert werden.
benachrichtigt und automatisch aktualisiert werden.
Beispiel:
Zeitgeber
- konkrete Subjektklasse
- benachrichtigt Beobachter jede Sekunde
public class Zeitgeber extends Subject {
public class Zeitgeber extends Subject {
int gibStunde(){ };
int gibStunde(){ };
int gibMinute(){ };
int gibMinute(){ };
int gibSekunde(){ };
int gibSekunde(){ };
void tick(){
void tick(){
// aktualisiert internen Zustand des Zeitgebers
// aktualisiert internen Zustand des Zeitgebers
benachrichtige();
benachrichtige();
}
}
}
}
public class Digitaluhr extends Beobachter {
public class Digitaluhr extends Beobachter {
Public void aktualisiere(){
Public void aktualisiere(){
// überschreibt Operation der Beobachterklasse
// überschreibt Operation der Beobachterklasse
}
}
}
}
- das Beobachter-Muster ermöglicht es, Beobachter und Subjekte unabhängig
voneinander zu modifizieren
- Subjekte und Beobachter können einzeln wiederverwendet werden
- neue Beobachter können ohne Änderung des Subjekts hinzugefügt werden
Kompositum (Composite)
[ Strukturmuster, objektbasiert ]
Füge Objekte zu Baumstrukturen zusammen, um Teil-Ganzes-Hierarchien zu
Füge Objekte zu Baumstrukturen zusammen, um Teil-Ganzes-Hierarchien zu
modellieren. Das Muster ermöglicht es Klienten, einzelne Objekte sowie
modellieren. Das Muster ermöglicht es Klienten, einzelne Objekte sowie
Kompositionen von Objekten einheitlich zu behandeln.
Kompositionen von Objekten einheitlich zu behandeln.
Implementierung:
- explizite Referenzen auf Elternobjekte
(um sich in der Hierarchie nach oben zu bewegen)
- Blatt- und Kompositionsklassen vor Klienten verstecken
Beispiel: Grafik-Objekte in Bibliotheken
- alle Klienten verwenden nur die Schnittstelle von Component
- der Klient wird einfacher, er kann zusammengesetzte und elementare Objekte
gleich behandeln
- es ist einfach, neue Arten von Komponenten einzufügen
Proxy / Stellvertreter (Proxy)
[ Strukturmuster, objektbasiert ]
Kontrolliere den Zugriff auf ein Objekt mit Hilfe eines vorgelagerten StellvertreterKontrolliere den Zugriff auf ein Objekt mit Hilfe eines vorgelagerten StellvertreterObjekts.
Objekts.
create
- der Proxy leitet Befehle an das echte Objekt weiter
- ein Remote-Proxy verbirgt die Tatsache, dass sich ein Objekt in einem
anderen Adressraum befindet
- ein virtuelles Proxy dient der Optimierung
- Schutz-Proxies ermöglichen die Durchführung zusätzlicher Verwaltungsaufgaben
beim Zugriff auf das Objekt
Fassade (Facade)
[ Strukturmuster, objektbasiert ]
Bietet eine einheitliche, einfache Schnittstelle zu einer Menge von Schnittstellen
Bietet eine einheitliche, einfache Schnittstelle zu einer Menge von Schnittstellen
bzw. Klassen (Paket).
bzw. Klassen (Paket).
Die Fassadenklasse definiert eine abstrakte Schnittstelle, um die Benutzung des
Die Fassadenklasse definiert eine abstrakte Schnittstelle, um die Benutzung des
Pakets zu vereinfachen.
Pakets zu vereinfachen.
Die Facade weiß, welche Klassen
des Pakets für die Bearbeitung einer
Botschaft zuständig sind und
delegiert Botschaften an die
zuständige Klasse.
Keine neue Funktionalität!
- die Klienten kommunizieren mit dem Paket, indem sie Botschaften an die
Fassade schicken, welche diese dann an das zuständige Objekt
innerhalb des Pakets weiterleitet
- das Fassaden-Muster reduziert die Anzahl der Klassen, welche den Klienten
bekannt sein müssen und vereinfacht die Benutzung des Systems
- die lose Kopplung erleichtert es, Pakete auszutauschen und erleichtert deren
unabhängige Implementierung
- bei Bedarf können Klienten die Fassade umgehen und direkt auf Klassen des
Pakets zugreifen.
Adapter (Adapter, Wrapper)
[ Strukturmuster, objektbasiert ]
Passe die Schnittstelle einer Klasse an eine andere, von Kunden erwartete
Passe die Schnittstelle einer Klasse an eine andere, von Kunden erwartete
Schnittstelle an. Zur Anpassung eines Interfaces an ein anderes wird ein
Schnittstelle an. Zur Anpassung eines Interfaces an ein anderes wird ein
Adapterobjekt verwendet.
Adapterobjekt verwendet.
Delegation
realize
Beispiel: „Hüllenklassen“: Klasse Integer für Datentyp int usw. in Java
Singleton (Singleton)
[ Erzeugungsmuster, objektbasiert ]
Sichere ab, dass eine Klasse genau ein Exemplar besitzt, und stelle einen globalen
Sichere ab, dass eine Klasse genau ein Exemplar besitzt, und stelle einen globalen
Zugriffspunkt darauf bereit.
Zugriffspunkt darauf bereit.
- Bei manchen Klassen ist es notwendig, dass es genau 1 Objekt gibt
- Zugriff von mehreren anderen Objekten erforderlich
Klassenvariable
Klassenmethode
public final class Singleton {
public final class Singleton {
private static Singleton uniqueInstance = null;
private static Singleton uniqueInstance = null;
}
private Singleton(){
private Singleton(){
}
}
public static Singleton instance(){
public static Singleton instance(){
if (uniqueInstance == null) {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
uniqueInstance = new Singleton();
}
}
return uniqueInstance;
return uniqueInstance;
}
}
}
- der Konstruktor ist private, nur mittels instance() können Objekte erzeugt
werden
- das Singleton-Muster ist eine Verbesserung gegenüber globalen Variablen
- die Singleton-Klasse kann durch Unterklassen spezialisiert werden
- Vorsicht vor „Singletonitis“
Fabrik-Methode (Factory Method)
[ Erzeugungsmuster, klassenbasiert ]
Definiere eine Klassenschnittstelle mit Operationen zum Erzeugen eines
Definiere eine Klassenschnittstelle mit Operationen zum Erzeugen eines
Objekts, aber lasse Unterklassen entscheiden, von welcher Klasse das zu
Objekts, aber lasse Unterklassen entscheiden, von welcher Klasse das zu
erzeugnde Objekt ist.
erzeugnde Objekt ist.
Das Muster wird auch als „virtueller Konstruktor“ bezeichnet.
Das Muster wird auch als „virtueller Konstruktor“ bezeichnet.
createProduct() ist abstrakt und heißt Fabrikmethode, sie ist für die Fabrikation
von Objekten verantwortlich.
Strategie (Strategy)
[ Verhaltensmuster ]
Definiere eine Familie von Algorithmen, kapsele jeden einzelnen und mache sie
Definiere eine Familie von Algorithmen, kapsele jeden einzelnen und mache sie
austauschbar. Das Strategie-Muster ermöglicht es, den Algorithmus unabhängig
austauschbar. Das Strategie-Muster ermöglicht es, den Algorithmus unabhängig
von ihn nutzenden Klienten zu variieren.
von ihn nutzenden Klienten zu variieren.
Schablonenmethode (Strategy)
[ Verhaltensmuster, objektbasiert ]
Definiere das Skelett eines Algorithmus in einer Operation und delegiere
Definiere das Skelett eines Algorithmus in einer Operation und delegiere
einzelne Schritte an Unterklassen. Die Verwendung einer Schablonenmethode
einzelne Schritte an Unterklassen. Die Verwendung einer Schablonenmethode
ermöglicht es Unterklassen, bestimmte Schritte eines Algorithmus zu überermöglicht es Unterklassen, bestimmte Schritte eines Algorithmus zu überschreiben, ohne seine Struktur zu verändern.
schreiben, ohne seine Struktur zu verändern.
Beispiel
Schablonenmethode-Muster:
- Schablonenmethoden bilden die grundlegende Technik zur
Wiederverwendung von Code
- sie realisieren das Prinzip „Don't call us, we'll call you“
9
Musterarchitekturen
9.1
Die MVC-Architektur
9.2
Grafische Benutzeroberflächen
9.3
Client-Server-Systeme mittels http und Servlets
9.4
Datenbankanbindungen an Java-Applikationen
Die Model-View-Controller-Architektur (MVC)
View
Model
Controller
• Modell-Objekt stellt das Anwendungsobjekt dar
• View-Objekt stellt die Bildschirmrepräsentation dar
• Controller-Objekt bestimmt die Reaktion auf Benutzereingaben
→ Veränderung des Modells
Einsatz von Entwurfsmustern in der MVC-Architektur:
•
Beobachter-Muster zur Entkopplung von Modell-Objekt und View-Objekt
•
Strategie-Muster zur Realisierung unterschiedlicher Reaktionen auf
Benutzereingaben
●
Kompositum-Muster zur Realisierung der Views
9.2
Grafische Benutzeroberflächen
► Entwicklung: - Oberflächenprogrammierung
- Grafikprogrammierung
► AWT
Swing
SWT
- schwergewichtig, plattformunabhängig (portabel)
- leichtgewichtig, plattformunabhängig
- schwergewichtig, plattformabhängig
► Peers schaffen einheitliche Schnittstelle zwischen AWT und Plattform-API,
sind in Java geschriebene Interfaces, Paket java.awt.peer
► Aufbau einer GUI in 2 Schritten:
- Struktur erstellen
- Aktionen implementieren,
die über die GUI ausgelöst werden
Darstellung aus Mittendorf, Singer,Strobel: Java Programmierhandbuch u. Referenz
AWT
(Abstract Window Toolkit)
►
Alle Komponenten von abstrakter Klasse Component abgeleitet
►
Container (abstrakt) können andere Komponenten enthalten
●
●
wird nicht direkt instanziiert
verwaltet einen Vektor von Komponenten
Klasse Container
▶ Container werden nicht direkt instantiiert.
▶ Windows und Panel sind spezielle Container
▶ Window ohne Rahmen und Menüleiste
▶
Panel als Zeichenelement nutzen
▶
Frame ist Window mit Rahmen ( sicherheitsrelevant bei Applets!)
▶
Jeder Container verwaltet einen Layoutmanager zur
Positionierung von Komponenten
Auslösen von Aktionen (Event Handling)
public class ConvenienceStoreSim extends Applet
implements ActionListener{
...
Button quitButton;
...
quitButton.addActionListener(this);
...
public void actionPerformed(ActionEvent evt) {
if(evt.getActionCommand().equals("Simulate")){
simulate((int)(serviceDurationPanel.getValue()),
(int)(arrivalRatePanel.getValue()),
(int)(durationPanel.getValue()));
}
if (evt.getActionCommand().equals("Quit")){
System.exit(0); window.dispose();
}
}
Swing
= 100 % pure Java
→
Java Versionen existierender
AWT-Komponenten
+
„higher level“-Komponenten
(trees, tabbed panes, … )
Abb.: de.wikipedia.org/wiki/Swing_(Java)
▶ GUI-Komponenten mit „pluggable“ Look & Feel
→ Windows-, Sun Solaris-, Macintosh-, Java (Metal)-Oberfläche
→ kann zur Laufzeit geändert werden
Beispiele: Motif-, Metal-, Ocean-, Synth-, Nimbus-L&F
▶ Swing-Komponenten sind „leichtgewichtig“
(bauen nicht auf User-Interface-Code auf, der BS-abhängig ist)
▶ Swing ist nicht thread-sicher (Wechselwirkungen zwischen Threads)
▶ Swing-Komponenten sind JavaBeans (nutzen Event Model)
▶ Packages
javax.swing
javax.accessibility
...
▶ Swing hat eigene Klassen für Event-Handling
→ MVC-Prinzip für jede JComponent
Klassifizierung von Komponenten
►
Jedes Programm, das ein Swing-GUI repräsentiert, enthält
wenigstens 1 Toplevel-Swing-Container, d.i. eine Instanz von
- JFrame oder
- JDialog oder
- JApplet
►
Panels (Pane) sind Zwischencontainer
→ JPanel, JScrollPane, JTabbedPane
►
Jeder Toplevel-Container enthält indirekt einen Zwischen-Container
ContentPane. Dieser Container enthält direkt oder indirekt alle
sichtbaren Komponenten (Ausnahme MenuBar).
►
Atomare Komponenten: JComboBox, JTextField, JTable, ...
MVC-Architektur für Komponenten
► Nutzer können steuern
- wie Widgets aussehen,
- wie sie auf Eingaben reagieren,
- wie Daten repräsentiert werden
► View und Controller sind in einem Objekt vereinigt, das delegate heißt.
delegates
- stellen das Modell dar (View-Aspekt)
- übertragen Nutzereingaben zum Modell (Controller-Aspekt)
► Eine JComponent hat - ein simple model
- ein simple delegate
► Mögliche Models für eine spezielle JComponent sind Klassen,
die ein für die Komponente spezifisches Model Interface implementieren.
► Mögliche Delegates für eine spezielle JComponent sind Klassen,
die ein für die Komponente spezifisches Delegate Interface implementieren.
Beispiel: Eine Klasse, die ein Model für JButton darstellt, muss
Beispiel: Eine Klasse, die ein Model für JButton darstellt, muss
das Interface ButtonModel implementieren.
das Interface ButtonModel implementieren.
Das Interface ButtonUI definiert das Delegate eines JButton.
Das Interface ButtonUI definiert das Delegate eines JButton.
► Alle Delegates sind von ComponentUI abgeleitet.
► ComponentUI enthält Funktionalität, um zu definieren, wie eine
Delegate-Klasse eine JComponent rendert.
Primäre Methode: paint()
► Spezielle Subinterfaces von ComponentUI definieren die ControllerAspekte
► DefaultButtonModel ist das Default-Model von JButton
► BasicButtonUI ist das Default-Delegate für JButton. Andere
Klassen sind WindowsButtonUI, MetalButtonUI,
MacButtonUI und MotifButtonUI
MVC-Architektur und GUI-Event Handling
Beispiel: Eine Liste fungiert als Modell für zwei Views
Motivation: Der Mittelwert kann nicht von der View-Liste berechnet
werden. Problem: Falls View-Liste abgeschaltet wird, kann kein
Mittelwert mehr berechnet werden
-
Die Views (avgField und textList) fungieren als
ChangeListener zum Modell (implementieren ein
ChangeListener-Interface). Sie benutzen eine Methode
stateChanged.
-
Der Controller (textField) benutzt einen ActionListener, der
dafür sorgt, dass die Daten im Modell geändert werden
(Methode actionPerformed).
-
Problem: In der Methode stateChanged können keine Daten
übergeben werden.
-
Lösung: Adapter vermitteln, sie besitzen erforderliche Informationen
Swing-Beispiele:
Beispiel:
JTree
In der Klasse Gui.Gui :
zuvor muss Syntaxbaum aufgebaut sein !
Konstruktor der Klasse TTree :
liefert DefaultMutableTreeNode
SWT
(Standard Widget Toolkit)
▶
Ursprung:
- Rational Devision of IBM
→ Object Technology International, Inc. (OTI)
- für Visual Age/Smalltalk Projekt → Portabilität
- Java-basiert: IBM VisualAge/Micro Edition →
Perfrmance-Probleme mit AWT/Swing
- Neues Toolkit: Smaltalk-Code → Java Code
OpenWidget Layer als Basis für SWT
▶
weiterentwickelt im Eclipse-Projekt, um Zugriff auf die „nativen“ User
Interface-Unterstützungen des Betriebssystems zu erhalten
▶
Auch für Standalone-Java-Applikationen einsetzbar
▶
Komponente der Eclipse-Workbench
→ org.eclipse.swt.widgets u.a.
▶
Package
org.eclipse.swt.custom
speziell für Eclipse entwickelt → ohne neue native Routinen
Beispiel:
1)
HelloWorld-Programm mit SWT
Beschaffen eines Quellprogramms
http://my.safaribooksonline.com/book/web-development/widgets/0321256638/
2)
In Eclipse Java-Projekt kreieren
Einstellungen, um das Programm auszuführen:
Vorlesungsbsp > Kontextmenü > Properties
Aus dem Verzeichnis 'plugins'
Mit 'OK' bestätigen, die im Quelltexteditor gezeigten Fehler sollten verschwinden
Vorlesungsbsp > Kontextmenü > Run As > Run Configurations
Zur Vermeidung des Fehlers
Das Fenster wird geöffnet:
Einbettung von Swing-Komponenten in SWT:
Problem:
- Jamus (Testwerkzeug) basiert auf AWT/Swing
- soll Eclipse-Nutzern als Werkzeug zur Verfügung gestellt
werden
- Eclipse basiert auf SWT, kann mit Swing nicht arbeiten
- Integration von Jamus in Eclipse-IDE:
→ PDE-Projekt anlegen (Struktur schaffen)
→ Jamus-Perspektive schaffen
→ Integration von Views/Editoren in IDE
→ Integration Menüs
→ Frames bleiben Frames
►
Über die Eclipse-Homepage ist ein Package
swingintegration.example_0.0.2.jar erreichbar.
Adresse:
http://www.eclipse.org/articles/Article-Swing-SWTIntegration/files/swingintegration.example_0.0.2.jar
►
Alle Klassen des Packages wurden in die eigene Anwendung
in das Paket de.htw.dresden.jamus.embeddedSwing
übernommen und individuell angepasst.
►
Die Klasse EmbeddedSwingComposite ist die Basis für die
Einbettung von AWT/Swing-Komponenten.
neu
ermöglicht die Integration
von AWT/Swing
Jamus-Perspektive schaffen
Ausschnitt aus plugin.xml
→
Die Perspektive wird der Workbench über den Extension Point
org.eclipse.ui.perspectives bekannt gegeben
→
Die Klasse Perspective muss org.eclipse.ui.IPerspectiveFactory
implementieren
→
mit der Methode createInitialLayout können der Perspektive
Ansichten (z.B. Projekt-Explorer, Editor) hinzugefügt und das Layout
konfiguriert werden.
Jamus-Menü
Jamus-Perspektive
Verwenden eines Templates für Einbettung der Swing-Komponenten:
Erläuterung zum Programmtext:
- EmbeddedSwingComponent ist eine abstrakte Klasse,
die Methode createSwingComponent ist abstrakt.
- es wird eine lokale, anonyme Klasse gebildet, die von
EmbeddedSwingComposite abgeleitet ist
- in der lokalen Klasse wird die Methode createSwingComponent()
überschrieben
- die innere Klasse kann auf Attribute und Methoden der umgebenden
Klasse zugreifen
- in der umgebenden Klasse wird keine Instanz der inneren Klasse
benötigt
→
Eine Instanz der Klasse EmbeddedSwingComposite wird erzeugt
(Singleton-Muster!)
→
der erste Parameter muss vom Typ org.eclipse.swt.Composite sein
→
Composite gruppiert grafische Elemente in einem Container
→
Swing-Komponenten können in einem Composite-Container
eingebettet werden
→
die Swing-Komponente muss von javax.Swing.JComponent abgeleitet sein
→ mittels Integrationstechnik werden realisiert:
JProjectTree
- Darstellung Projekt-Explorer
DocumentTextEditor
- Anzeigen Quelltext im Editor
Gui
- Darstellung des openFile-Dialogs
Einbetten des Projekt-Explorers (TreeViewpart - View-Reiter):
Einbetten des Quelltext-Editors (EditorViewpart):
Einbetten des OpenFile-Dialogs:
showDialog wird von openFileOpenDialog und openProjectOpenDialog aufgerufen
Pulldown-Menü
→ die Klasse Gui.Gui wird als Command in Eclipse realisiert
→ das Element commandParameter dient zur Unterscheidung der Menüeinträge
→ das Jamus-Menü-Command wird abhängig von der Jamus-Perspektive
eingeblendet
→ das Verhalten von Commands wird durch Handler definiert
→ Über en Extension Point org.eclipse.ui.handlers kann zu einem
Command eine Handlerklasse registriert werden
→ das Pulldown-Menü kann über den Extension Point
org.eclipse.ui.handlers registriert werden.
→ Hinzufügen von Commands/Untermenüs
→ Menüaktionen werden in der Methode execute der Handlerklasse Gui
imlementiert
Frames bleiben Frames
Technologie
(1) Projekt
→
→
→
→
→
Plug-in-Development-Projekt erzeugen
Kopieren der (alten) Jamus-Dateien in das Projekt
Abhängigkeiten prüfen
Quellprogramme anpassen
Testen mit: „Launch an Eclipse Application“
(2) Projekt
→
→
→
→
etc.
installieren:
Projekt exportieren (jar-File)
Projekt installieren (Help‐> Install New Software)
(3) Projekt
→
entwickeln:
nutzen (Eclipse mit Jamus-Plug-In):
Erstellen/Öffnen eines Jamus-Projektes
Bereistellen/Editieren eines Quelltextes
Parsen, Instrumentieren, Darstellen des gerichteten Graphen
JFace
►
JFace ist ein „higher level” UI-Toolkit, in Eclipse bereitgestellt
►
aus den von SWT zur Verfügung gestellten Basiskomponenten
werden komplexere Widgets zusammengesetzt Es wird eine
Abstraktionsschicht für den Zugriff auf die Komponenten bereitgestellt.
►
JFace besitzt Abhängigkeiten zu einigen Eclipse-Bibliotheken
►
stellt Viewer ListViewer, TableViewer, TreeViewer etc. bereit
►
die Viewer besitzen Adapter-Interfaces
9.3
Client-Server-Systeme mittels http und Servlets
►
Servlets sind spezielle Java-Klassen
►
Verteilte Anwendungen:
►
Servlets benötigen spezielle Laufzeitumgebung:
→
Servlet-Runner, Web-Container
(analog „Sandbox“ für Applets)
►
Servlets unterliegen Lebenszyklus
►
Servlets zur dynamischen Erzeugung von Web-Inhalten
►
Beschränkung auf Web-Anwendungen:
→
Apache Web-Server + Tomcat als Web-Container
Client-seitig: Applets
Server-seitig: Servlets
Der Servlet-Lebenszyklus
●
Laden und Initialisieren durch Laufzeitumgebung (Container)
●
Zyklisch:
●
Servlet entfernen
- Daten empfangen (Request)
- verarbeiten
- Daten zurückliefern (Response)
Servlet-Programmierung
► API: Package javax.servlet
http://download.oracle.com/javaee/6/api/javax/servlet/package-summary.html
http://download.oracle.com/javaee/6/api/javax/servlet/http/package-summary.html
► Implementierung der Schnittstelle javax.servlet.Servlet
► Nutzung des http-Protokolls:
Servlet als Spezialisierung der Klasse
javax.servlet.http.HttpServlet
+
Überschreiben der Methoden zur Behandlung von http-Interaktionen
► alle Methoden erwarten 2 Parameter:
HttpServletRequest (Daten vom Client)
HttpServletResponse (Daten an Client)
► Die Behandlung von Client-Requests erfolgt mit Methode service des
Servlets.
Die Methode service leitet Requests an eine in der Servlet-Klasse
überdefinierte Methode doXXX weiter.
► Methoden zur Behandlung von Requests:
• doGet
- Behandlung von GET-Requests, HEAD-Requests
• doPost
- Behandlung von POST-Requests
• doPut
- Behandlung von PUT-Requests
• doDelete
- Behandlung von DELETE-Requests
► HTTP-Request
• für alle HTTP-Methoden:
getParameterValues liefert den Wert eines Parameters
getParameterNames liefert die Namen der Parameter
• speziell für GET (HTTP):
getQueryString
liefert einen String, der ggf. zu parsen ist.
• für POST, PUT, DELETE:
getReader liefert einen BufferedReader,
der zum Lesen von Text-Daten verwendet werden kann,
getInputStream liefert einen ServletInputStream,
der zum Lesen von binär-Daten verwendet werdeen kann.
► HTTP-Response
Für die Rückgabe von Antworten bietet ein HttpServletResponse-Objekt
folgende Möglichkeiten:
• getWriter
liefert einen Writer für die Ausgabe von Textdaten
• getOutputStream liefert einen Output Stream für die Ausgabe von Binaries
► Servlet-Metadaten
Metadaten über ein Servlet werden in einer XML-Datei web.xml gespeichert
(sog. Deployment-Deskriptor)
Beispiel Das in der Server2Go-Applikation verwendete Servlet MyServlet
Die Ausgabe am Browser:
hier vordefinierte Beispiele auswählen
Beispiel
Servlet-Anwendung RequestInfoExample
In: htdocs\webapps\examples\Web-INF\classes\
RequestInfoExample
RequestInfoExample
/Users/fritzsch/workstation/SE/Demos-Beispiele/ServletExamples/classes/RequestInfoExample.java
Beispiel
Servlet-Anwendung RequestHeaderExample
In: htdocs\webapps\examples\Web-INF\classes\
RequestHeaderExample
RequestHeaderExample
/Users/fritzsch/Downloads/server2go/htdocs/webapps/examples/WEB-INF/classes/RequestHeaderExample.java
Beispiel
Servlet-Anwendung RequestParamExample
In: htdocs\webapps\examples\Web-INF\classes\
RequestParamExample
RequestParamExample
/Users/fritzsch/Downloads/server2go/htdocs/webapps/examples/WEB-INF/classes/RequestParamExample.java
<form
<form action="RequestParamExample"
action="RequestParamExample"
method=POST>
method=POST>
First
First Name:
Name:
<input
<input type=text
type=text size=20
size=20 name=firstname>
name=firstname>
<br>
<br>
Last
Last Name:
Name:
<input
<input type=text
type=text size=20
size=20 name=lastname>
name=lastname>
<br>
<br>
<input
<input type=submit>
type=submit>
</form>
</form>
web.xml
/Users/fritzsch/Downloads/server2go/htdocs/webapps/examples/WEB-INF/web.xml
/Users/fritzsch/workstation/SE/Demos-Beispiele/ServletExamples/classes/RequestParamExample.java
/Users/fritzsch/Downloads/server2go/htdocs/webapps/examples/WEB-INF/classes/RequestParamExample.java
Aufrufe von Servlets:
●
über die URL des Browsers
●
mittels eines Formulars
●
mittels eines Applets
Im Applet – in init bzw. start:
URL url = new URL(...);
URLConnection connection = url.openConnection();
OutputStream out = connection.getOutputStream;
PrintStream pout = new Printstream(out);
InputStream in = connection.getInputStream();
9.4
Datenbankanbindungen an Java-Applikationen
► Ein Java-Client-Programm, das auf eine Datenbank zugreifen soll, enthält
folgende Funktionen:
1.
Laden eines JDBC-Treibers
2.
Öffnen einer Datenbank (Verbindung aufbauen)
3.
Senden von SQL-Anweisungen an die Datenbank
4.
Auslesen und Bearbeiten der Ergebnisse
► Die Schritte 1. und 2. sind einmal in einer Anwendung auszuführen,
die Schritte 3 und 4 werden wiederholt ausgeführt.
► Voraussetzungen
1.
Installieren eines JDK
→ Bereitstellen JDBC API (Java DataBase Connectivity)
DB-Zugriff unabhängig vom verwendeten DBMS
Setzen der Umgebungsvariablen JAVA_HOME
2.
Installation eines Treibers auf der Maschine
→ siehe Anleitung Server2Go
3.
Installation eines DBMS
→ MySQL kommt mit dem Server2Go
→ MS ACCESS im Beispiel Biolexikon
4.
Vorbereitung einer Datenbank
→ mittels phpMyAdmin erstellen
Items – für MyServlet-Beispiel
biolexikon – für Biolexikon
► JDBC-Treiber laden u. DB-Verbindung aufbauen:
1) Bereitstellen eines Treibers (für MySQL) zur Laufzeit:
Class.forName("com.mysql.jdbc.Driver").newInstance();
Class.forName("com.mysql.jdbc.Driver").newInstance();
2) DB-Verbindung aufbauen:
Connection
Connection con
con == DriverManager.getConnection(a,b,c)
DriverManager.getConnection(a,b,c)
a:
url-String der Form jdbc : subprotocol : subname
String
String url
url == "jdbc:mysql://localhost:7188/server2go";
"jdbc:mysql://localhost:7188/server2go";
b:
Benutzername als String
c:
Passwort als String
Festlegung des Treiber-Herstellers
► SQL-Anweisung an die DB senden:
1) Erzeugen eines Statement-Objektes, um SQL-Statements an die
Datenbank zu senden:
Statement stmt = con.createStatement();
Statement
Statement stmt
stmt == con.createStatement();
con.createStatement();
2) Übermitteln des SFW-Blockes:
String
String query
query == "SELECT
"SELECT *"
*" ++
"FROM
String query = "SELECT
*" +
"FROM items";
items";
ResultSet
stmt.executeQuery(query);
items";
ResultSet rs
rs =="FROM
stmt.executeQuery(query);
ResultSet rs = stmt.executeQuery(query);
3) Automatische Übermittlung des Statements an das DBMS
mittels JDBC-Treiber.
► Auslesen und Bearbeiten der Ergebnisse:
●
●
●
●
SFW-Anweisung liefert Tabelle als Instanz von ResultSet
Methoden von ResultSet dienen dem Durchlaufen der Tabelle
und dem Zugriff auf Ergebnisse: Zeilenweise von links nach rechts.
Ausgabe der Tabelle als HTML-Datei
Vorteil: Web-Browser kümmert sich um die Formatierung
Auflistung der Spaltennamen: dynamisch ermitteln
ResultSetMetaData
rsmd
== rs.getMetadata();
ResultSetMetaData
rsmd
= rs.getMetadata();
ResultSetMetaData
rsmd
rs.getMetadata();
int
colums
=
rsmd.getColumnCount();
int colums
= rsmd.getColumnCount();
int colums
= rsmd.getColumnCount();
for
(int
i=1;i<=colums;i++)
for (int
fori=1;i<=colums;i++)
(int i=1;i<=colums;i++)
System.out.println("<TH>"
System.out.println("<TH>" ++
●
++
System.out.println("<TH>"rsmd.getColumnName(i)
+
rsmd.getColumnName(i)
"</TH>");
rsmd.getColumnName(i)
+
"</TH>");
"</TH>");
→ Das Feld ist 1-basiert!
●
Ausgabe des Tabelleninhaltes:
while
(rs.next())
while
(rs.next())
{ {{
while
(rs.next())
System.out.println("<TR>");;
System.out.println("<TR>");;
System.out.println("<TR>");;
for
(int
for (int
fori=1;i<=colums;i++)
(int i=1;i<=colums;i++)
i=1;i<=colums;i++)
System.out.println("<TD>"
++
System.out.println("<TD>"
+
System.out.println("<TD>"
rs.getObject(i)
++
rs.getObject(i)
+
rs.getObject(i)
"</TD>");
"</TD>");
"</TD>");
System.out.println("</TR>");;
System.out.println("</TR>");;
System.out.println("</TR>");;
}}
}
●
Schließen geöffneter Objekte: Ressourcenfreigabe
rs.close();
rs.close();
rs.close();
stmt.close();
stmt.close();
stmt.close();
con.close();
con.close();
con.close();
rs.next()
positioniert zum nächsten Datensatz
muss bereits vor dem Lesen des ersten Datensatzes
aufgerufen werden
Die innere Schleife generiert die <TD>-Elemente
rs.getObject(int columnindex)
liefert den Wert der durch den Parameter bestimmten Spalte
der aktuellen Zeile als String.
Der Wert ist immer von der Klasse Object,
unabhängig vom Datentyp des Attributs in der DB-Tabelle.
Die Ausgabemethode konvertiert den Wert in String.
Falls der Datentyp der Elemente bekannt ist, können auch die
Zugriffsmethoden
getInt()
getString()
usw. verwendet werden.
zeilenweise Ausgabe
rs.getString(int columnIndex)
rs.getString(String columnLabel)
liefert den Wert der durch den Parameter bestimmten Spalte
in der aktuellen Zeile als String zurück
Beispiel
1. Erstellen der Datenbank
Änderungen in der DB persistent machen:
→
Anleitung von Herrn Roeper
2. JDBC-Treiber bereitstellen
Datei: mysql-connector-java-5.1.15.zip
Quelle: http://www.mysql.com/downloads/connector/j
mysql-connector-java-5.1.15.zip
→
entpacken
mysql-connector-java-5.1.15-bin.jar
nach webapps/mywebapp/WEB-INF/lib speichern
9.5 Analysieren der Applikation BioLex
(Historisches biografisches Lexikon)
→ Architektur / HTML-Seite: ClientF.html
→ Applet: DBApplet.java
→ Kommunikation mit Servlet: ServletCom.java
→ Kommunikation mit Applet: COMApplet.java
→ Servlet: DBServlet.java
→ Kommunikation mit DB: DBConnect.java
http://www2.htw-dresden.de/~fritzsch/ISGV/BioLex/ClientApplet/ClientF.html
Herunterladen