Graph transformation support forsoftware refactoring
Tom Mens
Software Engineering LabUniversity of Mons-Hainaut
http://www.umh.ac.be/~genlog
© Tom Mens, 28 June 2004, University of Kent 2
Refactoring
Definition (Fowler, 1999)
Refactoring is the process of changing a software system insuch a way that it does not alter the external behavior of thecode, yet improves its internal structure
Goals
– Improve the design of software– Increase program understanding– Detect existing bugs– Avoid introducing new bugs– Increase productivity– Increase maintainability
© Tom Mens, 28 June 2004, University of Kent 3
• Four distinct activities1. determine when an application should be refactored2. identify which refactorings should be applied, and where3. (automatically) perform these refactorings4. analyse/assess effect of applied refactoring (improved
quality)
• Support in current development environments limitedto step 3
• Step 1, 2 & 4 performed manually– time consuming, labour-intensive, error prone
Refactoring support
© Tom Mens, 28 June 2004, University of Kent 4
Refactoring formalisms
• Question– which formalisms can be used to improve tool support for
refactoring?• Answers
– Graph transformation• Program represented as a graph; transformed via graph rewrite
rules– Logic meta programming
• Program information and evolution expressed by logic rules atmetalevel
– Software metrics• Measure need for refactoring (code-smells); measure quality
improvement– Formal concept analysis, program slicing, fuzzy logic, ...
Graph Transformation
for software refactoring
© Tom Mens, 28 June 2004, University of Kent 6
Research context
• Research project– "A Formal Foundation for Software Refactoring"
Financed by• Fund for Scientific Research - Flanders
– Duration• January 2003 --> December 2006
– In collaboration with• Serge Demeyer and Dirk Janssens• University of Antwerp
© Tom Mens, 28 June 2004, University of Kent 7
Graph transformation formalism
• Formalism based on– graphs: expressive representation of program structure and
behaviour– graph transformation: intuitive representation of software
transformation• Graph transformation theory offers many theoretical
results that can help during analysis– type graph, negative application conditions, parallel and
sequential (in)dependence, confluence and critical pairanalysis
• Graph transformation tools allow us to performconcrete experiments
– Fujaba– AGG
© Tom Mens, 28 June 2004, University of Kent 8
Graph transformation tools - Fujaba
© Tom Mens, 28 June 2004, University of Kent 9
Graph transformation tools - AGG
© Tom Mens, 28 June 2004, University of Kent 10
Graph transformation tools - AGG
• Critical pair analysis
© Tom Mens, 28 June 2004, University of Kent 11
Graph transformation experiments
• Two concrete experiments– use graph transformation theory to prove that
refactorings preserve certain behaviouralproperties
• In Fujaba– use graph transformation theory to detect and
resolve structural conflicts when refactorings areapplied in parallel
• Based on critical pair analysis in AGG
Graph transformation experiment 1
behaviour preservation
© Tom Mens, 28 June 2004, University of Kent 13
workstation 1
fileserver 1
workstation 2printer 1
workstation 3
1. originate(p)
2. send(p)
3. accept(p)
4. send(p)
5. accept(p)
6. send(p)7. accept(p)
8.print(p)
Experiment 1
• Case study: LAN simulation
© Tom Mens, 28 June 2004, University of Kent 14
originate(p:Packet)
Workstation
contents
Packet
accept(p:Packet)send(p:Packet)
Nodeoriginator
name
print(p:Packet)
PrintServer
addresseenextNode
Experiment 1: UML class diagram
• Case study: LAN simulation
© Tom Mens, 28 June 2004, University of Kent 15
Experiment 1: Java source codepublic class Node { public String name; public Node nextNode; public void accept(Packet p) { this.send(p); } protected void send(Packet p) { System.out.println( name + "sends to" + nextNode.name); nextNode.accept(p); } }
public class Packet { public String contents; public Node originator; public Node addressee; }
public class Printserver extends Node { public void print(Packet p) { System.out.println(p.contents); } public void accept(Packet p) { if(p.addressee == this) this.print(p); else super.accept(p); } }
public class Workstation extends Node { public void originate(Packet p) { p.originator = this; this.send(p); } public void accept(Packet p) { if(p.originator == this) System.err.println("nodestination"); else super.accept(p); } }
© Tom Mens, 28 June 2004, University of Kent 16
Experiment 1: Program Structure
• Directed, labelled, typed graph
© Tom Mens, 28 June 2004, University of Kent 17
Experiment 1: Program Behaviour
• Behaviour of class Node
{this.send(p);}
{System.out.println( name+"sends to"+nextNode.name); nextNode.accept(p);}
© Tom Mens, 28 June 2004, University of Kent 18
Experiment 1: wf-constraints
• Type graph– Represents OO metamodel– Expresses wf-constraints
on the graph model C
M MD
V VDl
lm
m
EP
ea,u
a,u
t,p
t
p
i
ec
© Tom Mens, 28 June 2004, University of Kent 19
Experiment 1: wf-constraints
• Type graph in AGG
© Tom Mens, 28 June 2004, University of Kent 20
Experiment 1: wf-constraints
• Type graph in Fujaba
© Tom Mens, 28 June 2004, University of Kent 21
Experiment 1: wf-constraints
• Forbidden subgraphs– WF-1: a class cannot define the same method twice– WF-2: a method cannot refer to variables in
descendant classes– WF-3: a method cannot refer to parameters of
other methods
C MDm
V
l m i*a | u
e*
E
MD MD
P
pa | u
e*
E
m MC
MDm
MDm l
l
WF-1 WF-2 WF-3
© Tom Mens, 28 June 2004, University of Kent 22
Selected refactorings
• Pull up method– Replace similar methods in subclasses by common
superclass method– Precondition
• Replaced method should not refer to methods insubclasses
© Tom Mens, 28 June 2004, University of Kent 23
Experiment 1: Example Refactoring
public class Node { private String name; private Node nextNode; public String getName() { return this.name; } public void setName(String s) { this.name = s; } public Node getNextNode() { return this.nextNode; } public void setNextNode(Node n) { this.nextNode = n; } public void accept(Packet p) { this.send(p); } protected void send(Packet p) { System.out.println( this.getName() + "sends to" + this.getNextNode().getName()); this.getNextNode().accept(p); } }
public class Node { public String name; public Node nextNode; public void accept(Packet p) { this.send(p); } protected void send(Packet p) { System.out.println( name + "sends to" + nextNode.name); nextNode.accept(p); } }
• EncapsulateVariable encapsulates public variables andprovides accessor methods
© Tom Mens, 28 June 2004, University of Kent 24
(t,1) (t,1), (p,2), (t,3)outgoing edgesincoming edges
Experiment 1: Graph transformation
• EncapsulateVariable(var,getter,setter)– Parameterised transformation– Embedding mechanism
var V1
P1
var V1
setter M2
getter M3
© Tom Mens, 28 June 2004, University of Kent 25
(m,0) (m,0), (m,4), (m,5)(a,1) (c,3) (u,1) (c,2)outgoing edgesincoming edges
Experiment 1: Graph transformation
• EncapsulateVariable(var,getter,setter)– Parameterised transformation– Embedding mechanism
P2
© Tom Mens, 28 June 2004, University of Kent 26
preconditionsfor
EncapsulateVariableP2
repeat
succeed
fail
P1
Experiment 1: Graph transformation
• Controlled graph rewriting is needed to– Control the application order of productions– Specify refactoring preconditions
© Tom Mens, 28 June 2004, University of Kent 27
Experiment 1: Graph transformation
• Use preconditions– To satisfy wf-constraints– to satisfy more specific constraints
• e.g. EncapsulateVariable should not introduce accessormethod names that exist in inheritance chain
• Express negative preconditions as forbiddensubgraphs
m lgetter M
i*MDCCvar V
mVD
l
m lgetter M
i*MDCCvar V
mVD
l
© Tom Mens, 28 June 2004, University of Kent 28
• Graph invariant
• EncapsulateVariable preserves accessbehaviour
– variables remain accessible via transitive closure
Experiment 1: Behaviour preservation
MD V?*a
var VEE getter M MD1
c l aevar V
a
853MD
e*EMD
e*
1
VDl
© Tom Mens, 28 June 2004, University of Kent 29
• Graph invariant
• EncapsulateVariable preserves updatebehaviour
– variables remain updatable via transitive closure
Experiment 1: Behaviour preservation
var VEE setter MD MD1
c l uevar V
1
u
MD V?*u
742MD
e*EMD
e*
VDl
© Tom Mens, 28 June 2004, University of Kent 30
• Graph invariant
• preserves call behaviour• Trivially fulfilled for EncapsulateVariable
– all existing calls are preserved– But: new calls are introduced for each variable
access/update!
Experiment 1: Behaviour preservation
MD M?*c
MDl
© Tom Mens, 28 June 2004, University of Kent 31
• PullUpMethod(parent,child,name)– affects all subclasses– need controlled graph rewriting
name M4
child C
MDm
parent C1
2
3 l
i
P1
name M4
child C
MDm
parent C1
2
3 l
i
Experiment 1: PullUpMethod refactoring
P2
name M4
C
MDm
parent C1
5
6 l
i
name M4
C
parent C1
5
i
MD
l
i
MD
l
i
3 3
© Tom Mens, 28 June 2004, University of Kent 33
• PullUpMethod preserves calls, accesses, updates– Only if we assume isomorphism between pulled up method
definitions in subclasses
Experiment 1: Behaviour preservation
C
name MMD
m
parent C
l
iC
MD
m l
c c a a
u u
© Tom Mens, 28 June 2004, University of Kent 34
• PullUpMethod preserves calls, accesses, updates– Need tracking function to express method equivalence
Experiment 1: Behaviour preservation
P2
name M4
C
MD
m
parent C1
5
6 l
i
name M4
C
parent C1
5
i
MD
l
i
MD
l
i
3 3
© Tom Mens, 28 June 2004, University of Kent 35
Experiment 1: Conclusion
• Graph transformation useful for specifyingrefactorings
– Language independent– Visual, flexible, precise representation– Verifying different kinds of behaviour preservation
• But– need to manipulate complex graph structures
• deep copy (push down method), deep move (move method)– current-day tools are immature and not scalable– need to investigate more complex notions of behaviour
preservation
Graph transformation experiment 2
critical pair analysis
© Tom Mens, 28 June 2004, University of Kent 37
Experiment 2
• Goal– detect structural evolution conflicts due to parallel
changes• Two concrete scenarios
© Tom Mens, 28 June 2004, University of Kent 38
Experiment 2: critical pair analysis
• Use critical pair analysis– T1 and T2 form a critical pair if
• they can both be applied to the same initial graph G but• applying T1 prohibits application of T2 and/or vice versa
G H1
H2
T1
T2
X
T2
XT1
© Tom Mens, 28 June 2004, University of Kent 39
Experiment 2: parallel refactorings
• Compute critical pairs for 9 representativerefactorings
© Tom Mens, 28 June 2004, University of Kent 40
Experiment 2: parallel refactoings
• Perform confluence analysis to resolve detectedconflicts
© Tom Mens, 28 June 2004, University of Kent 41
Experiment 2: framework customisation
• Customisation conflicts due to frameworkrefactoring
© Tom Mens, 28 June 2004, University of Kent 42
Experiment 2: framework customisation
• Customisation conflicts due to frameworkrefactoring
© Tom Mens, 28 June 2004, University of Kent 43
Experiment 2: Open question
• How to deal with semantic conflicts?
Concluding remarks and future research
on formal support for refactorings
© Tom Mens, 28 June 2004, University of Kent 55
Conclusion
attributes and attribute conditions
refactoring transformationparameterised tranformation withembedding mechanism
to compose primitivetransformations and to controltheir order of application
controlled graph rewriting (Fujaba)
RefactoringGraph Transformationwf-constraintstype graph, graph expressions
to detect parallel evolutionconflicts
critical pair analysis (AGG)
preconditionsnegative application conditions(NAC)
behaviour preservavtiongraph invariants
© Tom Mens, 28 June 2004, University of Kent 56
Fundamental Research Questions
• other uses of graph transformationformalism to assist with refactoring– (de)composition of refactorings– analyse complexity of refactorings– triple graph grammars to deal with co-evolution of
refactorings at different levels
© Tom Mens, 28 June 2004, University of Kent 57
Fundamental Research Questions
• Which other formalisms can be used for refactoring ?– formal concept analysis– program slicing– ...
• What is behaviour ? Behaviour preserving ?– real-time systems (time); embedded systems (power & memory);
safety critical systems (liveness, …)– What are good program invariants ? How to express them ?
• Co-evolution: How to address consistency maintenance andchange propagation ?
– code ⇔ design ⇔ architecture ⇔ requirements
© Tom Mens, 28 June 2004, University of Kent 58
Practical Questions
• How to refactor at higher abstraction levels ?– UML, design patterns, architecture, component-based software
• How can we build more open refactoring tools ?• How can we determine where and why to refactor ?• How to deal with evolution conflicts ?• Where does refactoring fit in the process ?• What's the effect of refactoring on software quality ?• How is refactoring related to other techniques ?
– design patterns, application frameworks, aspect-orientedprogramming, generative programming, …