A Model-driven Approach to Refactoring
Tiago MassoniSoftware Productivity GroupUFPE
A Model-driven Approach to Refactoring Slide 2
Software Evolution
Need to evolve Synchronism with ever-changing business Adaptive, perfective and corrective
evolution But, in general, evolution degenerates
structure! The more you change, the harder to
change again
A Model-driven Approach to Refactoring Slide 3
Improving Evolution
Program refactoring Clean-up before further changes Improves O.O. programs keeping
observable behavior Tool support
Model refactoring Abstraction Cheaper design exploration Model-driven development
Automated traceability is needed But hard to achieve in practice
A Model-driven Approach to Refactoring Slide 4
Round-trip Engineering: refactoring programs
Bank
Account
Collectioncol
elem s
AccountBank accs
P1 P2
Program Refactoring
Rather concrete models
Business rules from programs get lost
A Model-driven Approach to Refactoring Slide 5
Round-trip Engineering: refactoring models
User-edited source code and regeneration are problematic
MDA tools have similar problems
Bank
Account
Collectioncol
elem s
AccountBank accs
P1 P2
ModelRefactoring
A Model-driven Approach to Refactoring Slide 6
Contributions
Structural model-based approach to refactorings Basis: primitive laws for Alloy (on-going work)
Definition of an analogous program transformation for each Alloy law Sequence of law applications in ROOL Given ROOL programs in conformance to
an Alloy model Alloy law’s conditions are sufficient to reason
about the analogous transformation on ROOL Result: reasoning of joint refactoring by
considering only model refactorings
A Model-driven Approach to Refactoring Slide 7
Contributions
Make the results from our work available to UMLers Semantics for UML class diagrams
Translational semantics based on Alloy Denotational semantics, using the same
semantic model as Alloy
Benefits: Automatic analysis, laws, formal refactoring, model-based program refactoring
A Model-driven Approach to Refactoring Slide 8
Content
Laws Alloy ROOL
Our approach to model-based refactoring
UML Semantics
A Model-driven Approach to Refactoring Slide 9
Algebraic Laws
Define a notion of equivalence between language constructs Programs Models
Define two semantics-preserving transformations (proven)
Restructuring and stepwise development
Clarify language constructs Axiomatic semantics
A Model-driven Approach to Refactoring Slide 10
Laws for Alloy
Alloy Modeling language Signatures (sets), relations and predicate
logic Automatic analysis
Laws for Alloy Composed to form coarse-grained laws Refactorings
Based on an equivalence notion for object models Alphabet (Σ) and view (v)
A Model-driven Approach to Refactoring Slide 11
Example Applying the Pull Up Relation Law
=
Account
ChAccChBook
x
r
Σ = {Account,ChAcc,ChBook,r}
v = {r → x}
no (Account-ChAcc).x
Σ,v
Account
ChAcc
ChBook
*
*
A Model-driven Approach to Refactoring Slide 12
Laws of Programming
Formally define program transformations
Laws for imperative programming: Hoare et al., Morgan
Laws for object-oriented programming: ROOL
A Model-driven Approach to Refactoring Slide 13
ROOL
Refinement Object-Oriented Language Formal object-oriented programming
language Similar to Java, although sequential with a
copy semantics A comprehensive set of primitive laws
Laws for commands and classes Relative completeness: normal form Proven to be behavior-preserving
A Model-driven Approach to Refactoring Slide 14
Laws for ROOL
Class Refinement Based on traditional data refinement Refinement by internal
representation change Coupling invariant relate representations
Extended to consider refinement of class hierarchies
Laws composed to prove formal refactorings
A Model-driven Approach to Refactoring Slide 15
Conformance of Programs to Alloy
We delimit our notion of conformance Structures (signatures and relations)
are implemented in the program Constraints from the model are
satisfied at certain points during program’s execution Model define invariants on how the heap of
the object-oriented program will be organized at these points
A Model-driven Approach to Refactoring Slide 16
Combining Laws: Push Down Relation
checks
SavAcc ChAcc
*
ChBookAccount
no (Account – ChAcc).checks
abstract class Account
pub checks:ChBook;
...
meth m = (pds • ...
a:= self.checks;
... class ChAcc extends Account
new= self.checks:= new ChBook;
...
class SavAcc extends Account
new= self.checks:= null;
...
//Any other class
Chbook cb:= new ChBook;
Account acc:= ...;
if acc is ChAcc -> acc.checks:= cb;
...
A Model-driven Approach to Refactoring Slide 17
Combining Laws
class Account {
pub checks:ChBook;
...
meth m = (pds • ...
a:= self.checks;
...
end
class ChAcc extends Account {
new =
self.checks:= new ChBook;
...
end
class SavAcc extends Account {
new =
self.checks:= null;
...
end
//Any other class
...
Account acc:= new ChAcc;
acc.checks:= new ChBook;
...
end
Source code in conformance with the structural model
Law application on the model is OK
But several program constructs prevent program refactoring Usual pre-conditions
are not fullfilled
Satisfies heap invariants
A Model-driven Approach to Refactoring Slide 18
Example: Push Down Relation
checks
SavAcc ChAcc
*
ChBook
checks
SavAcc ChAcc
*
Account ChBookAccount
no (Account – ChAcc).checks
A Model-driven Approach to Refactoring Slide 19
Our Approach
Define a sequence of transformations that are analogous to the modeling law Fixing those red fragments Then pushing down the attribute
Fixing the fragments Transfer the model invariant to the program Use ROOL laws to rewrite those code fragments
Defining an analogous transformation Tactics language Step-by-step guiding the rewritings in a formal way
A Model-driven Approach to Refactoring Slide 20
Our Approach
Assumption {self is SavAcc} self.checks:= null;
Applying model invariant [self<=Account and !(self<=ChAcc)=> self.checks =
null] {self.checks=null} self.checks:= null;
Simple specification self.checks:[self.checks=null,self.checks=null];
Trivially skip;
class SavAcc extends Account
new= self.checks:= null;
...
A Model-driven Approach to Refactoring Slide 21
Our Approach
Assumption (law [is test true]) if acc is ChAcc -> {acc is ChAcc} acc.checks:= cb;
Introduce cast if acc is ChAcc -> ((ChAcc)acc).checks:= cb;
//Any other class
Chbook cb:= new ChBook;
Account acc:= ...;
if acc is ChAcc -> acc.checks:= cb;
...
A Model-driven Approach to Refactoring Slide 22
Our Approach
Considering two distinct cases self is ChAcc or !(self is ChAcc)
This leads to an if statement if (self is ChAcc) -> a:= ((ChAcc)self).checks;
!(self is ChAcc)-> a:= null;
abstract class Account
pub checks:ChBook;
...
meth m = (pds • ...
a:= self.checks;
...
A Model-driven Approach to Refactoring Slide 23
Push Down Attribute Transformation
Push Down Attribute (M1: model, P1: program, A: attribute)if P1 not structured as M1
id(P1)
else
if A.modifier = pri
apply <pri-pub>
for each writing violation
case 1(as in SavAcc): replace by skip
case 2(as in other class): specialized casting
...
for each reading violation
case 1(as in Account):replace by an if stat.
...
apply <move attribute to superclass(right-left)(A)>
if old(A.modifier) = pri
apply <self-encapsulate-field(A)>
A Model-driven Approach to Refactoring Slide 24
Example: Push Down Relation
checks
SavAcc
*
ChBookAccount
abstract class Account
meth m = (pds • ...
if (self is ChAcc)->
a:= ((ChAcc)self).checks;
!(self is ChAcc)-> a:= null;
...class ChAcc extends Account
pub checks:ChBook;
new= self.checks:= new ChBook;
...
class SavAcc extends Account
new= skip;
...
//Any other class
Chbook cb:= new ChBook;
Account acc:= ...;
if acc is ChAcc ->
((ChAcc)acc).checks:= cb;
...
ChAcc
A Model-driven Approach to Refactoring Slide 25
Benefits of our Solution
Application of refactoring to models Automatic replication to source code No need for manual updates or
round-trip Model constraints are maintained
“Smart refactorings” Based on the model’s constraints
A Model-driven Approach to Refactoring Slide 26
Benefits of our Solution
Possible composition of laws Application of refactoring just as possible
in models For each modeling law two
correspondent program transformations Tool support May be used to horizontal consistency
between views of a model Class diagrams driving changes to
interaction diagrams
A Model-driven Approach to Refactoring Slide 27
Possible Limitations We rely on conformance of source
code Hard to check automatically
Identifying potential problems (red fragments) Efficiently implementable?
We have to change the program in “unexpected” ways Renaming, self-encapsulate field
Alloy’s references and ROOL’s copy semantics To be investigated
A Model-driven Approach to Refactoring Slide 28
Assumptions
Constrained conformance How models are implemented (alphabet
may help) Tactics language
Not sure if it’s the best representation Transfer the results to Java
Aliasing Fitting model-based refactoring into
evolution process What about evolutionary changes that are
not refactoring?
A Model-driven Approach to Refactoring Slide 29
UML Translational Semantics
fact BankProperties { Account = ChAcc all a:Account|lone a.~accs bk = ~accs}sig Bank { accs: set Account}sig Account{ bk: set Bank}sig ChAcc extends Account {}
A Model-driven Approach to Refactoring Slide 30
UML Translational Semantics
A set of translation rules Representing class diagrams with OCL by
using Alloy Tool support for translation
Benefits Alloy’s automatic analysis to UML Leveraging work with Alloy
Laws and refactoring Equivalence notion Model-based refactoring
A Model-driven Approach to Refactoring Slide 31
UML Translational Semantics
Possible limitations Translational semantics may not
work well Some UML concepts are not representable
in Alloy Alternative: Provide a denotational
semantics to class diagrams, using same semantic model as Alloy
Dependency on UML standards and the Alloy Analyzer API
A Model-driven Approach to Refactoring Slide 32
Status
Three modeling laws have been addressed Correspondent program transformations in tactics
format Approaches to conformance have been
investigated Aim: Investigate the whole set of modeling laws
Translation rules from UML to Alloy have been defined in detail Currently developing tool support Analysis of limitations in order to assess the need
for an alternative approach
A Model-driven Approach to Refactoring
Tiago MassoniSoftware Productivity GroupUFPE
A Model-driven Approach to Refactoring Slide 34
Another Example: Introduce Relation
CarCustomer
owned = exp
owned
*
CarCustomer
Pre-conditions: To introduce owned as relevant (in Σ), it must
depend on pre-defined relations (or be empty), as recorded in the view by owned = exp
Customer itself or its family do not declare any relation named owned
A Model-driven Approach to Refactoring Slide 35
Applying transformation to program
We must not only introduce the attribute We should also make the program conform to the
invariant (owned=exp) We identified three basic ways to define a
new relevant relation exp = empty exp = another relation r exp = a composition of relations s.t (using an
auxiliar signature) Solution: Apply class refinement
coupling invariant: based on the invariant owned = exp
A Model-driven Approach to Refactoring Slide 36
Applying transformation to program
exp = t Add new attribute to Customer
CI: self.t = self.owned Maintain reads, guards and method calls to t For each write, augment assignment
self.t,self.owned:= a,a;
exp = empty Add new attribute to Customer
CI: self.owned = null; Augment constructor
self.owned:= null;
A Model-driven Approach to Refactoring Slide 37
Applying transformation to program
exp = s.t Add new attribute to Customer
CI: !(self.s=null)=> self.owned=self.s.t,
self.owned=null Maintain reads, guards and method calls to self.s, self.s.t For each write to self.s.t, augment assignment
self.s.t,self.owned:= a,a;
CarCustomer
Aux
owned
s t
A Model-driven Approach to Refactoring Slide 38
Aux
CarCustomerowned
s t
Applying transformation to program
For each write to self.s, augment specialized assignment if !(a=null)-> self.s,self.owned:= a, a.s;
(a=null)-> self.s,self.owned:= a,null;
Instances of Aux created by Customer (s attribute) are confined
to Customer
Confinement is required (automatic from ROOL)
A Model-driven Approach to Refactoring Slide 39
Thesis
Hypothesis For each relation Rm: M->M found a relation Rp: P->P There’s a conformance relation CONF: P->M
Thesis(all m1,m2:M, p1:P |
(p1,m1) in CONF && (m1,m2) in Rm)=>
(some p2:P | p1 != p2 && (p1,p2) in Rp && (p2,m2) in CONF)