• Keine Ergebnisse gefunden

Beispielrefactoring: ¨ Andern einer bidirektionalen Referenz in eine

8.3 Implementierung

8.3.2 Beispielrefactoring: ¨ Andern einer bidirektionalen Referenz in eine

1 c l a s s R e f a c t o r i n g{

2 . . .

3 op void c h a n g e B i d i r e c t i o n a l T o U n i d i r e c t i o n a l R e f e r e n c e ( E R e f e r e n c e r e f ) {

4 i f( r e f . EOpposite != n u l l)

5 E c o r e U t i l : : remove ( r e f )

6 }

7 . . .

8 }

Auflistung 8.1:Xcore Implementierung des Refactorings zur Umwandlung einer bidirektionalen in eine unidirektionale Referenz

der Menge der Refactorings wird im Folgenden die Implementierung des Refactorings zum Umwandeln einer bidirektionalen in eine unidirektionale Referenz und dessen Pro-pagation beispielhaft vorgestellt.

Um ein propagierendes Refactoring auszuf¨uhren, wurden Konnektoren in Java ge-schrieben, die dessen Aufruf aus dem Ecore-Modell durch einen Rechtsklick auf ein Modellelement erlauben. Dadurch werden nacheinander die ¨Anderung am Modell und an allen zugeh¨origen Regeln vorgenommen. Dabei ist in manchen F¨allen eine Interaktion mit dem Nutzer n¨otig, da die Propagation bei textuellen Ausdr¨ucken gelegentlich Einga-ben fordert. Die Regeln werden nach Abschluss der ¨Anderungen validiert, vor allem um die Navigierbarkeit ihrer Knoten zu pr¨ufen. Ist eine Regel nach einem propagierenden Refactoring nicht mehr valide, so wird sie markiert, um den Nutzer darauf aufmerksam zu machen. Dieser muss nun die Regel ausnahmsweise manuell anpassen.

8.3.2 Beispielrefactoring: ¨ Andern einer bidirektionalen Referenz in eine unidirektionale

Das hier n¨aher betrachtete Refactoring ist das - bereits in der Problemstellung motivierte - Umwandeln einer bidirektionalen Referenz in eine unidirektionale. Betrachtet man zun¨achst den Sachverhalt und seine Verbesserung nach Fowler:

”Es gibt eine beidseitige Assoziation,

jedoch ben¨otigt eine Klasse Eigenschaften der anderen Klasse nicht mehr.“

”Entferne das unn¨otige Ende der Assoziation.“

(¨ubersetzt aus [33])

Im EMF-Kontext bedeutet dies, dass die Entgegengesetzte einer Referenz gel¨oscht wer-den kann, sofern sie nicht mehr ben¨otigt wird. Dies stellt eine sehr einfache ¨Anderung im Modell, die in Xcore durch den Aufruf der geeigneten Utility-Methode realisiert ist, dar. Auflistung 8.1 zeigt die in Xcore modellierte Methode, welche die Referenz korrekt aus ihrem Kontext l¨oscht. Dazu wird die Referenz mittels einer von EMF gestellten Utility-Klasse gel¨oscht (Zeile 5).

Die Propagation dieses Refactorings gestaltet sich komplexer. Instanzen dieser Refe-renzen k¨onnen sowohl im Graphmuster als auch in der NAC in Form von Links vor-kommen. Die Propagation hierf¨ur ist in Auflistung 8.2 gezeigt. Sie ruft die beiden in

Auflistung 8.2: Xcore Kontrollfluss: Steuerung der Regeln zur Propagation des Refactorings zur Umwandlung einer bidirektionalen in eine unidirektionale Referenz

Abbildung 8.6 dargestellten Metaregeln auf. Dabei wird zuerst die Propagation der Re-gel in das Graphmuster aufgerufen (Zeilen 6 & 7). Danach wird, f¨ur jede NAC einzeln, die Regel zu ihrer ¨Anderung aufgerufen (Zeilen 9-13).

