In this blog post we will introduce our project and the results of our work with refactorings. The work has been done as part of the lecture "Advanced Model Engineering". Our task was to evaluate and create model refactorings for fUML conform UML models. As part of this work it was also required to formulate pre- and postcondition with OCL for each of the refactorings that we created which ensure that the refactorings preserve model semantics.
But lets start with some basic terms first. What is model refactoring? What is fUML and what is model execution? And what is semantic preservation?
Surely everyone who is familiar with software development knows refactoring. When we talk about refactoring we usually think of source code written in languages such as Java or C and actions such as renaming a variable or a class or the extraction of code into a new method. Model refactoring is basically the same, just that we don't refactor source code but models. The actions include simple actions such as renaming a Class, a Property (the UML term for fields) or an Operation (the UML term for Methods), but also more complex ones such as encapsulate property. As part of our work we implemented the following refactorings:
- Rename class
- Rename property
- Rename operation
- Encapsulate property
- Pull up property
- Pull up operation
- Extract super class
fUML is a subset of UML which defines additional semantics such that it is possible to execute fUML conform UML models. This means if we consider refactorings of executable fUML models we must consider both class and activity diagrams. Since class and activity diagrams are connected we cannot simply change the class diagram without performing a change in the activity diagram. This procedure is called co-refactoring. As such each of our refactorings done to a class diagram performs a co-refactoring of related activity diagrams if this is necessary.
The co-refactoring of activity diagrams means that the semantics of the affected activites can potentially change. This requires work to ensure that the model is not changed in incorrect ways or ways that do not preserve the semantics of the model. There are two approaches to tackle this problem. The static approach evaluates the model before and after the refactoring with OCL constraints. Such pre- and postconditions define constraints that the model must satisfy. With these constraints it can be ensured that the model has a certain state that prevents incorrect refactorings.
The other approach is a dynamic one. The model is executed before and after the refactoring and the execution traces are compared as well as the model state of the refactored and non-refactored models.
For each of the above mentioned refactorings we have implemented the required transformations of the model including the co-refactoring of activities as well as pre- and postconditions. In order to evaluate our refactorings and explain them in our report we have created a comprehensive example model including class and activity diagrams. We have written a test suite with test cases for each refactoring that executes the defined pre- and postconditions and performs the model refactoring.