Using Graph Rewriting Models for Object-Oriented Oriented Software volution om Mens tom.mens@vub.ac.be rogramming echnology ab epartment of Computer Science Vrije Universiteit Brussel
Object-oriented software evolution Need better tool support for version control e.g. upgrading application frameworks collaborative software development e.g. software merging evolution at a higher level of abstraction e.g. refactoring e.g. evolution of design pattern (instances) change propagation, change impact analysis, effort estimation... Seminaire CRI, 8/3/2002 UC 2
ool support must be scalable applicable to large-scale industrial software systems generic major challenge for the research community is to develop a good theoretical understanding an underpinning for maintenance and evolution, which scales to industrial applications. [Bennett&Rajlich 2000] independent of the programming or modelling language applicable in all phases of the software life-cycle formally founded to prove that results are well-formed, correct, complete, confluent, compositional,... Seminaire CRI, 8/3/2002 UC 3
Graph rewriting can be used as formal model for software evolution graphs compact and expressive representation of program structure and behaviour 2- nature removes redundancy in source code (e.g., localised naming) graph rewriting intuitive description of transformation of complex graph-like structures theoretical results help in the analysis of such structures confluence property, parallel/sequential independence, critical pair analysis, compositionality, Seminaire CRI, 8/3/2002 UC 4
wo applications Software refactoring use graph rewriting to express and detect various kinds of behaviour preservation in collaboration with rof. Serge emeyer and rof. irk Janssens, University of ntwerp Software merging use graph rewriting to detect evolution/merge conflicts between parallel evolutions of the same software h thesis of om Mens Seminaire CRI, 8/3/2002 UC 5
pplication 1 Software Refactoring
What is refactoring? Refactorings are software transformations that restructure an object-oriented application while preserving its behaviour. ccording to Fowler (1999), refactoring improves the design of software makes software easier to understand helps you find bugs helps you program faster Formalisms can help to gain insight in the fundamental underlying principles prove correctness, e.g., to guarantee behaviour preservation Seminaire CRI, 8/3/2002 UC 7
Refactoring case study: N Goal: show feasibility of graph rewriting formalism to express and detect various kinds of behaviour preservation 1. originate(p) workstation 1 3. accept(p) workstation 3 2. send(p) fileserver 1 8.print(p) printer 1 7. accept(p) workstation 2 6. send(p) 5. accept(p) 4. send(p) Seminaire CRI, 8/3/2002 UC 8
UM class diagram Node originator acket nextnode name accept(p:acket) send(p:acket) addressee contents Workstation originate(p:acket) rintserver print(p:acket) FileServer save(p:acket) Seminaire CRI, 8/3/2002 UC 9
Java source code public class Node { public String name; public Node nextnode; public void accept(acket p) { this.send(p); } protected void send(acket p) { System.out.println( name + "sends to" + nextnode.name); nextnode.accept(p); } } public class rintserver extends Node { public void print(acket p) { System.out.println(p.contents); } public void accept(acket p) { if(p.addressee == this) this.print(p); else super.accept(p); } } Seminaire CRI, 8/3/2002 UC } public class acket { public String contents; public Node originator; public Node addressee; } public class Workstation extends Node { public void originate(acket p) { p.originator = this; this.send(p); } public void accept(acket p) { if(p.originator == this) System.err.println("no destination"); else super.accept(p); } 10
Refactoring xample 1: ncapsulate Field Fowler 1999, page 206 here is a public field Make it private and provide accessors public class Node { public String name; public Node nextnode; public void accept(acket p) { this.send(p); } protected void send(acket p) { System.out.println( name + "sends to" + nextnode.name); nextnode.accept(p); } } Seminaire CRI, 8/3/2002 UC om Mens, Vrije Universiteit } Brussel 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(acket p) { this.send(p); } protected void send(acket p) { System.out.println( this.getname() + "sends to" + this.getnextnode().getname()); this.getnextnode().accept(p); } 11
Refactoring xample 2: xtract Method Fowler 1999, page 110 You have a code fragment that can be grouped together urn the fragment into a method whose name explains the purpose of the method public class Node {... public void accept(acket p) { this.send(p); } protected void send(acket p) { System.out.println( this.getname() + "sends to" + this.getnextnode().getname()); this.getnextnode().accept(p); } } public class Node {... public void accept(acket p) { this.send(p); } protected void send(acket p) { this.log(p); this.getnextnode().accept(p); } protected void log(acket p) { System.out.println( this.getname() + "sends to" + this.getnextnode().getname()); } Seminaire CRI, 8/3/2002 UC } 12
Graph representation part 1 program structure acket C println M (s) String C contents originator addressee send M (p) I Node C I accept M (p) name nextnode (send) B (accept) B originate M (p) Workstation C rintserver C print M (p) (originate) B (accept) B (accept) B (print) B Seminaire CRI, 8/3/2002 UC 13
Graph representation part 2 program behaviour for class Node Node C void send(acket p) { 1: System.out.println( name + "sends to" + nextnode.name); 2: nextnode.accept(p); } name nextnode (send) B (accept) B 1 2 1 + M println M (s) send M (p) accept M (p) Seminaire CRI, 8/3/2002 UC 15
Refactoring xample 1: ncapsulate Field before the refactoring Node C name nextnode (send) B (accept) B 1 2 1 + M println M (s) send M (p) accept M (p) Seminaire CRI, 8/3/2002 UC 18
Refactoring xample 1: ncapsulate Field after the refactoring 1 Node C nextnode name 1 (getname) B (getnextnode) B (send) B (accept) B 2 1 String C 1 getname M getnextnode M + M println M send M accept M (s) (p) (p) Seminaire CRI, 8/3/2002 UC 19
Refactoring xample 1: ncapsulatefield graph production refactoring achieved by applying 2 occurrences of production ncapsulatefield(class,attr,type,accessor,updater) ncapsulatefield(node,name,string,getname,setname) ncapsulatefield(node,nextnode,node,getnextnode,setnextnode) (updater) B type C (accessor) B 1 6 class C attr U 4 2 3 5 6 (updater) B type C 1 1 attr U 3 class C 1 2 (accessor) B updater M accessor M 4 updater M 5 accessor M (p) (p) Seminaire CRI, 8/3/2002 UC 20
Refactoring xample 1: Behaviour preservation ncapsulatefield preserves behaviour access preserving: all attribute nodes can still be accessed via a transitive closure attr accessor M B attr 5 3 5 3 update preserving: all attribute nodes can still be updated via a transitive closure U attr U updater M B attr 4 3 4 3 Seminaire CRI, 8/3/2002 UC 21
Refactoring xample 2: xtract Method before the refactoring xtractmethod(node,send,log,{1}) Node C name nextnode (send) B 2 1 + M println M send M accept M (s) (p) (p) Seminaire CRI, 8/3/2002 UC 22
Refactoring xample 2: xtract Method after the refactoring xtractmethod(node,send,log,{1}) Node C name nextnode (log) B (send) B 1 1 2 + M println M log M send M accept M (s) (p) (p) (p) Seminaire CRI, 8/3/2002 UC 23
Refactoring xample 2: xtractmethod graph production refactoring is achieved by applying an occurrence of production xtractmethod(class,old,new,statist) given the body of method old in class, redirect all statements in Statist to the body of a parameterless method new class C class C (new) B new M α 3 (old) B (new) B α (old) B 2 3 2 1 α Statist old M new M old M 1 1 (method parameters can be introduced afterwards by ddarameter) Seminaire CRI, 8/3/2002 UC 24
Refactoring xample 2: Behaviour preservation xtractmethod preserves behaviour statement preserving: all expressions (calls, accesses, updates) that were performed before the refactoring, are still performed (via transitive closure) after the refactoring old M B a old M 1 2 3 1 B 2 new M B a 3 α Statist Seminaire CRI, 8/3/2002 UC 25
Behaviour preservation types ccess preservation (see ncapsulatefield) each method body (indirectly) performs at least the same attribute accesses as it did before the refactoring Update preservation (see ncapsulatefield) each method body (indirectly) performs at least the same attribute updates as it did before the refactoring Statement preservation (see xtractmethod) each method body (indirectly) performs at least the same statements as Call preservation each method body (indirectly) performs at least the same method calls as ype preservation each statement in each method body still has the same result type or return type as Seminaire CRI, 8/3/2002 UC 26
Refactoring: Conclusion Graph rewriting seems a useful and promising formalism to provide support for refactoring More practical validation needed Current experiment only focuses on behaviour preservation formalism can assist the refactoring process in many other ways roposed FWO research project (4 years / 3 persons) Seminaire CRI, 8/3/2002 UC 27
Refactoring: Open questions Which program properties should be preserved by refactorings? input/output behaviour, timing constraints, static versus dynamic behaviour support for non-behaviour-preserving refactorings? What is the complexity of a refactoring? complexity of applicability / complexity of applying the refactoring How do refactorings affect quality factors? increase/decrease complexity, understandability, maintainability, How can refactorings be composed/decomposed? composite refactorings / extracting refactorings from successive releases How do refactorings interact? parallel application of refactorings may lead to consistency problems How do refactorings affect design models? anguage-independent formalism for refactoring? Seminaire CRI, 8/3/2002 UC 28
pplication 2 Software Merging
What is Software Merging? Context: Collaborative Software evelopment many software developers working together on the same software need to integrate parallel changes made to the same code Software merging automated tool support for integrating these parallel changes detect inconsistencies (conflicts) between parallel changes provide support for resolving these inconsistencies Merge tools are usually part of a configuration management system or version management system e.g. CVS, RCS, ClearCase, dele,... Seminaire CRI, 8/3/2002 UC 30
roblem public class Node { public String name; public Node nextnode; public void accept(acket p) { this.send(p); } protected void send(acket p) { System.out.println( name + "sends to" + nextnode.name); nextnode.accept(p); } } xtract Method public class Node {... public void accept(acket p) { this.send(p); } protected void send(acket p) { this.log(p); this.nextnode().accept(p); } protected void log(acket p) { System.out.println( name + "sends to" + nextnode.name); } } ncapsulate Field 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(acket p) {this.send(p);} protected void send(acket p) { System.out.println(this.getName() + "send to" + this.getnextnode().getname()); this.getnextnode().accept(p); } } Current merge tools cannot merge the two parallel changes automatically due to a merge conflict in the send method Seminaire CRI, 8/3/2002 UC 31
Solution Node C Node C name nextnode (send) B (accept) B name nextnode (log) B (send) B (accept) B 1 send M 2 (p) accept M ncapsulate Field (p) log M 1 send M 1 2 (p) accept M xtract Method 1 Node C nextnode name 1 (getname) B (getnextnode) B (send) B (accept) B 1 getname M getnextnode M send M 2 (p) accept M Sequential application of the parallel graph rewritings yields correct merge result Seminaire CRI, 8/3/2002 UC 32
Solution xpress and document software evolution by means of explicit graph transformations etect whether parallel evolutions can be sequentialised (parallel/sequential independence) If not, syntactic conflicts need to be resolved first e.g. renaming same entity twice If yes, merging corresponds to sequential application of graph transformations Order of application is irrelevant (confluence property) otential semantic conflicts need to be detected (based on category-theoretical notion of pushouts/pullbacks) Seminaire CRI, 8/3/2002 UC 33
For more details see formal foundation for object-oriented software evolution om Mens. h hesis, Vrije Universiteit Brussel, September 1999 xtended abstract in roc. Int. Conf. Software Maintenance 2001, pp. 549-552, I Computer Society ress Conditional graph rewriting as a domain-independent formalism for software evolution om Mens. roc. gtive 99, ecture Notes in Computer Science 1779: 127-143, Springer-Verlag, 2000 state-of-the-art survey on software merging om Mens. I rans. Software ngineering, 28(5), May 2002 Seminaire CRI, 8/3/2002 UC 34
Open Issue: Structural Conflicts Shape Shape Square Rectangle Circle InsertClass (Shape,Quadrangle, [Square,Rectangle]) Quadrangle Circle ddsubclass(shape,arallellogram) ddsubclass(shape,riangle) Square Rectangle Shape More difficult to detect in a general way arallellogram riangle Square Rectangle Circle Seminaire CRI, 8/3/2002 UC 35
General Conclusion Graph rewriting can be used as a formal model for various aspects of software evolution software refactoring software merging Formalism allows us to express interesting properties Behaviour preservation of refactorings Compositionality of refactorings Syntactic and semantic merge conflicts More theoretical research and practical validation needed roposed FWO research project (4 years / 3 persons) pply formalism on evolution of real software systems Seminaire CRI, 8/3/2002 UC 46