Hauptseite

UML-Diffing


Themen

Uml-Diagramme und ihre Repräsentation

UML-Diagramme sind Klassendiagramme welche für uns im XML-Format vorliegen.
Warum XML:

Besonderheiten beim UML-diffing

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
-> Semantische Suche möglich

TransformationsoperationAnwendbarkeitBemerkung
addalle nur einzelne Elemente
delete alle entfernt Element inkl. Inhalt
rename alle außer generalization verändert name-XML-Attribut
change visibilityclass, 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 typealle außer generalization und package siehe 3.1
modify alle außer package abstract, multiplicity etc.
add/delete stereotypealle außer generalization und package stereotype-XML-Attribute
add/del./mod. propertyallefrei 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
  1. Pakete
  2. Klassen
  3. Generalisierungen
  4. Attribute - verschobenes Attribut kann verschobene Assoziation bedeuten
  5. Assoziation
  6. Operationen - auch klonbar
  7. 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

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

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:
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
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