Upload
others
View
0
Download
0
Embed Size (px)
Citation preview
111/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Grundlagen der Softwareproduktlinien: 4. Laufzeitparameter & Forks
Wintersemester 2019/20Gunter Saake, Jacob Krüger
211/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Letzte Woche
311/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Letzte Woche
411/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
• Ist das Modell konsistent?
• Ist eine Featureauswahl korrekt?
• Welche Features können nicht ausgewählt werden?
• Wie viele valide Produkte existieren?
• Sind zwei Modelle äquivalent?
• …
Letzte Woche
511/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Design Patterns
611/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
• Muster für die Lösung wiederkehrender Probleme
• Viele Designs für Variabilität, Entkopplung und Erweiterbarkeit
• Auswahl:• Observer• Template Method• Strategy• Decorator• …
Design Patterns
711/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Observer Pattern
VIEW
Obse
rver
s
A = 50%B = 30%C = 20%Su
bjec
t
811/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Template Method Pattern
public abstract class BubbleSorter{ protected int length = 0; protected void sort() {
if (length <= 1) return; for (int nextToLast = length-2;
nextToLast >= 0; nextToLast--) for (int index = 0;
index <= nextToLast; index++) if (outOfOrder(index)) swap(index);
} protected abstract void swap(int index); protected abstract boolean outOfOrder(int index);
}
BubbleSorter{abstract}
IntBubbleSorter DoubleBubbleSorter
911/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Beispiel: IntBubbleSorter
public class IntBubbleSorter extends BubbleSorter{ private int[] array = null; public void sort(int[] theArray) {
array = theArray; length = array.length; super.sort();
} protected void swap(int index) {
int temp = array[index]; array[index] = array[index+ 1]; array[index+1] = temp;
}protected boolean outOfOrder(int index) {
return (array[index] > array[index+ 1]); }
}
1011/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Strategy Pattern
Context <<interface>>Strategy
algorithmInterface()
algorithmInterface()ConcreteStrategyA
algorithmInterface()ConcreteStrategyB
algorithmInterface()ConcreteStrategyC
1111/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Strategy Pattern
Context <<interface>>Strategy
algorithmInterface()
algorithmInterface()ConcreteStrategyA
algorithmInterface()ConcreteStrategyB
algorithmInterface()ConcreteStrategyC
<<interface>>SortHandle
IntSortHandle DoubleSortHandle
BubbleSorter
QuickSorterClie
nts
Strategies
1211/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
• Subklassen als Erweiterungsmechanismus• Modular• Unflexibel
Vererbung
SynchronizedStack
UndoStack
SecureStack
Stack
Stack
SynchronizedStackUndoStack
SecureStack
z. B. White-Box-Framework
1311/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
• Subklassen als Erweiterungsmechanismus• Modular• Unflexibel• Kein „Mix & Match“
Vererbung
SynchronizedStack
UndoStack
SecureStack
Stack
Stack
SynchronizedStackUndoStack
SecureStack
Erweiterungen nicht
kombinierbar
mittlere Erweiterungen
nicht optional
z. B. White-Box-Framework
1411/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
• Kombinierte Klassenhierarchie• Kombinatorische Explosion der Varianten• Massive Code-Replikation
Lösungsidee
1511/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
• Kombinierte Klassenhierarchie• Kombinatorische Explosion der Varianten• Massive Code-Replikation
Lösungsidee
Stack
SynchronizedStack
SynchronizedUndoSecureStack
UndoSecureStack
SecureStackUndoStack
SynchronizedUndoStack
1611/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
• Kombinierte Klassenhierarchie• Kombinatorische Explosion der Varianten• Massive Code-Replikation
• Mehrfachvererbung• Kombinatorische Explosion• Nur in wenigen Sprachen verfügbar
(Diamantproblem)
Lösungsidee
Stack
SynchronizedStack
SynchronizedUndoSecureStack
UndoSecureStack
SecureStackUndoStack
SynchronizedUndoStack
1711/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
• Was passiert?
• new LockedUndoStack().pop()
Diamant-Problem
LockedStack
+push()+pop()+size()+lock()+unlock()
UndoStack-log+push()+pop()+undo()
LockedUndoStack
Stack-values+push()+pop()+size()
1811/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
• Was passiert?
• new LockedUndoStack().pop()
Diamant-Problem
“Multiple inheritance is good, but there is no good way to do it.”
A. SYNDER
LockedStack
+push()+pop()+size()+lock()+unlock()
UndoStack-log+push()+pop()+undo()
LockedUndoStack
Stack-values+push()+pop()+size()
1911/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Delegation statt Vererbung
class LockedStack implements IStack {final IStack _delegate;public LockedStack(IStack delegate) {this._delegate = delegate;
}private void lock() { /* ... /* }private void unlock() { /* ... /* }public void push(Object o) {lock();_delegate.push(o);unlock();
}public Object pop() {lock();Object result = _delegate.pop();unlock();return result;
}public int size() {return _delegate.size();
}}
class UndoStack implements IStack {final IStack _delegate;public UndoStack(IStack delegate) {this._delegate = delegate;
}public void undo() { /* ... /* }public void push(Object o) {remember();_delegate.push(o);
}public Object pop() {remember();return _delegate.pop();
}public int size() {return _delegate.size();
}}
2011/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Delegation statt Vererbung
class LockedStack implements IStack {final IStack _delegate;public LockedStack(IStack delegate) {this._delegate = delegate;
}private void lock() { /* ... /* }private void unlock() { /* ... /* }public void push(Object o) {lock();_delegate.push(o);unlock();
}public Object pop() {lock();Object result = _delegate.pop();unlock();return result;
}public int size() {return _delegate.size();
}}
class UndoStack implements IStack {final IStack _delegate;public UndoStack(IStack delegate) {this._delegate = delegate;
}public void undo() { /* ... /* }public void push(Object o) {remember();_delegate.push(o);
}public Object pop() {remember();return _delegate.pop();
}public int size() {return _delegate.size();
}}
Main:IStack stack = new UndoStack(
new LockedStack(new Stack()));
2111/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Decorator Pattern
LockedStack
+push()+pop()+size()+lock()+unlock()
SecureStack-keyphrase+push()+pop()+encrypt()+decrypt()
StackDecorator-delegate+push()+pop()+size()
Stack-values+push()+pop()+size()
<<interface>>IStack
+push()+pop()+size()
UndoStack-log+push()+pop()+undo()
2211/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
• Verschiedene Funktionen zur Ein- und Ausgabe• Programme operieren auf Stream-Objekten• Unabhängig von der Datenquelle und der Art der Daten
Decorator in java.io
InputStream
FileInputStream
PipedInputStream
FilterInputStream
DataInputStream
PushbackInputStream
BufferedInputStream
ByteArrayInputStream
2311/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
• Dynamische Kombination möglich
• Erweiterungen müssen alle unabhängig sein
• Kann keine Methoden hinzufügen, nur bestehende erweitern
• Kein spätes Binden (keine virtuellen Methoden)
• Viele Indirektionen in der Ausführung (Performance)
• Mehrere Objektinstanzen bilden ein Objekt (Objektschizophrenie)
Delegation vs. Vererbung
2411/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Flexible Erweiterungsmechanismen?
???
2511/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Durchgängiges Beispiel
2611/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
• Durchgängiges Beispiel für Implementierungstechniken
• Bibliothek von Graph-Datenstrukturen und –Algorithmen• Gewichtete/ungewichtete Kanten• Gerichtete/ungerichtete Kanten• Gefärbte Knoten• Algorithmen:
• Kürzester Pfad• Minimale Spannbäume• Transitive Hülle• …
Graph Bibliothek
2711/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Feature-Modell
2811/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Graph-Implementierung
class Edge { Node a, b; Color color = new Color(); Weight weight = new Weight(); Edge(Node _a, Node _b) { a = _a; b = _b; } void print() { Color.setDisplayColor(color); a.print(); b.print(); weight.print(); }}
class Edge { Node a, b; Color color = new Color(); Weight weight = new Weight(); Edge(Node _a, Node _b) { a = _a; b = _b; } void print() { Color.setDisplayColor(color); a.print(); b.print(); weight.print(); }}
class Edge { Node a, b; Color color = new Color(); Weight weight Edge(Node _a, Node _b) { a = _a; b = _b; } void print() { Color.setDisplayColor(color); a.print(); b.print(); weight.print(); }}
class Graph { Vector nv = new Vector(); Vector ev = new Vector(); Edge add(Node n, Node m) { Edge e = new Edge(n, m); nv.add(n); nv.add(m); ev.add(e); e.weight = new Weight(); return e; } Edge add(Node n, Node m, Weight w) Edge e = new Edge(n, m); nv.add(n); nv.add(m); ev.add(e); e.weight = w; return e; } void print() { for(int i = 0; i < ev.size(); i++) { ((Edge)ev.get(i)).print(); } }}
class Graph { Vector nv = new Vector(); Vector ev = new Vector(); Edge add(Node n, Node m) { Edge e = new Edge(n, m); nv.add(n); nv.add(m); ev.add(e); e.weight = new Weight(); return e; } Edge add(Node n, Node m, Weight w) Edge e = new Edge(n, m); nv.add(n); nv.add(m); ev.add(e); e.weight = w; return e; } void print() { for(int i = 0; i < ev.size(); i++) { ((Edge)ev.get(i)).print(); } }}
class Node { int id = 0; Color color = new Color(); void print() { Color.setDisplayColor(color); System.out.print(id); }}
class Node { int id = 0; Color color = new Color(); void print() { Color.setDisplayColor(color); System.out.print(id); }}
class Color { static void setDisplayColor(Color c) { ... } }
class Weight { void print() { ... } }
2911/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Laufzeitvariabilität
3011/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Parameter
3111/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Parameter –i in grep
3211/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Globale Konfigurationsoptionen
class Conf { public static boolean Logging = false; public static boolean Windows = false; public static boolean Linux = true;}class Main { public void foo() { if (Conf.Logging) log(„running foo()“); if (Conf.Windows) callWindowsMethod(); else if (Conf.Linux) callLinuxMethod(); else throw RuntimeException(); }}
3311/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Graph-Implementierung
class Graph { Vector nv = new Vector(); Vector ev = new Vector(); Edge add(Node n, Node m) { Edge e = new Edge(n, m); nv.add(n); nv.add(m); ev.add(e); if (Conf.WEIGHTED) e.weight = new Weight(); return e; } Edge add(Node n, Node m, Weight w) if (!Conf.WEIGHTED) throw RuntimeException(); Edge e = new Edge(n, m); nv.add(n); nv.add(m); ev.add(e); e.weight = w; return e; } void print() { for(int i = 0; i < ev.size(); i++) { ((Edge)ev.get(i)).print(); } }}
class Color { static void setDisplayColor(Color c) { ... } }
class Edge { Node a, b; Color color = new Color(); Weight weight = new Weight(); Edge(Node _a, Node _b) { a = _a; b = _b; } void print() { if (Conf. COLORED) Color.setDisplayColor(color); a.print(); b.print(); if (Conf.WEIGHTED) weight.print(); }}
class Node { int id = 0; Color color = new Color(); void print() { if (Conf.COLORED) Color.setDisplayColor(color); System.out.print(id); }}
class Weight { void print() { ... } }
class Conf { public static boolean COLORED = true; public static boolean WEIGHTED = false;}
3411/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Propagierte Parameter
Durch viele Aufrufepropagiert, stattglobal definiert.
3511/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
• Kommandozeilenparameter• Config-Dateien• Dialog• Quelltext• …
Konfiguration
3611/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
• Variabilität im gesamten Programm verteilt• Globale Variablen oder lange Parameterlisten
Diskussion
3711/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
• Variabilität im gesamten Programm verteilt• Globale Variablen oder lange Parameterlisten
• Konfiguration geprüft?• Änderungen zu Laufzeit möglich?• Geschützt vor Aufruf deaktivierter Funktionalitäten?
Diskussion
3811/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
• Variabilität im gesamten Programm verteilt• Globale Variablen oder lange Parameterlisten
• Konfiguration geprüft?• Änderungen zu Laufzeit möglich?• Geschützt vor Aufruf deaktivierter Funktionalitäten?
• Kein Generator• Immer sämtliche Variabilität ausgeliefert
• Codegröße, Speicherverbrauch, Performance• Ungenutzte Funktionalität als Risiko
Diskussion
3911/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
SPLE ProzessDo
mai
n En
g.Ap
plic
atio
n En
g.
Parameterauswahl(Feature-Auswahl)
Parameterliste(Feature-Modell)
Program mit Laufzeitparametern
Setzen der Startparameter Programmausführungmit gewünschtem Verhalten
4011/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Versionsverwaltungssysteme
4111/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
• Teil des Konfigurationsmanagements• Versionierung von Quelltexten• Gemeinsame, verteilte Entwicklung• Archiv alter Quelltextversionen
• Zeitstempel• Benutzerkennung• Änderungen als Delta
• Prozess:Checkout – Change – Commit – Update – Change – Commit
• Beispielsysteme:• CVS• SVN• Git• Mercurial• …
Versionsverwaltung
4211/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
• Trunk: Basis (unbenannter Branch/Master)
Branching & Merging
4311/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
• Trunk: Basis (unbenannter Branch/Master)
• Branch: Paralleles Duplikat des Systems (Fork: Komplett getrennte)
Branching & Merging
4411/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
• Trunk: Basis (unbenannter Branch/Master)
• Branch: Paralleles Duplikat des Systems (Fork: Komplett getrennte)
• Merge: Zusammenführung von Branches
Branching & Merging
4511/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
• Trunk: Basis (unbenannter Branch/Master)
• Branch: Paralleles Duplikat des Systems (Fork: Komplett getrennte)
• Merge: Zusammenführung von Branches
• Tag: Textuelles Label
Branching & Merging
V1.1
Discontinued
Customer A
4611/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Varianten Graph-Bibliothek
Basis-Variante(mit Farben und Gewichten)
Variante 2 ohne Gewichte
Variante 3 ohne Gewichteund ohne Farben
Schnellere Suche
NullPointer-Exceptionabgefangen
4711/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
• Code• Dokumentation• Modelle• Build-Skripte (Ant/Makefile)• Lizenzen• Grammatiken• Kompilierte Dateien• Generierte Dateien• …
Code- und Nicht-Code Dateien
4811/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
• Code• Dokumentation• Modelle• Build-Skripte (Ant/Makefile)• Lizenzen• Grammatiken• Kompilierte Dateien• Generierte Dateien• …
• Binärdateien erschweren die (oftmals zeilenbasierte) Konfliktbehandlung bei Merges
Code- und Nicht-Code Dateien
4911/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Varianten vs. Revisionen
Sensor-DB (Auto)
SmartCard-DB
GPS-DB
Sensor-DB (Habitat Monitoring)
Sensor-DB (Erdbeben)
V1.0
X
X
X
V1.1
X
X
X
V2.0
X
X
X
X
V3.0
X
X
X
X
Revisionen
Varia
nten
5011/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
SPLE ProzessDo
mai
n En
g.Ap
plic
atio
n En
g.
Varianten-Auswahl
Varianten-Liste
Versionsverwaltung mit Branches
Checkout des passendenBranches
Fertiges Program
Varianteals Eingabe□Sensor-DB (Auto)
Sensor-DB (Habitat Monitoring)□Sensor-DB (Erdbeben)□SmartCard-DB□GPS-DB
•Sensor-DB (Auto)•Sensor-DB (Habitat Monitoring)•Sensor-DB (Erdbeben)•SmartCard-DB•GPS-DB
Mapping von Variantezu Branch
5111/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
• Vorteile• Etablierte, stabile Systeme• Bekannter Prozess• Gute Werkzeugintegration
• Nachteile• Vermischen von Revisionen und Varianten• Entwicklung von Varianten (nicht Features) beschränkt flexible
Kombinationen• Keine strukturierte Wiederverwendung• Hoher Wartungsaufwand (Merging)
• Aktuelle Forschung fokussiert Integration von Variabilität in Versionsverwaltungssysteme
Produktlinien mit Versionsverwaltung
5211/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Build-Systeme
5311/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
• Automatisierter Build-Prozess
• Kopiert Dateien, ruft Compiler auf, startet weitere Tools, …
• Mehrere Schritte mit Bedingungen: Dateien• Einbeziehen• Ausschließen• Übersetzen• Überschreiben• …
• Werkzeugunterstützung (Make, Ant, Maven, …)
• Pro Variante eine Konfigurationsdatei (Build-Skript)
Build-Systeme
[Staples & Hill 2004]
5411/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Graph-Bibliothek
Basis-Implementierung
Variante mit Gewichten
build.xml
src
Graph.java
Edge.java
build.xml
src
Edge.java
class Edge { Node a, b; Edge(Node _a, Node _b) { a = _a; b = _b; } void print() { a.print(); b.print(); }}
class Edge { Node a, b; Weight weight; Edge(Node _a, Node _b) { a = _a; b = _b; } void print() { a.print(); b.print(); weight.print(); }}
5511/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Graph-Bibliothek: Alternative
class WEdge extends Edge { Weight weight; void print() { super.print(); weight.print(); }}
…und alle new-Aufrufe anpassen,ggf. Factory Pattern verwenden
build.xml
src
Graph.java
Edge.java
build.xml
src
WEdge.java
class Edge { Node a, b; Edge(Node _a, Node _b) { a = _a; b = _b; } void print() { a.print(); b.print(); }}
Basis-Implementierung
Variante mit Gewichten
5611/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
SPLE ProzessDo
mai
n En
g.Ap
plic
atio
n En
g.
Build-Skript pro Variante+ spezifische Dateien
Feature-Modell Basis-Implementierung
Standard Build(make, ant, …)
Fertiges Program
□Sensor-DB (Auto)
Sensor-DB (Habitat Monitoring)
□Sensor-DB (Erdbeben)
□SmartCard-DB
□GPS-DB
5711/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
• Relativ einfacher Mechanismus
• Hohe Flexibilität (beliebige Änderungen möglich)
• Benötigt wenig Vorplanung
• Entwicklung für jede Variante getrennt (ggf. hoher Aufwand im Application Engineering)
• Änderungen nur auf Dateiebene (Überschreiben ganzer Dateien)
• Änderungen an Basisimplementierung schwierig
Produktlinien mit Build-Systemen
5811/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Zusammenfassung
5911/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
• Design Patterns
• Laufzeitvariabilität
• Versionsverwaltungssysteme
• Build-Systeme
Zusammenfassung
6011/20/2019Gunter Saake, Jacob Krüger | Einführung in Softwareproduktlinien
Fragen