Die obere Regel der Abbildung 8.6 zeigt die vorzunehmenden ¨Anderungen im Graph-muster. Der Metaregel werden als Parameter eine Regelruleund die ehemals gegen¨ uber-liegende Referenz der gel¨oschtenformerOpposite¨ubergeben. Von der Regelruleausgehend wird das Graphmuster graphPattern gefunden und von dort aus der zu l¨oschende Link delLink. Die vom Link instanziierte Referenz darf nicht mehr auffindbar sein. Dies wird durch eine OCL Bedingung an den den Link repr¨asentierenden Knoten der Metaregel ausgedr¨uckt. Dies k¨onnte jedoch auch andere Ursachen als das Refactoring haben. (Zum Beispiel kann der Nutzer die Referenz gel¨oscht haben.) Daher werden anschließend sein Quellknoten node1 und sein Zielknoten node2 betrachtet. Beide Knoten sind ¨uber das InterfaceGTNodedes Graphtransformations-Metamodells typisiert, da es sich jeweils um beliebige im Muster vorkommende Knoten handeln darf. Die Pfade stellen sicher, dass beide Knoten ¨uber Klassen typisiert sind, welche durch die ReferenzformerOpposite ver-bunden werden d¨urfen. Ist dies der Fall, wird der nicht mehr valide LinkdelLinkentfernt und ein neuer Link link erzeugt. Er wird den Elementen des graphPattern hinzugef¨ugt und ist eine Instanz der Referenz formerOpposite. Der Link verbindet die Knoten node1 und node2 nun in entgegengesetzter Richtung.

Die untere Metaregel in Abbildung 8.6 zeigt die Propagation in den NACs. Da diese aus der Xcore-Operation f¨ur jede NAC einzeln aufgerufen wird, werden ihr die NACnac und die ehemalig gegen¨uberliegende Referenz ¨ubergeben. Die weitere Regel ist analog aufgebaut. Der Link, dessen zugeh¨orige Referenz nicht mehr aufgel¨ost werden kann, wird gel¨oscht und durch einen entgegengesetzten ersetzt.

Wendet man dieses Refactoring auf den Bugtracker an, um die bidirektionale Referenz zwischen Project und Ticket in eine unidirektionale umzuwandeln, so erh¨alt man das in

Abbildung 8.6:ModGraph-Regeln zur Propagation des Ecore-Modell-Refactorings zum Um-wandeln einer bidirektionalen Referenz in eine unidirektionale auf betroffene ModGraph-Regeln

BeispielmengeabhängigerModelle NACHdemRefactoring BeispielmengeabhängigerModelle

VORdemRefactoring

Abbildung 8.7: Anwendung des propagierenden Refactorings auf das Bugtracker Beispiel: Um-wandlung der bidirektionalen Referenz zwischen Project und Ticket in eine unidirektionale

Abbildung 8.7 unten gezeigte Ergebnis. Hier werden Screenshots aus der ModGraph-Werkzeugumgebung vor und nach dem propagierenden Refactoring gezeigt. Der obere Teil der Abbildung zeigt einen Ausschnitt aus dem Modell und eine der betroffenen Re-geln,getTicketsWithStatusAndSeverity, vor Anwendung des propagierenden Refactorings.

Die Referenz zwischen Projekt und Ticket ist bidirektional. Der Link in der Regel zeigt zum aktuellen Objekt des Typs Project. Das Ergebnis nach Ausf¨uhrung des propagie-renden Refactorings, welches die Referenz owningProject ersetzt, ist in Abbildung 8.7 unten dargestellt. Die Referenz zwischen Project und Ticket ist nun eine unidirektionale Referenz. Der Link in der Regel zeigt nun zum mehrwertigen tickets-Objekt.

Eine andere Version dieses Refactorings ist in [82] ver¨offentlicht. Die hier gezeigte Variante ist eine Weiterentwickung von [82].6

6Der explizite Vergleich mit der Ver¨offentlichung zeigt: Dabei wurde die explizite Verwaltung aller vom Refactoring m¨oglicherweise betroffenen Klassen durch dieses abgeschafft.