Hauptseite UML-Diffing
Themen
- Themen
- Uml-Diagramme und ihre Repräsentation
- Besonderheiten beim UML-diffing
- Difference Detection in UML Class Diagrams by Martin Girschick
- Algorithmus
- Vergleichsfunktion
- Visualisierung
- Implementierung
- Weitere Arbeit
- UMLDiff by Zhenchang Xing, Eleni Stroulia
- Namensähnlichkeit Heuristik
- Longest Common Subbsequence (LCS)
- Most Common Pairs
- Global Similarity Algorithm
- Produktiver Einsatz
- Meine Meinung
- Generic Uml Diffing
Uml-Diagramme und ihre Repräsentation
UML-Diagramme sind Klassendiagramme welche für uns im XML-Format vorliegen.
Warum XML:
-
Hierarchische Ordnung:
Packages > Classes, Interfaces > methods,attributes
-
Baumartige Struktur in Klassendiagramm - jedes Element hat genau einen Elternknoten
Besonderheiten beim UML-diffing
-
Diffing im Allgemeinen: Vergleich zweier Subjekte welches in einer Formel resultiert die angibt welche Einfüge/Entferne und
Verschiebe Operationen auf einem der beiden ausgeführt werden muss um das Andere zu erhalten
- Bekannteste 'diff' - vergleicht Textdokumente zeilenweise und nur Einfügen/Entfernen - wird z.B. in SVN benutzt
- Uml-Diagramme sind Textdokumente -> Xml-Dokumente -> haben spezielle Struktur und Semantik
- diff - würde funktionieren (Textdokumente) - kann aber z.B. ein move nicht erkennen (löschen->einfügen)
xmidiff.png
In dem Screenshot sieht man, dass einige Attribute nach unten geschoben wurden, was in einem XML-Dokument eigentlich keine
Relevanz haben sollte
-> kein Gewinn das auf Textlevel zu vergleichen, da das höhere strukturierte Level dabei nicht respektiert wird.
-
generic xml-differ - theoretisch gute Idee - basiert darauf, dass XML-Dokumente Bäume sind und vergleicht dann 2 Bäume
Könnte schon brauchbare Resultate liefern hat aber Nachteile:
- meistens werden "Ähnlichkeiten" nicht unterstützt (z.B. bei Namen)
- Basieren ähnlich wie diff nur auf Insert und Delete
- benutzen nicht das uml-metamodel: können viele Informationen die theoretisch vorhanden sind nicht benutzen
(Vergleich IKT: je mehr man über die Quelle kennt umso besser kann man sie behandeln)
- UML-Diff:
- Konzentration auf Ähnlichkeiten - im Besonderen Strings
- Konzentration auf Metamodell
- Suchalgorithmen suchen Schichtenweise. Vergleiche nur innerhalb einer Schicht: Klasse<->Klasse, Attribut<->Attribut
- Suchalgorithmen von oben (Package) nach unten (Attribut,Operation)
- Suchalgorithmen bauen sich Landmarks auf - zuerst Punkte die sehr ähnlich/gleich sind und als Referenz
dienen
Difference Detection in UML Class Diagrams by Martin Girschick
girschick.pdf
girschick2.pdf
Diplomarbeit behandelt sein Paper ausführlicher
Ziel: uml diffs erstellen
Sehr analytisch beschrieben wie verschiedene diff-algorithmen vorgehen (Teile sind in meine Einleitung zu diff reingekommen) auch stellt er mehrere XML-Austauschformate vor
- Typ eines XML-Elements nicht änderbar (Klasse wird nie Attribut)
- Reihenfolge Klassen, Attribute, Operationen nicht relevant.
- Reihenfolge Parameter relevant.
- Klassen, Attribute, Operationen, Parameter besitzen immer Attribut name
- name innerhalb eines Containers eindeutig (Außer überladene Operationen -> Signatur benutzen
- die id im xml diagramm ist eindeutig und nicht änderbar
- Stereotypen
nicht änderbar (nur delete,add)
- Der Supplier einer Generalisierung kann nur entlang der eigenen Vererbungshierarchie verändert werden (ansonsten ist es andere Generalisierung)
- Assoziationen nur entlang der Vererbungshierarchie bewegt
-> Semantische Suche möglich
Transformationsoperation | Anwendbarkeit | Bemerkung |
add | alle | nur einzelne Elemente |
delete | alle | entfernt Element inkl. Inhalt |
rename | alle außer generalization | verändert name-XML-Attribut |
change visibility | class, attribute, operation | verändert visibility-XML-Attr. |
move | class, attribute, operation | bewegt Element in anderen Container |
clone | class, operation | z.B. Erzeugung Klasse aus Interface |
change type | alle außer generalization und package | siehe 3.1 |
modify | alle außer package | abstract, multiplicity etc. |
add/delete stereotype | alle außer generalization und package | stereotype-XML-Attribute |
add/del./mod. property | alle | frei definierbare Eigenschaftswerte |
-> Befehlssatz: add, delete, modify, move und clone.
Algorithmus
Ebenenweise zuerst Pakete, Klassen.. usw..
dabei immer nur markieren - Unterelemente werden nicht automatisch mitgelöscht oder als hinzugefügt.
add,delete haben alle
- Pakete
- modify (name) - verschieben und umbenennen
- Klassen
- suche im gesammten diagramm
- verschoben - move - mit ihrem Inhalt
- modify - name,typ
- add, delete
- Generalisierungen
- modify - verschiebung innerhalb vererbungshierarchie
- add, delete
- Attribute - verschobenes Attribut kann verschobene Assoziation bedeuten
- Assoziation
- Operationen - auch klonbar
- Operationen-Parameter
Fertig.
Vergleichsfunktion
-16 .. +16 = unwahrscheinlich .. sehr wahrscheinlich
IDMatch() - wenn die uml-diagramme mit der id matchen bricht es sofort ab
Zuerst Teilmenge mit ContainerElement -> dann der maxwert der Vergleiche.. wenn der nicht hoch genug (LIMIT konstante) wird in allen
Containern gesucht - wenn nicht da, dann add (LIMIT2).
Reihenfolge:
package > class > generalization > attribute > association > operation
findMatch(varElement, baseDiagram)
{
varContainer = varElement.Container;
baseContainer = getMatch(varContainer, baseDiagram);
foreach (baseContainer)
maxElement = highest match there;
if (value(maxElement) < DEFINED_LIMIT)
// maxElement = suche in anderen containtern auf der gleichen hierarchie ebene
if (value(maxElement) < DEFINED_LIMIT2) // das element ist neu
return null;
return maxElement;
}
Liste von Bewertungsfunktionen absteigend nach Wichtung sortiert
- location - 1. an der alten Stelle - 2. Vererbungshierarchie
- name - 1. Gleichheit, 2. Groß/KleinSchreibung, 3. Neuer Anfang,Ende 4. anderer Name
- stereotype - manche stereotype einmalig in container und können identifizierungsmerkmal sein
- type - Rückgabetyp oder bei Assoziationen supplier
- signature - bei Operation sehr markant
- parts - Inhalte von Paketen,Klassen
- predecesor - physischer vorgänger gleich
Visualisierung
SVG wegen weiterverarbeitung und einfacher generierung
Implementierung
Java - xmlparser:jdom, da SAX und DOM zu allgemein
Weitere Arbeit
Sequenzdiagramme prototypisch eingebaut
Er fand die unterschiede ziemlich groß - sein alter Vergleichsalgorithmus ging da nicht mehr
UMLDiff by Zhenchang Xing, Eleni Stroulia
xing.pdf
-
Ziel tool "JDEvAn"
- parst java-code und erstellt UML-Diagramm
- über mehrere Versionen können strukturelle Differenzen gefunden werden
-
Datenmodell = Baum mit virtuellen Wurzelknoten
- Matcht Elemente mit
- Namensähnlichkeit Heuristik - Sicher, da es selten vorkommt dass ein Element entfernt wird und mit exakt dem gleichen Namen
ein neues dazu kommt
- Ähnliche Beziehungen zu anderen Elementen - z.B. Klassen mit gleichen Attributen und Methoden
Namensähnlichkeit Heuristik
Vergleich 2er Strings
Longest Common Subbsequence (LCS)
Sucht längsten gemeinsamen Substring - Berechnung einer normierten Zahl
Motorbike and Mountainbike hat "bike" als longest common subsequence
Code:
getLCSMetric(string s1, string s2)
{
return length(LCS(s1, s2)) * 2 / (length(s1) + length(s2));
}
Nachteil: nur lexikalische Ähnlichkeit aber keine Ähnlichkeit wenn die Wortanordnung sich ändert
Most Common Pairs
Wurde in diesem Paper erfunden - Idee Strings in Blöcke von der Länge 2 Aufsplitten und Anzahl gleicher Blöcke vergleichen
getMostCommonPairs(string s1, string s2)
{
s1 = upper(s1); // since reordering words will invalidate case sensitiveness
s2 = upper(s2);
s1 = pairs(s1); // will split abcde to ['ab', 'bc', 'cd', 'de']
s2 = pairs(s2);
union = len(s1) + len(s2);
s1.retainAll(s2); // will only keep those blocks which both have in common
return len(s1)*2 / union;
}
Das hilft bei umsortierten Wörtern - und auch bei Tippfehlern - Vorteil gegen LCS vor allem bei kurzen Wörtern:
Konstruiertes Beispiel was LCS schlecht aussehen lässt:
3 Wörter: mobey money grey (mobey soll ein Tippfehler sein)
LCS: |
LCS(mobey, money) | = 2 ("mo" or "ey") | score: 2*2/(5+5) | = 0.40 |
LCS(mobey, grey) | = 2 ("ey") | score: 2*2/(5+4) | = 0.44 -> win |
MCP: |
MCP(mobey, money) | = 2 ("mo", "ey") | score: 2*2/(4+4) | = 0.5 -> win |
MCP(mobey, grey) | = 1 ("ey") | score: 1*2/(4+3) | = 0.14 |
Global Similarity Algorithm
3 Warteschlangen:
- next - matching-Elemente eines anderen levels, für nächste runde
- match - matching-elemente auf dem jetzigen level
- results - verarbeitete
Die Schlangen bestehen immer aus einem Tupel (model_original, model_vergleich)
Umldiff(vr1, vr2) {
Queue next, match, results;
level=VIRTUAL_ROOT; // beginnt mit virtuellen Root
next.add([vr1, vr2]); // fügt model1 und model2 in die next-queue
while (next != null) {
match = next.duplicate();
next.clear();
// die schleife sucht nach neuen matches
while(match != null) {
Set s = match.pop();
temp_match.add(s);
HashMap[] c1 = s[1].getChildren();
HashMap[] c2 = s[2].getChildren();
identifyMatch(c1, c2, match, next);
}
match.addAll(temp_match);
// leert die match-schlange und fügt sie zum ergebnis hinzu
// gleichzeitig wird geguckt ob die kinder matchen und werden in die nextschleife eingereiht
while(match != null) {
Set s = match.pop();
results.add(s);
HashMap[] c1 = s[1].getChildren();
HashMap[] c2 = s[2].getChildren();
if(!childrenMatchChecked(s[1],s[2]))
identifyMatch(c1, c2, match, next);
// else ??
identifyRename(c1, c2, match, next);
}
HashMap[] m1 = generateMoveCandidates(vr1, level);
HashMap[] m2 = generateMoveCandidates(vr2, level);
// versucht verschiebungen zu finden - also über mehrere level
identifyMove(m1, m2, next);
// geht eine ebene tiefer
level++ ;
}
results.addAll(markAllUnmatchEntities(vr1, remove));
results.addAll(markAllUnmatchEntities(vr2, add));
diffAttributesAndDependencies(results);
}
identifyMatch(set1, set2, match, next) {
for all e1 of a particular entity type in set1 {
e2 = set2.search_entity(e1.name);
if(e2 != null)
{
if(e2.level==level)
match.add([e1, e2]);
else
next.add([e1, e2]);
}
}
}
Similarity Metric - nur innerhalb einer klasse wegen cpu (wenn man das ziel des projekts betrachtet war - für uns trifft das nicht so sehr zu)
Produktiver Einsatz
Projekt 800 Klassen: 2.5h extrahieren und 25 Minuten vergleichen - 95% korrekte Matches (per hand überprüft)
Meine Meinung
Die hohen korrekten Zahlen durch Information wie Funktionsparameter und evtl andere Code-Informationen die nicht in jedes Klassendiagramm
reinkommen
String Similarity interessant
Algorithmus auch interessant aber ziemlich schwer zu verstehen - evtl dadurch buggy
Generic Uml Diffing
generic.pdf
Haben uml-Metamodell abstrahiert, da es zu komplex war und dann auch erweiterungen auf mehrere Dokumentformate zulässt:
Baum mit typsierten Elementen wo Attribute drandekoriert werden können
- Dokument hat einige Elemente
- Elemente haben speziellen typ und haben Beziehung zu anderen Elementen über ihre Referenz-Klasse
Beispiele: Packages, Classes, operations, attributes, parameters
- Attribute hat name und value Paare - z.B. isAbstract mit true,false
- Composite: elemente haben subelemente
Mapping von XMI zu Datamodell mit Konfigurationsdatei
Algorithmus
Bottom up mit kurz abwechselndem Bottom Down
1. nur die welche eindeutig zugeordnet werden koennen,
mehrdeutige koennen verschwunden sein und vllt auch als eindeutig zugeordnet werden
wenn auf einer hoeheren ebene ein match gefunden wurde, wo die subelemente noch nicht gematcht wurden geht es in top-down phase über
2. Top-Down: elemnt wird nach unten durchpropagiert - damit wird die wichtung beeinflusst (da parentelements anders wurden)
es wird bottom down auf eindeutige zuordnung verglichen - wenn nichts mehr neues gefunden wird geht bottom up weiter
Wichtungen bei Klassen:
Namensähnlichkeit: 0.4
Gleiche oder Ähnliche Operationen: 0.2
Gleiche oder Ähnliche Attribute: 0.2
Generalisierungen die gleich sind: 0.1
Pagete die gleich sind: 0.1