A Model-driven Approach to Refactoring Tiago Massoni Software Productivity Group UFPE 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 2 Improving Evolution Program refactoring Model refactoring Clean-up before further changes Improves O.O. programs keeping observable behavior Tool support Abstraction Cheaper design exploration Model-driven development Automated traceability is needed But hard to achieve in practice A Model-driven Approach to Refactoring Slide 3 Round-trip Engineering: refactoring programs Bank Bank a ccs Account Rather concrete co l models Collection Business rules from programs get lost e le m s Account Program Refactoring P1 A Model-driven Approach to Refactoring P2 Slide 4 Round-trip Engineering: refactoring models Model Refactoring Bank Bank a ccs Account User-edited source co l Collection code and regeneration are problematic e le m s Account MDA tools have similar problems P1 A Model-driven Approach to Refactoring P2 Slide 5 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 6 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 7 Content Laws Alloy ROOL Our approach to model-based refactoring UML Semantics A Model-driven Approach to Refactoring Slide 8 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 9 Laws for Alloy Alloy Modeling language Laws for Alloy Signatures (sets), relations and predicate logic Automatic analysis 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 10 Example Applying the Pull Up Relation Law no (Account-ChAcc).x ChBook Account =Σ,v ChBook r * x * Account ChAcc ChAcc Σ = {Account,ChAcc,ChBook,r} v = {r → x} A Model-driven Approach to Refactoring Slide 11 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 12 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 13 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 14 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 15 Combining Laws: Push Down Relation checks Account ChBook * SavAcc no (Account – ChAcc).checks ChAcc //Any other class abstract class Account Chbook cb:= new ChBook; pub checks:ChBook; Account acc:= ...; ... if acc is ChAcc -> acc.checks:= cb; meth m = (pds • ... ... a:= self.checks; ... class SavAcc extends Account new= self.checks:= null; ... A Model-driven Approach to Refactoring class ChAcc extends Account new= self.checks:= new ChBook; ... Slide 16 Combining Laws Satisfies heap invariants //Any other class ... Account acc:= new ChAcc; class Account { acc.checks:= new ChBook; pub checks:ChBook; ... ... end meth m = (pds • ... a:= self.checks; class SavAcc extends new = self.checks:= null; ... class ChAcc extends Account { end new = Account { self.checks:= new ChBook; ... end ... end A Model-driven Approach to Refactoring 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 Slide 17 Example: Push Down Relation Account checks ChBook Account * SavAcc ChAcc ChBook checks SavAcc * ChAcc no (Account – ChAcc).checks A Model-driven Approach to Refactoring Slide 18 Our Approach Define a sequence of transformations that are analogous to the modeling law Fixing the fragments Fixing those red fragments Then pushing down the attribute 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 19 Our Approach class SavAcc extends Account new= self.checks:= null; Assumption [self<=Account and !(self<=ChAcc)=> self.checks = null] {self.checks=null} self.checks:= null; Simple specification {self is SavAcc} self.checks:= null; Applying model invariant ... self.checks:[self.checks=null,self.checks=null]; Trivially skip; A Model-driven Approach to Refactoring Slide 20 Our Approach //Any other class Chbook cb:= new ChBook; Account acc:= ...; if acc is ChAcc -> acc.checks:= cb; ... 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; A Model-driven Approach to Refactoring Slide 21 Our Approach abstract class Account pub checks:ChBook; ... meth m = (pds • ... a:= self.checks; ... 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; A Model-driven Approach to Refactoring Slide 22 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 A Model-driven Approach to Refactoring Slide 23 apply <self-encapsulate-field(A)> Example: Push Down Relation Account ChBook checks SavAcc * ChAcc //Any other class abstract class Account Chbook cb:= new ChBook; meth m = (pds • ... Account acc:= ...; if (self is ChAcc)-> a:= ((ChAcc)self).checks; if acc is ChAcc -> ((ChAcc)acc).checks:= cb; !(self is ChAcc)-> a:= null; ... ... class SavAcc extends Account class ChAcc extends Account new= skip; pub checks:ChBook; ... new= self.checks:= new ChBook; A Model-driven Approach to Refactoring ... Slide 24 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 25 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 26 Possible Limitations We rely on conformance of source code Identifying potential problems (red fragments) Efficiently implementable? We have to change the program in “unexpected” ways Hard to check automatically Renaming, self-encapsulate field Alloy’s references and ROOL’s copy semantics To be investigated A Model-driven Approach to Refactoring Slide 27 Assumptions Constrained conformance Tactics language Not sure if it’s the best representation Transfer the results to Java How models are implemented (alphabet may help) Aliasing Fitting model-based refactoring into evolution process What about evolutionary changes that are not refactoring? A Model-driven Approach to Refactoring Slide 28 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 29 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 30 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 31 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 Slide 32 A Model-driven Approach to Refactoring Tiago Massoni Software Productivity Group UFPE Another Example: Introduce Relation Customer Car Customer owned Car * owned = exp 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 34 Applying transformation to program We must not only introduce the attribute We identified three basic ways to define a new relevant relation We should also make the program conform to the invariant (owned=exp) 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 35 Applying transformation to program exp = empty Add new attribute to Customer CI: self.owned = null; Augment constructor self.owned:= null; 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; A Model-driven Approach to Refactoring Slide 36 Applying transformation to program Customer owned s Car t Aux 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; A Model-driven Approach to Refactoring Slide 37 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; Confinement is required (automatic from ROOL) Customer owned s Car t Instances of Aux created by Customer (s attribute) are confined to Customer Aux A Model-driven Approach to Refactoring Slide 38 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) A Model-driven Approach to Refactoring Slide 39