390 likes | 504 Views
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!
E N D
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
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
Round-trip Engineering: refactoring programs • Rather concrete models • Business rules from programs get lost Program Refactoring P2 P1 A Model-driven Approach to Refactoring
Round-trip Engineering: refactoring models Model Refactoring • User-edited source code and regeneration are problematic MDA tools have similar problems P2 P1 A Model-driven Approach to Refactoring
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
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
Content • Laws • Alloy • ROOL • Our approach to model-based refactoring • UML Semantics A Model-driven Approach to Refactoring
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
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
Example Applying the Pull Up Relation Law no (Account-ChAcc).x x Account ChBook Account * = Σ,v r ChAcc ChBook ChAcc * Σ = {Account,ChAcc,ChBook,r} v = {r → x} A Model-driven Approach to Refactoring
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
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
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
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
Combining Laws: Push Down Relation checks Account ChBook * no (Account – ChAcc).checks SavAcc ChAcc //Any other class Chbook cb:= new ChBook; Account acc:= ...; if acc is ChAcc -> acc.checks:=cb; ... abstractclass 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; ... A Model-driven Approach to Refactoring
//Any other class ... Account acc:= new ChAcc; acc.checks:= new ChBook; ... end 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 Combining Laws • 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
Example: Push Down Relation checks Account Account ChBook ChBook * checks * SavAcc SavAcc ChAcc ChAcc no (Account – ChAcc).checks A Model-driven Approach to Refactoring
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
Our Approach class SavAcc extends Account new= self.checks:= null; ... • 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; A Model-driven Approach to Refactoring
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
Our Approach abstractclass 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
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
Example: Push Down Relation Account ChBook checks * SavAcc ChAcc //Any other class Chbook cb:= new ChBook; Account acc:= ...; if acc is ChAcc -> ((ChAcc)acc).checks:=cb; ... abstractclass Account meth m = (pds • ... if (self is ChAcc)-> a:= ((ChAcc)self).checks; !(self is ChAcc)-> a:= null; ... class SavAcc extends Account new= skip; ... class ChAcc extends Account pub checks:ChBook; new= self.checks:= new ChBook; ... A Model-driven Approach to Refactoring
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
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
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
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
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
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
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
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
A Model-driven Approach to Refactoring Tiago Massoni Software Productivity Group UFPE
Another Example: Introduce Relation • 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 owned Customer Customer Car Car * owned = exp A Model-driven Approach to Refactoring
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
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
Applying transformation to program owned Customer Car s 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
Confinement is required (automatic from ROOL) Instances of Aux created by Customer (s attribute) are confined to Customer 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; owned Customer Car s t Aux A Model-driven Approach to Refactoring
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