220 likes | 417 Views
Synchronous Refactoring of UML Diagrams and Models Using Model-to-Model Transformations. Helmut Neukirchen University of Iceland, Reykjavík, Iceland Joint work together with Hafsteinn Þór Einarsson:
E N D
Synchronous Refactoring of UML Diagrams and Models Using Model-to-Model Transformations Helmut Neukirchen University of Iceland, Reykjavík, Iceland Joint work together with Hafsteinn Þór Einarsson: Hafsteinn Þór Einarsson, Helmut Neukirchen: “An Approach and Tool for Synchronous Refactoring of UML Diagrams and Models Using Model-to-Model Transformations.” Proceedings of the 5th Workshop on Refactoring Tools co-located with ICSE 2012, June 1 2012 in Rapperswil, Switzerland, ACM Digital Library 2012.
Outline • Foundations & Motivation • Related Work • Approach • Prototype tool • Discussion
Foundations: Refactoring • Definition Refactoring: “A change made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behavior.” (Martin Fowler 1999) • Cleaning up code, but in a systematic way to avoid changing behaviour unintentionally: mechanical step-by-step instructions that even a tool can apply. • Typically, refactoring only applied to programming language source code: • Every mature development environment comes nowadays with refactoring tool support.
Java Refactoring Example:Extract Method • Code fragment that can be grouped together. • Turn fragment into method with a descriptive name. void printOwing() { double outstanding=getOutstanding(); printBanner(); //print details System.out.println ("name: " + theName); System.out.println ("amount:" + outstanding); } • Advantages: • printOwing() gets clearer. • New method can be also used elsewhere. void printOwing() { printBanner(); printDetails(getOutstanding()); } void printDetails (double outstanding) { System.out.println ("name: " + theName); System.out.println ("amount:" + outstanding); }
Extract Method: Mechanics • Create new method (“target” method) and name it by what it does. • Copy extracted code into new target method. • Scan extracted code for references to variables that are local in the scope of the source method. • Variables that are used only within extracted code: • Turn into local variables used in target method only. • Variables that are modified in target method and later-on used by source method: • Turn into return value of target method (return …) • More than one such variable: Extract Method not easily applicable! • Variables that are only read in target method: • Pass as parameter into target method. • Compile • In source method: • Replace extracted code by call to target method, • Remove any obsolete declaration of local variables. • Compile and run tests!
Motivation for Refactoring of UML • Model-Driven Engineering (MDE): • Develop software based on high-level models instead of low-level source code (low-level code may be generated from models). • Refactoring of models needed! • Most popular modeling language: • Unified Modeling Language (UML) by industry consortium Object Management Group (OMG). • Refactoring of UML needed!
Foundations:Hand-drawn UML Diagram • Obviously not possible to apply tools to it.
Foundations: Tool-drawn UML Diagram • Still lacks information that may inhibit tool processing, e.g.: • What do the referenced classes “Ticket” and “Change” contain?
Foundations:UML Models and UML Diagrams • A UML model contains all elements and their relationship. • UML diagrams visualise specific parts of the UML model from a particular viewpoint, e.g. using a class diagram. • UML models themselves have noconcrete syntax. • Only abstract syntax, i.e.: which elements are allowed/required, which relationships between elements are allowed/required? • (UML diagrams are the means to visualise a UML model for an end-user.) • UML models may even contain elements that are not contained in any related UML diagram, e.g. elements • that have been automatically generated by other tools, • that have been added manually using a low-level UML model editor, • for which once a diagrams existed, but that diagram has been deleted. • Every non-visual UML tool (e.g. code generator) works on the model! • Every (sane) human user works on the diagrams!
Foundations: UML Diagrams & Models • UML := diagrams + underlying model • Diagrams are just a partial view of the model. • Model does not contain information related to diagrams: No layout information! • Abstract syntax (=“metamodel”) of UML model: • Defined using MOF (Meta Object Facility). • The “EBNF” describing valid UML models. • Concrete syntax of UML diagram: • Defined using prose language and graphical examples.
Foundations: XMI and UMLDI File Formats • Standard formats for UML models and diagrams: • Model: XMI (XML Metadata Interchange) • Applicable to anything that has a MOF-compliant metamodel. • As UML standard does not define diagrams in terms of MOF, XMI cannot be immediately used to store diagrams. • Diagram: UMLDI (UML Diagram Interchange) • Introduces MOF-compliant metamodel for layout information XMI can be used as well for storing diagrams. • Contains only information not contained in the model. • Refer to model elements using GUID (Globally Unique Identifier).
Reference to other model elements using their GUID Name of element XMI of model (excerpt): Definition of GUID Definition of Action node UMLDI of diagram (excerpt): Layout information Reference to model element using GUID Layout information Foundations: XMI/UMLDI Example
2. Related Work • A couple of commercial UML editors support simple UML refactorings: • “Rename element”: is in fact just an operation on the model. (Due to references, diagram will refer to the changed name in the model.) • A couple of academic tools support more advanced refactorings: • However, only performed on the model. • Diagrams & model will become inconsistent.
3. Approach • Refactor model + diagram using Model to Model (M2M) transformations. • We use the transformation language Query/View/Transformation (QVT). • Standardised by OMG Natural choice for transforming UML. • Flavours: QVT Relations (declarative), QVT Operational (procedural). • Applicable to any MOF-compliant model. • Both XMI and UMLDI are MOF-compliant: • QVT can be used to transform UMLmodel + diagram. • 1 transformation for XMI + 1 transformation for UMLDI. • Consistency of model + diagram preserved when applying comparable transformations!
QVT Operational: Example • (Not shown) MOF metamodels BOOK and PUB specify: • A Book has a title and sequence of chapters, where each chapter has a title and a number of pages per chapter (nbPages), • A Publication has a title and a number of pages per publication (nbPages). • M2M transformation of an instance of Book into a corresponding instance of a Publication: Type (=metamodel) of input and output models of transformation transformationBook2Publication(in bookModel : BOOK, out pubModel : PUB); main() { bookModel.objectsOfType(Book) -> map book_to_publication(); } mapping Book::book_to_publication() : Publication { title := self.title; nbPages := self.chapters->nbPages->sum(); } Call mapping on every element of type Book from bookModel. Mapping of an instance of type Book to an instance of type Publication. Use book title as publication title. Sum up number of pages of all book chapters and use this as number of pages of publication.
4. Prototype Tool • Implemented a refactoring plug-in for open-source Eclipse UML editor Papyrus. • Stores model in XMI, diagram in UMLDI format. • Eclipse M2M project provides QVTO engine. • Implements QVT Operational language. • Allows “black-box” approach: • Implement & call functionality that is not present in QVTO by providing & calling a Java implementation.
Architecture • Java invocation library: • User interface + glue code to invoke QVTO transformations. • QVTO transformations: • The actual refactorings. • Java black-box library: • Mainly needed because the Eclipse QVTO implementation does not support the full QVT standard.
Sample Refactoring: Merge Actions • Summary: The action which is on the source-end (“first action”) of the connecting edge will be merged into the target-end action (“last action”). • Mechanics (to be applied on model and diagram): • Move the target of all incoming edges from first action to last action. • Add name of first action to name last action. • Remove the control flow edge that connects first and last action. • Remove first action. • Merge actions of activity diagram After: Before: “First action” “Connectingedge” “Last action”
Sample Merge Actions Implementation Refactor Diagram (simplified) (1 of 2) Type of input and output models of transformation … transformation MergeActions(inout notation : NOTATION, inout uml : UML); configuration property toMerge1 : String; configuration property toMerge2 : String; property objToMerge1 : notation::Shape = null; property objToMerge2 : notation::Shape = null; … main() { notation.objectsOfType(Shape) -> getSelectedObjects(); notation.objectsOfType(Shape) -> map merge(); … } query Shape::getSelectedObjects() : Void { if (self.hasGlobalId(toMerge1)) then { objToMerge1 := self; } endif; if (self.hasGlobalId(toMerge2)) then { objToMerge2 := self; } endif; } External input parameters: strings containing GUIDs of elements selected in the editor. “Global variables”: hold non-string reference to elements selected in editor Query to convert string GUIDs into non-string references. (Called on every element of type Shape.) Not shown: call of mapping to refactor model just like diagram Call mapping to refactor diagram. (Called on every element of type Shape.) Find out if current shape happens to have a GUID matching an element selected in the editor: if yes, store reference in global variable.
Sample Merge Actions Implementation Refactor Diagram (simplified) (2 of 2) mappinginout notation::Shape::merge() when { self.hasGlobalId(toMerge1) } { var firstNode : Shape = null; var lastNode : Shape = null; var connectingEdge : Edge = null; self.targetEdges->forEach(incoming) { if (incoming.source = objToMerge2) then { firstNode := objToMerge2; lastNode := objToMerge1; connectingEdge := incoming; } endif; }; … firstNode.oclAsType(Shape).targetEdges->forEach(incomingEdge) { incomingEdge.target := lastNode; }; notation.removeElement(connectingEdge); notation.removeElement(firstNode); } Mapping called on every Shape, however only applicable if Shape happens to be the Activity to be merged. getSelectedObjects() did not tell us which of the two selected nodes is the first, which is the last: find out by investigating for each edge that targets us whether it comes from the other node. First step of actual refactoring mechanics: Move the target of all incoming edges in diagram from first action to last action. Further steps of actual refactoring mechanics: remove obsolete elements from diagram. Not shown: mapping to refactor model just like diagram was refactored (plus: adjust name of activity node).
5. Discussion • By considering UML diagram as model (using UMLDI), diagram can be refactored just like a UML model. • QVT language useable for refactoring implementation. • More and more UML tools support QVT, XMI, UMLDI. • QVT refactoring implementations exchangeable between tools! • QVTO advantage: procedural programmers feel familiar. • QVTO disadvantage: procedural programming isawkward. • But having pattern matching/iterating is already nice and the fact that transformations are done on the model level (not on data structure level) is nice. • Implementation of 2 prototype refactorings is pretty short: • 205 LOC of QVTO, 57 LOC of Java for the black-box library, 284 LOC of Java for user interface and glue code.
Discussion • Other M2M languages may be better suited, e.g. QVT Relations or languages specific to refactoring domain. • Transformation of two related models not based on any formal foundations with respect to consistency. • If QVT code applied to UML model and QVT code applied to UML diagram are buggy, model and diagram may get out-of-sync. • Not considered: speed (UML models are typically small). • If you really want to use QVT in your projects: • Better QVT development environment needed: Refactoring of QVT code itself!