Download - Gliederung: Teil 3 - Anpassungen
Dr. Welf Löwe und Markus Noga 1
Gliederung: Teil 3 - Anpassungen
1. Einführung– Motivation– Definition, – Konzepte für Komponenten (klassische, kommerzielle, akademische)
2. Industrielle Komponentensysteme der 1. Generation1. CORBA 2. Enterprise JavaBeans3. (D)COM
3. Anpassungen – Daten und Funktion– Interaktion
• Kommunikation• Synchronisation• Protokolle
– Lebendigkeit
Dr. Welf Löwe und Markus Noga 2
Problem
3.1 Anpassungen von Funktionen
Dr. Welf Löwe und Markus Noga 3
Daten- als Funktionsanpassung
Datenanpassung – Transformation von Wertetypen– Transformation von Schnittstellen– Können Auswirkung auf Implementierung von Diensten haben– Sind damit spezielle Funktionsanpassungen– Modell: Herausziehen generischer Klassen
Funktionsanpassung– Hinzufügen, Entfernen und Ändern von Funktionalität– Allgemeiner
Dr. Welf Löwe und Markus Noga 4
Domäne der Datenanpassung
Quelle: Class X { R1 m1(P1); R2 m2(P2); ... Rn mn(Pn);}
Ziel: Class Y { R`1 m1(P‘1); R`2 m2(P‘2); ... R`n mn(P‘n);}
Mittel: Class GX ( GP1 < TS1, (von Impl.) GP2 < TS2, ..., GR1 <, (von Benutzung) GR2 <, ..., ) { GR1 m1(GP1); GR2 m2(GP2); ... GRn mn(GPn);}
Dr. Welf Löwe und Markus Noga 5
Datenanpassung mit generischen Klassen
Konkrete Parameter und Ergebnisse– Als einen zusammengesetzten Typ auffassen– Durch generischen Typ ersetzen
Einsetzen neuer spezieller Typen bildet neue Instanz
Anpassungen von– Parametern – Resultaten– Methodenimplementierung (implizit)
Weitere nicht-generische Anpassungen– Methodennamen
Dr. Welf Löwe und Markus Noga 6
Beispiel
Quelle: class SetOfComplex { void add(double re, double im); boolean has(double re, double im); int size();}
Mittel: class Set<Type T> { void add(T t); boolean has(T t); int size();}
Ziel: class SetOfComplex { void set(Complex c);
boolean get(Complex c);
boolean empty();}
Dr. Welf Löwe und Markus Noga 7
Techniken revisited
XSLT & Co– Umformen von WSDL-Beschreibungen– Umformen konkreter Aufrufe, z.B.
• Permutation von Parametern
• Umbenennungen
Compost– Leistet Typanalyse– Identifiziert Stellen für innere Anpassung– Bietet Grundwerkzeuge zur Anpassung– Werkzeug mächtiger als (hier) benötigt
Dr. Welf Löwe und Markus Noga 8
Beispiel: Umbenennen mit Compost
public ProblemReport analyze() {transformations = new TwoPassTransformationArrayList();CrossReferenceServiceConfiguration config = getServiceConfiguration();ProblemReport report = EQUIVALENCE;AbstractTreeWalker tw = new ForestWalker(getSourceFileRepository().getKnownCompilationUnits());while (tw.next()) { ProgramElement pe = tw.getProgramElement(); TwoPassTransformation t; if (pe instanceof TypeDeclaration) {
TypeDeclaration td = (TypeDeclaration)pe;if (td.getName() != null) { t = new RenameType(config, td, createName(td)); report = t.analyze(); if (report instanceof Problem)
return setProblemReport(report); transformations.add(t);}
} else if (pe instanceof VariableSpecification) { // ...
Dr. Welf Löwe und Markus Noga 9
Grenzen
Nur Anpassung einzelner Methoden– Keine Aggregation– Keine Zerlegung– Keine Rekombination
Anpassung von Feldern teilweise problematisch– Wann ist Typgleichheit Zufall?– Wie identifiziere ich diese Fälle?
Nur implizite Änderung von Funktionalität– Gezielte Änderungen unmöglich
Dr. Welf Löwe und Markus Noga 10
Grenzen am Beispiel
Quelle: class SetOfComplex { void add(double re, double im); boolean has(double re, double im); int size(); double getReAt(int iter); double getImAt(int iter);
void setLoad(double d);}
Ziel: class SetOfComplex { void add(Complex c);
booelan has(Complex c);
int size(); Complex get(int iter);
}
Dr. Welf Löwe und Markus Noga 11
Funktionsanpassungen
Datenanpassungen (subsumiert)
Neue Sichten auf Funktionalität– Aggregation– Zerlegung– Rekombination
Veränderungen der Funktionalität– Erweitern (mit neuem Code)– Einschränken (durch explizites Löschen)– Ändern (beides)
Dr. Welf Löwe und Markus Noga 12
Beispiel Aggregation
Quelle: class Konto { void abheben (double euro); void einzahlen(double euro); }
Ziel: class Konto { void abheben (double euro); void einzahlen(double euro); void überweise(Konto k, double euro);}
mit Semantik
Void überweise(double euro) { this.abheben (euro); k .einzahlen(euro);}
Dr. Welf Löwe und Markus Noga 13
Beispiel Zerlegung
Quelle: class Filter { Filter(Config c);
void run(Input i);}
Ziel: class Filter { Filter(); void setup(Config c); void run(Input i);}
Dr. Welf Löwe und Markus Noga 14
Beispiel Rekombination
Quelle: class ModelView { void addAndEnable(Model m);}
Ziel: class ModelView { void add (Model[] m); void enable(Model[] m);}
Mittel: class ModelView { void add (Model m); void enable(Model m);}
Dr. Welf Löwe und Markus Noga 15
Beispiel Erweiterung
Quelle: class Signal { void set(double[] data); void multiply(double s); void resample(double f); void haarWavelet(); void haarWaveletInv();}
Ziel: class Signal { void set(double[] data); void multiply(double s); void resample(double f); void wavelet (Wavelet w); void waveletInv(Wavelet w);}
Implementierung spezifiziert durch
Benutzer.
Dr. Welf Löwe und Markus Noga 16
Beispiel Einschränkung
Quelle: class GrooveFiles { Handle add (File f); File get (Handle h); void update (Handle h, File f); void setRights(Handle h, Rights r); void enterpriseFunc2(); void enterpriseFunc3();}
Ziel: class GroovePreviewFiles { Handle add (File f); File get (Handle h); void update(Handle h, File f);
}
Dr. Welf Löwe und Markus Noga 17
Techniken
Anpassung ist Codetransformation
Einsatz von Compost– Analyse der Quellen– Spezifikation der Anpassungen als Metaprogramm– Umsetzung mit Grundbausteinen aus Bibliothek
Beispiele zeigen primär Anpassung auf Signaturenmengen– Erweiterungen/Einschränkungen denkbar, die quer zum OO-Modell
liegen– Z.B. Hinzufügen/Entfernen von Tests, Persistenz etc.– Auch mit Compost möglich.
Dr. Welf Löwe und Markus Noga 18
Beispiel: Erweitern mit Compost
public ProblemReport execute() {MutableSet inserted = new IdentityHashSet();CrossReferenceServiceConfiguration config = getServiceConfiguration();ProgramFactory pf = getProgramFactory();SourceInfo si = getSourceInfo();CompilationUnitList units = getSourceFileRepository().getKnownCompilationUnits();for (int i = 0; i < units.size(); i += 1, inserted.clear()) { CompilationUnit cu = units.getCompilationUnit(i); TreeWalker tw = new TreeWalker(cu); while (tw.next()) {
ProgramElement pe = tw.getProgramElement();if (pe instanceof MethodReference) {
// [omitted: treat some special cases ...] MethodReference caller = (MethodReference)pe; MethodReference insert = (MethodReference)
pf.parseExpression("System.out.println(\"\")"); // [omitted: build expression to insert ...] TwoPassTransformation t =
new PrependExpressionWithStatements(config, caller, insert); ProblemReport report = t.analyze();
Dr. Welf Löwe und Markus Noga 19
Warum Unterscheidung?
Datenanpassungen sind– Einfacher– Stärker lokalisiert– Mit einfacheren Werkzeugen (z.B. XSLT) behandelbar
Funktionsanpassungen sind– Komplexer– Weniger lokalisiert– Erfordern aufwendigere Werkzeuge.
Praktische Unterscheidung für Ingenieure sinnvoll
Theoretische Unterscheidung evtl. nicht sinnvoll– Jede Anpassung ist durch Wegwerfen und Neuschreiben möglich
Dr. Welf Löwe und Markus Noga 20
Problem
3.2 Anpassungen von Interaktionen
Dr. Welf Löwe und Markus Noga 21
Grau ist alle Theorie
Ansatz– Interaktion = Datenfluß + Kontrollfluß
Kollision mit der Realität– Häufigstes Interaktionsmittel ist der Prozeduraufruf– Datenfluß legt Kontrollfluß fest– Ebenso
• RMI• Ereignisse• Synchrone Kommunikationskanäle• etc.
– Variablenzugriffe sind Methodenaufrufe (bei Verteilung)
Auflösung in Bestandteile theoretisch denkbarSpätestens bei Rückabbildung große Probleme!
Dr. Welf Löwe und Markus Noga 22
Literatur
Understanding Software - Static and Dynamic Aspects(Löwe, Ludwig, Schwind)
Aspect-Oriented Configuration and Adaptation of Component Communication(Heuzeroth, Löwe, Ludwig, Aßmann)
Compost: siehe vorangehende Vorlesung
Dr. Welf Löwe und Markus Noga 23
Definition
Interaktion = Kommunikation + SynchronisationKommunikation ist Daten- und Kontrollfluß– Lokaler Methodenaufruf– Java/Corba RMI– Ereignisse– etc.
Synchronisation stimmt Steuerflüsse ab– Semaphore– Kritischer Abschnitt– Monitor
Explizite Manipulation von Steuerflüssen– z.B. Threads– hier nicht betrachtet
Dr. Welf Löwe und Markus Noga 24
Warum Kommunikation anpassen?
OO Entwurf– aktive Objekte– Relationen meist eigenständig– Kommunikation über Nachrichten
OO Umsetzung– passive Objekte– wenig aktive Threads– Relationen meist in Objekte eingemischt– Kommunikation und Aktivierung durch Methodenaufrufe
Folge– Große Spielräume bei der Umsetzung– Verwendung von Entwurfsmustern kann Kompatibilität nicht garantieren– Mangelnde Kompatibilität von Umsetzungen verschiedener Hersteller
Dr. Welf Löwe und Markus Noga 25
Ein Beispiel
Class Producer {
void register(Consumer c);
Product produce();
}
Class Consumer {
void register(Producer p);
void consume(Product p);
}
Produzent passivKonsument passivRegistrierung in beidenAnpassung nötig!
Dr. Welf Löwe und Markus Noga 26
Kommunikationsanpassung
Finde Kommunikationsports
Ersetze konkrete durch abstrakte/generische Aufrufe
Konfiguriere neu
Instanziiere gemeinsam (passfähig)
ProgrammingLanguage
AbstractCommunicationModel
Source Codeof- components- existing systems
Program P1
Abstract ModelInstancefor Program P1
Abstract ModelInstancefor Program P1
ConfiguredSource Codeof- adapted components- restructured systems
Program P2
Analysis Configuration (Re-)Production
Transformation
Dr. Welf Löwe und Markus Noga 27
Analyse
Statische Analyse identifiziert Methodenaufrufe
Problem: modellgebundene uneigentliche Kommunikation– Z.B. Registrierung eines Listeners– Identifikation: Semantikwissen in Muster übertragen
Problem: unvollständige Information– M EventSources, N Listener– Alle erben/benutzen abstrakte Interfaces– Wer kommuniziert wirklich mit wem?
Lösung: Zusätzliche dynamische Analyse– Auflösung polymorpher Aufrufe aufzeichnen– Nur exemplarisch möglich (konkreter Programmlauf)
Dr. Welf Löwe und Markus Noga 28
Analysewerkzeug VizzAnalyzer
Statische Analyse – Nutzt Compost– Konzepte: Bezug-auf, Enthält, Unterklasse-von
Dynamische Analyse– Nutzt Java Debug Interface– Zeichnet (Ausschnitt aus) Programmlauf auf– Konzepte: Ruft-auf, Zugriff-auf, Kennt, Instanz-von
Gefilterte Visualisierung– Ignorieren von Paketen– Hierarchische Aggregation– Automatisches Layout
Dr. Welf Löwe und Markus Noga 29
Beispiel Analyse
CommunicationOut-Port
DataType
CommunicationIn-Port
}
some calculations...
further calculations... }}
public doSomething() {
class Producer {
out(d : DataType)in() : DataType in() : DataType
out(d : DataType)
}
public doSomething() { some calculations...
further calculations... }}
class Consumer { private Channel<DataType> c;
public Producer(Channel<DataType> c) { this.c = c;
c.out(d);
Channel Channel
private Channel<DataType> c;
public Consumer(Channel<DataType> c) { this.c = c;
d = c.in();
Dr. Welf Löwe und Markus Noga 30
Konfiguration
Semantik der Kommunikation festlegen– Gepuffert / ungepuffert– Koordination (FIFO, LIFO etc.)– Destruktives / nicht-destruktives Lesen– Aktivität– Verteilung– Basiskommunikation
Bibliokthek von Konnektoren– Deckt verbreitete Fälle ab– Erweiterbar
Konfigurator– Metaprogramm, das Anpassung an Konnektor vornimmt
Dr. Welf Löwe und Markus Noga 31
Beispiel Konfiguration
CommunicationOut-Port
CommunicationIn-Port
in() : DataTypeout(d : DataType)
BufferDataType
}
public doSomething() { some calculations...
further calculations... }}
this.b = b;
d = b.in();
private Buffer<DataType> b;class Consumer {
public Consumer(Buffer<DataType> b) {
M1
M1
in() : DataTypeout(d : DataType)
counterInit : intBufferedQueueChannel
MetaprogramConfiguration
}
public doSomething() { some calculations... b.out(d); further calculations... }}
this.b = b;
private Buffer<DataType> b;class Producer {
public Producer(Buffer<DataType> b) {
Abstract Communication Connector
Communication Configurator
A A
Dr. Welf Löwe und Markus Noga 32
Transformation
Ziel– Ersetze abstrakte durch konkrete Kommunikation– Abbildung auf Zielsprache
Mittel– Metaprogramme der Konfiguratoren ausführen
Mögliche Optimierungen– Einsparen von Puffern– Einsparen von Kanal-Objekten– etc.
Werkzeug– Compost
Dr. Welf Löwe und Markus Noga 33
Ergebnis am Beispiel
Produzent aktiv
Konsument passiv
Registrierung beim Produzenten
Class Producer {
void register(Consumer c);
void produce() {
Product p=myProduce();
for(int i=0; i<cs.length; i++)
cs[i].consume(p);
}
}
Class Consumer {
void consume(Product p);
}
Dr. Welf Löwe und Markus Noga 34
Warum Anpassungen der Synchronisation?
Methodenausführung ist nicht atomar– Synchronisation nötig um Semantik zu erhalten
Viele Mechanismen (alle äquivalent)– Mutexe– Semaporen– Kritische Abschnitte– Barrieren– usw.
Abbildung aufeinander i.A. nicht einfach
Oft Entwicklung im threadfreiem Raum– Wiederverwendung in multi-threaded Umgebungen nicht gesichert
Dr. Welf Löwe und Markus Noga 35
Synchronisation
Behandlung wie Kommunikation– Analyse der konkreten Synchronisation– Abbildung auf abstrakte Synchronisation– Konfiguration– Transformation auf neue konkrete Synchronisation
Kern– Abstrakter Synchronisations-Port
Evtl. erweitern um– Explizite und implizite Manipulation von Threads
(fork / waitpid etc.)
Dr. Welf Löwe und Markus Noga 36
Beispiel
Quelle: class SyncUser { Semaphore s;
void insensitive() { s.wait(); sensitive(); s.post(); }
void sensitive() { // perform some operations // that need synchronization }}
Ziel: class SyncUser { synchronized void sensitive() { // perform some operations // that need synchronization }}
Dr. Welf Löwe und Markus Noga 37
Analyse
Erkennt abstrakte Synchronisation durch Muster– Keine Synchronisation– Exklusivzugriff auf Objekte– Exklusivzugriff auf Methodenmengen eines Objektes– Entweder N Leser oder 1 Schreiber
Einfach für implizite Synchronisation– Kritische Abschnitte (z.B. Java synchronized)– Barrieren
Schwieriger für explizite Synchronisation– Mutexe– Semaphoren
I.A. nicht statisch lösbarEvtl. Einsatz dynamischer Analysen
Dr. Welf Löwe und Markus Noga 38
Grenzen
Explizite Synchronisation kennt Objekte und ReferenzenGenerelle Probleme– Gehört das Objekt zu einem speziellen Codeabschnitt?– Wird es für andere Abschnitte wiederverwendet?
Aliasing-Probleme– Worauf zeigt eine Referenz?– Ist sie die einzige, die dorthin zeigt?– Welche Aussagen über Synchronisationszustand sind möglich?
Lebendigkeit– Welche Auswirkungen auf das Gesamtsystem treten ein?
Selbststabilisierende Algorithmen– Was definiert die Sprache?
Dr. Welf Löwe und Markus Noga 39
Beispiel für Grenzen
class SyncUser { Semaphore s;
void insensitive() { s.wait(); sensitive(); s.post(); }
void sensitive();
Semaphore get() { return s; }}
class SyncRoulette { Vector us; Random r=new Random( System.currentTimeMillis() );
void add(SyncUser u) { us.add(v.get()); }
void roulette() { int i=r.nextInt(us.size()); Semaphore s=(Semaphore) us.elementAt(I); if(r.nextBoolean()) s.wait(); else s.post(); }}
Dr. Welf Löwe und Markus Noga 40
Konfiguration
Festlegen der Semantik– Synchronisationsform
(z.B. Exklusivzugriff auf Objekt)– Synchronisationsmechanismus
(z.B. OS, Runtime, Dienstgeber)– etc.
Bibliothek von Synchronisatoren– deckt gängige Fälle ab
Konfigurator– Metaprogramm, das Anpassung an Synchronisator vornimmt
Dr. Welf Löwe und Markus Noga 41
Transformation
Ziel– Ersetzen der abstrakten durch konkrete Synchronisation– Abbildung auf Zielsprache
Mittel– Metaprogramme der Konfiguratoren ausführen
Mögliche Optimierungen– Einsparen von Objekten durch implizite Synchronisation– Einsparen von Synchronisationen
(z.B. durch Dominanz- und Escape-Analyse)– etc.
Werkzeug– Compost
Dr. Welf Löwe und Markus Noga 42
Synchronisation und Transaktionen
Synchronisation– Ausführung einer Methode ist atomar
Transaktion– Ausführung mehrerer Methoden ist atomar
(z.B. Abheben,Einzahlen = Überweisung)– Unterschiedliche Anforderungen je nach Einsatzkontext
Modellierung von Transaktionen– Abstrakten Sync- oder Lock-Ports– Statische Analyse schwer– Weitgehend ungelöst
Dr. Welf Löwe und Markus Noga 43
Synchronisation in der Praxis
Theorie zeigt viele schwer beherrschbare Probleme auf
Abbildungen zwischen Mechanismen eher selten
In der Praxis entscheidend: Threadfähigkeit
Single threaded multi threaded– Funktional erforderlich– Beherrschbar mit einfachen Mitteln– Wrapping mit Synchronisationsbarriere ausreichend
Multi threaded single threaded– Funktional kein Problem– Geschwindigkeitsgewinne möglich– Einsatz alter Bekannter: Escape-Analyse etc.
Dr. Welf Löwe und Markus Noga 44
Zusammenfassung
Unterscheidung nach Ingenieurskriterien sinnvoll
Gemeinsamer Ansatz– Konkrete Umsetzung analysieren– Abstrakte/Generische Anknüpfungspunkte identifizieren– Diese neu instantiieren
Unnötig bei völlig generischem Programmieren, aber– Keine Sprache kann alle Sichten vorsehen– Neue Sprachen helfen nicht beim Umgang mit Altsystemen– Es gibt immer mehr Altsysteme
Also– Analyse und Transformation sind der Schlüssel zum Reengineering– Übersetzerbau ist ein aktuelles Thema