4-2Refactorings

advertisement
Refactorings
1. model refactoring
2. object oriented refactorings
structural equalities in object oriented programs
OBJECT ORIENTED
REFACTORINGS
Ref2-1
Introduction
• A refactoring is a semantics-preserving transformation that maps an input program
to an output program
• “behavior” of the program is the same – at least, that is the goal…
• structure should be cleaner or easier to understand or extend
• Now known that refactorings apply to all program representations
• like model refactorings of the last lecture
Ref2-2
Fowler’s Text and Web Site
• Fowler has collected and described a
large number of common OO refactorings
• Some covered in this lecture
• Others, not part of Fowler’s collection,
are also covered
• See:
refactoring.com/catalog/index.html
Ref2-3
Big Picture
• A refactoring is an endogenous transformation domain, codomain are the same
• should be bi-directional – it has an inverse
• some directions are harder to implement than others
• each direction is usually given a distinct name
• A refactoring should be a theorem
• on the semantic equivalence of the input and output diagrams
• not something to be “liked” or “disliked”
• interestingly, correctness proofs for refactorings are scant
• rely on programming language semantics, which makes proofs hard
• you must experiment to understand the semantics of a refactoring yuck
• consequently – expect to find refactoring engines that introduce errors
Ref2-4
Refactoring Tools
• IDEs offer some built-in refactorings
• NetBeans IDE has at least these
refactorings see figure to right
• other IDEs may have more
• Most refactorings are NOT supported by IDEs
• Fowler’s text has > 70
• there are many, many more…
Ref2-5
So What?
• Programming methodologies based around refactorings
• Extreme Programming (XP)
• Agile Software Development
• natural part of maintaining or beautifying OO programs
• Refactorings automate common programming tasks that are tedious and error prone
• “Design first, code later” is alternative
• code evolves over time; connection of the code to the design slowly fades
• software decay – “code slowly sinks from engineering to hacking”
• Refactoring is the opposite of this practice
• transforming bad code into better code…
• can never transform bad code into great code….
Ref2-6
Extreme Programming
• Idea to incrementally build your
program using refactorings and
extensions
• Kerievsky’s text is a practical example
of what we talk about in this course –
how composing refactorings yield
design patterns
Ref2-7
Big Picture
• Refactorings with
• Refactorings with
are supported by NetBeans
are in Fowler’s catalog
Ref2-8
how individual methods evolve structurally
BASIC METHOD
REFACTORINGS
Ref2-9
Refactoring
• This is a radically new way to think about refactorings
• but I think it is also a fundamental way (to implement refactoring engines)
• Think of a C function declaration – not Java but C! and a call to this function:
int foo(B b, C c, D d) { /* body */ }
foo(b1,c1,d1)
Ref2-10
Move Method Refactoring
int foo(B b, C c, D d) { return b.x+c.x+d.x; }
foo(b1,c1,d1)
• How would this function definition and call appear if foo was
in class
Java Declaration
Java this
Java call
B
int foo(C c, D d) { ret x+c.x+d.x }
b
b1.foo(c1,d1)
D
int foo(B b, C c) { ret b.x+c.x+x }
d
d1.foo(b1,c1)
E
unrelated
static int foo(B b, C c, D d)
{ return b.x+c.x+d.x; }
-
E.foo(b1,c1,d1)
• This is how to think about a method move refactoring
• when you move a method B.foo(C,D) to class D, it becomes D.foo(B,C)
• and all calls to foo are updated in the above way
• Q: from the above, what constraint would preclude the above move?
• Why is tool support necessary?
Ref2-11
Move B.biff(A)  A.biff(B)
after move
• Here is the Eclipse project from which this video is taken – you do it yourself
Ref2-12
Change Method Signature
Refactoring
• Add a parameter (A a) to foo( … ) – must supply a default argument a1 yields
int foo(B b, C c, D d)
d, A a)
{ return b.x+c.x+d.x; }
...foo(b1,c1,d1,a1)...
...foo(b1,c1,d1)...
• Remove an unused parameter (A a) from the above-modified foo( … ) yields
int foo(B b, C c, D d)
{ return b.x+c.x+d.x; }
...foo(b1,c1,d1)...
Ref2-13
Change Method Signature
• Special case of remove unused parameter – A is unused
int foo(B b, C c, D d)
d, A a) { return b.x+c.x+d.x; }
Ref2-14
Corner Case of
Change Method Signature
• Today’s IDE’s don’t allow you to do this, but …suppose foo is a method of class A
class A {
int foo(B b, C c, D d)
{ return b.x+c.x+d.x; }
}
• After removing parameter A, the definition of foo should become…
class A {
static int foo(B b, C c, D d)
{ return b.x+c.x+d.x; }
}
• Why?
see my answers in slide notes
Ref2-15
Another Refactoring:
Move Via Field
• Move B.biff(A)  C.biff(A,B) via field B.c
• Semantics of move via field is a sequence of refactorings
• add parameter C to biff with argument this.c
• move B.biff(A,C)  C.biff(B,A)
Ref2-16
Move via Field Refactoring
• Goal I want you to think as precisely as you can in software design – it is not ad hoc
• Think of a refactoring engine being similar to reflection – for each
• class in a program – there is a RClass object
• method in a program – there is an RMethod object
• field in a program – there is a RField object
• So suppose rbiff is the RMethod object for method “biff”
class B {
C c;
we know: RType t = rbiff.getReturnType();
t.name.equals(“void”)
void biff(...) {
…
}
// is true
Rclass b = rbiff.getClass();
b.name.equals(“B”)
// is true
.. biff()..
}
Ref2-17
Move via Field is a
Composite Refactoring
static void MoveViaField(RMethod m, RField f) {
RType ft = f.getType();
if (ft.isPrimitive()) {
throw new RefactoringError(“field can’t be primitive”);
}
m.addParameter(f);
// adds param fname of type ft
m.moveTo(ft);
}
1.
2.
3.
verify that field f is a class and not a primitive type
add a new parameter to method m with name f.getName() with type f.getType()
move m to class f.getType()
Ref2-18
Rename Refactoring
int bar(B
foo(B b, C c, D d) { /* body1 */ }
bar(b1,c1,d1)
foo(b1,c1,d1)
• Rename changes the name of a method: foobar
• rename all method calls as well
rename
B.foo()
to
B.bar(A)
Ref2-19
Rename Refactoring
• There are constraints – just as there are constraints in UML class diagrams – for all
refactorings
• Suppose I want to rename B.biff(A) to B.zoo(A) is this legal? Eclipse produces…
Ref2-20
Yes and No…
• I think it is a bug!
• Cute, but not funny…
• It is correct because the semantics of the
program has not changed – there is no call
to B.biff(A)
• But look!
Ref2-21
Strange
• What about this case? Rename B.biff(A)  B.zoo(A)
• Eclipse does the right thing now by renaming all biff methods to zoo…
• Because there is a reference…
• Just be careful!
Ref2-22
Substitute Refactoring
int bar(B b, C c, D d) { /* body1
body2 */ }
bar(b1,c1,d1)
• Substitute changes the body of a method: body1body2
• to substitute “semantically equivalent” code fragments
• Example:
int find(String person) {
if (person.equals(“don”))
return 1;
if (person.equals(“john”)
return 2;
if (person.equals(“sally”)
return 3;
return 0;
}
int find(String person) {
String[] array = {“don”,”john”,”sally”};
for (i=0; i<array.length; i++)
if (person.equals(array[i])
return i;
return 0;
}
Ref2-23
Extract Method / Inline Method
Refactorings
Lift a block of code into a method
void printOwing() {
printBanner();
// print details
System.out.println(“name:
System.out.println(“amount:
” + _name);
” + _getOutstanding());
}
extract
method
aka “lift”
inline
method
void printOwing() {
printBanner();
printDetails();
}
void printDetails() {
// print details
System.out.println(“name:
System.out.println(“amount:
}
” + _name);
” + _getOutstanding());
Ref2-24
Beware of Refactoring Engines
• This is what Eclipse does for lift refactoring – create a method of highlighted code
• I’m impressed! Not bad at all!
Ref2-25
Beware of Refactoring Engines
• And what do you think Eclipse does in this case of Lift?
• Well, not surprising. This is HARD. Why is this hard???
Ref2-26
Why Am I Telling You This?





I like you
It’s Thursday
To wake you up
To prepare you for the midterm
Reasons I haven’t told you yet
• Reasons:
• every bit of your CS education is relevant to software design
• one of the distinguishing features about software is that you can’t just
focus on one thing – ultimately you have to consider all possibilities
• shows you why there are limitations to tools
• also tells you where things are headed in the future
Ref2-27
motivations for other refactorings – now look at some
DESIGN PROBLEMS
Ref2-28
Design Problem #1
• Start with a general-purpose class Sample that has operations on statistical
samples. You create a class that uses Sample to perform a general cost-benefit
analysis that is particular to your business application
• This design smells bad – why? And what refactoring do we use to fix it?
Ref2-29
Step 1: Eliminate Redundant Code
• Lift or extract method brings us to this point
Design still smells bad.
Why?
And what refactoring
do we apply?
Ref2-30
Step 2: Move Method Via Field
remove dependency
• Move MyAnalysis.stdev()  Sample.stdev() via field MyAnalysis.mySample
• This is beautiful! But Eclipse did more than just a move
• what extra did it do for you? see slide notes for an answer
Ref2-31
Semantic Equality of Designs
• These designs are interchangeable equal
*
MyAnalysis
1
*
Sample
MyAnalysis
1
+costAnalysis() : double
+benefitAnalysis() : double
-mySample
+average() : double
+sum() : double
+max() : double
Sample
-array : double
+array : double[]
+costAnalysis() : double
+benefitAnalysis() : double
costAnalysis() {
..
sd = // code to compute 2 * standard deviation on mySample.array
..
}
costAnalysis() {
..
sd = 2 * mySample.stdev();
..
}
benefitAnalysis() {
..
xy = // code to compute 1.5 * standard deviation on mySample.array
..
}
benefitAnalysis() {
..
xy = 1.5 * mySample.stdev();
..
}
-mySample
+average() : double
+sum() : double
+max() : double
+std() : double
stdev() {
// return standard deviation on array
}
• Why?
• Are there hidden preconditions for equality?
Ref2-32
Perspective
• We used in this example the following refactorings:
• lift or extract method
• move via field
• Eclipse does a beautiful job – almost…
can you spot the problem?
• NetBeans supports none of these refactorings
Ref2-33
Design Problem #2
• Sometimes vanilla constructors are not enough
• Consider a class of complex numbers – what is its constructor?
Complex( float im, float re ) {…}
• Suppose we need a constructor for complex numbers that takes polar coordinates
as input. What would it look like?
Complex( float radius, float angle ) {…}
• Oops! All constructors have to have the same name “Complex”!
Now What?
Ref2-34
Solution
• Hide actual constructor and use static methods with understandable names as
constructors – called static factory methods
class Complex
{
public static Complex fromCartesian(double real, double imag) {
return new Complex(real, imag);
}
public static Complex fromPolar(double radius, double angle) {
return new Complex( radius*cos(angle), radius*sin(angle));
}
private Complex(double i, double r) {
// ...
}
}
Complex c = Complex.fromPolar(1, pi); // same as fromCartesian(-1, 0)
Ref2-35
Factory Method Refactoring
A factory method provides a typically static method for a constructor.
// application
Employee
-data
...
new Employee( d )
...
+Employee(in data)
Employee( data ) {
this.data = data;
}
Employee
// application
-data
...
Employee.New( d )
...
-Employee(in data)
+New(in data)
static Employee New( data ) {
return new Employee(data);
}
Note: most refactorings are simple structural rewrites that
have many, many semantic applications.
Ref2-36
Delegate Refactoring
• Common primitive refactoring that is
usually bundled up with larger
refactorings
start here
rename delegate and hide constructor
create delegate of constructor
Ref2-37
More Generally
• Can create delegate for object methods as well – works in the obvious way
• makeDelegate of average:
• afterward, go and rename delegate….
Ref2-38
Automate makeFactory Refactoring
• In principle, this “transformation” or “refactoring” is composite
static RMethod makeFactory(RMethod c, String name) {
if (!c.isConstructor())
throw RefactoringError(“must supply constructor!”);
RMethod f = c.makeDelegate();
f.rename(name);
c.makePrivate();
return f;
}
• c.makeFactory(“New”)
class C {
c(int x) {...}
}
class C {
private c(int x) {...}
static C New(int x) {
return c(x);
}
}
Ref2-39
Design Problem #3
• There is not much that is wrong with the design below, but there is a small irritant.
You never need more than one instance of Math really
// application
Math m = new Math();
x = m.sqrt( m.sin(4.0) * m.cos(2.0) )
• What could be an improvement?
Math
+e : double
+pi : double
+sin(in x : double) : double
+cos(in x : double) : double
+sqrt(in x : double) : double
+exp(in x : double) : double
+Math()
Math
class
constructor
Ref2-40
Several Refactoring Solutions
Math
// application
Math m = new Math();
x = m.sqrt( m.sin(4.0) * m.cos(2.0) )
+e : double
+pi : double
+sin(in x : double) : double
+cos(in x : double) : double
+sqrt(in x : double) : double
+exp(in x : double) : double
+Math()
Math
// application
make static
with no Math
parameter
x = Math.sqrt( Math.sin(4.0) * Math.cos(2.0) )
// application
Math m = Math.singleton;
singleton
singleton creates
1 instance class
x = m.sqrt( m.sin(..)* m.cos(..));
...
+e : double
+pi : double
+sin(in x : double) : double
+cos(in x : double) : double
+sqrt(in x : double) : double
+exp(in x : double) : double
Java
Solution
Math
+e : double
+pi : double
+singleton : Math
+sin(in x : double) : double
+cos(in x : double) : double
+sqrt(in x : double) : double
+exp(in x : double) : double
-Math()
class Math {
public static singleton = new Math();
...
}
Design
Patterns
Solution
Ref2-41
Design Problem #4
• You are developing a tax code package
• You want to debug a NewCalcTaxes class; it does everything CalcTaxes does,
except it has new algorithms.
• How can you redesign our application so it easy to flip between classes?
// application
CalcTaxes c = new CalcTaxes();
c.salary()
c.deduction()
...
CalcTaxes
+year
+state
+deduction()
+interest()
+salary()
+charity()
NewCalcTaxes
+year
+state
+deduction()
+interest()
+salary()
+charity()
Ref2-42
Solution
• Extract an interface TaxInterface from CalcTaxes or NewCalcTaxes;
this is a refactoring called Extract Interface
• Make CalcTaxes or NewCalcTaxes implement both
• Create single TaxInterface variable and use it throughout the program
// application
TaxInterface c;
c = new CalcTaxes();
// c = new NewCalcTaxes();
«interface»
TaxInterface
+deduction()
+interest()
+salary()
+charity()
c.salary()
c.deduction()
...
CalcTaxes
+year
+state
+deduction()
+interest()
+salary()
+charity()
NewCalcTaxes
+year
+state
+deduction()
+interest()
+salary()
+charity()
Ref2-43
Extract Interface Refactoring
static RInterface extractInterface(RClass c, String name) {
RPackage p = c.getPackage();
RInterface i = p.createInterface(name);
for (RMethod m : c.getMethods()) {
if (m.isPublic()
(m.isPublic())&& !m.isConstructor())
i.addMethod(m);
}
c.implements(i);
return i;
}
1.
2.
3.
4.
5.
find the package in which class c exists
create an empty interface i in this package
create a method “stub” for each public method in c
make c implement i
return i
Ref2-44
inheritance hierarchy
MEMBER MOVEMENTS
Ref2-45
Pull Up Member
Move identical members in one or more subclasses to superclass.
Employee
Employee
-getName
Salesman
-getName
Engineer
Salesman
Engineer
-getName
how would you “automate”
or program this refactoring?
BE CAREFUL with Methods!
why? and where have you seen this before?
Ref2-46
Push Down Member
Move a member from a superclass to one or more subclasses;
remaining subclasses do not use this member.
Employee
Employee
-getName
Salesman
-getName
Engineer
Salesman
Engineer
-getName
how would you “automate”
or program this refactoring?
Ref2-47
how individual classes evolve
CLASS REFACTORINGS
Ref2-48
Design Problem #5
• You maintain a collection of Person objects:
Person
-Name
-Age
-ZipCode
-City
Name
Age
ZipCode
City
Don
55
78746
Austin
Elaine
45
44126
Cleveland
Alex
17
78746
Austin
Elizabeth
15
78761
Buda
Betty
36
78746
Austin
• Problems:
• zipcode + city information replicated
• zipcodes periodically get absorbed into another city, ex: Buda + Austin
• How can this design be improved?
Ref2-49
Class Extraction:
Table Normalization
•
Fundamental idea from databases: a design is bad when a row represents multiple,
logically distinct rows. Bad idea if a single object contains replicated smaller objects
Name
Age
Don
Name
Age
ZipCode
City
Don
55
78746
Austin
Elaine
45
44126
Cleveland
Alex
17
78746
Austin
Elizabeth
15
78761
Buda
Betty
36
78746
Austin
ZC
bad design
zipcode-city
pairings repeated
ZipCode
City
55
78746
Austin
Elaine
45
78761
Buda
Alex
17
44126
Cleveland
Elizabeth
15
Betty
36
better design
zipcode-city
facts in
separate table
Ref2-50
Table Normalize Class Refactoring
You have one class doing work that should be done by two.
Create a new class and move the relevant fields and methods
from the old class into the new class.
Person
-name
-age
-city
-state
+getName()
+getAge()
+getCity()
+getState()
normalize
Inline class
Person
-name
-age
+getName()
+getAge()
+getCity()
+getState()
-hasInhabitants
1..*
Note: Person.getCity()
delegates to
City.getName();
-livesIn
1
City
-name
-state
+getName()
+getState()
what would
it take to
implement
this?
Ref2-51
Design Problem #6
• You’ve written a single Java class that implements both a GUI and some functionality
• Your manager is unhappy with your GUI, but does see the benefit of the functionality
that you’ve created
• What can you do to help fix the problem?
GUI+Functionality
-guiAttributes
-functionalityAttributes
+guiMethods()
+functionalityMethods()
+guiMethodsCallingFMethods()
GUI
Functionality
-guiAttributes
+guiMethods()
+guiMethodsCallingFMethods()
1
1
-functionalityAttributes
+functionalityMethods()
Ref2-52
Another: Partition Class
• Just slice object/class into 2 connected pieces
Name
Age
Don
ZC
Name
Age
ZipCode
City
Don
55
78746
Austin
Elaine
45
44126
Cleveland
Alex
17
78746
Austin
Elizabeth
15
78761
Buda
Betty
36
78746
Austin
ZipCode
City
55
78746
Austin
Elaine
45
44126
Cleveland
Alex
17
78746
Austin
Elizabeth
15
78761
Buda
Betty
36
78746
Austin
what would
it take to
implement
this?
Ref2-53
Table Normalize and Partition
Refactorings
• Table Normalize: Person objects are 1:n with City objects
Person
-name
-age
-city
-state
+getName()
+getAge()
+getCity()
+getState()
Person
-name
-age
+getName()
+getAge()
-hasInhabitants
1..*
-livesIn
1
City
-name
-state
+getName()
+getState()
• Partition: Person objects are 1:1 with Rest objects
Person
-name
-age
-city
-state
+getName()
+getAge()
+getCity()
+getState()
Person
-name
-state
+getAge()
+getCity()
-1stHalf
Rest
-2ndHalf
-age
-city
1
1
Ref2-54
before iphones, children kept themselves busy pulling taffy…
HIERARCHY REFACTORINGS
Ref2-55
Extract Interface
Several clients use the same subset of a class’s interface,
or two classes have part of their interfaces in common.
Extract a subset of methods into an interface.
Employee
+getRank()
+getSkills()
+getName()
+getDept()
«interface»
Billable
+getRank()
+getSkills()
we saw
extract
interface
before
Employee
interfaces also hides implementation
details of modules/classes
+getRank()
+getSkills()
+getName()
+getDept()
Ref2-56
Simple GUI Picker
static RInterface extractSubsetInterface(RClass c, String name) {
RPackage p = c.getPackage();
RInterface i = p.createInterface(name);
Set<RMethod> methods = new Set<>();
for (RMethod m : c.getMethods())
if (m.isPublic())
methods.add(m);
Set<RMethod> meths = gui.picker(methods);
for (RMethod mm : meths)
i.addMethod(mm);
c.implements(i);
return i;
}
Ref2-57
Extract Superclass
You want extract general members from a class.
Creates an abstract superclass in which to move sharable fields and methods.
abstract
specific
definition
of method
“plug-in”
Ref2-58
Example
Polygon
Polygon
-edges[
]
Square
-edges[ ]
-edges[
+draw() ]
+area()
+draw()
+area()
Square
-edges[ ]
+draw()
+draw()
+area()
+area()
Ref2-59
What are Extract Super Preconditions?
• What superclasses can be extracted from the class below?
• Rule: whatever result you end up with must be type safe no compilation errors
class add {
int a;
int b;
int compute() { return a+b; }
}
Ref2-60
Template
Similar to Extract Superclass but uses hooks
Creates an abstract superclass in which to move fields and methods.
template
method
(hook is
abstract)
finishes
template
“plug-in”
Ref2-61
Hook Methods
• Take a general method that is customized for a plug in and make it general again
• The result is a “general” method + a lifted plug-in specific method called a hook
• What should be “lifted” into a hook is decided by a programmer not a machine
int compute(...) {
general-stuff;
x = specific-stuff;
more-general-stuff(x);
}
int compute(...) {
general-stuff;
x = hook(…);
more-general-stuff(x);
}
int hook(…) {
return specific-stuff;
}
Ref2-62
Example: “Raise” Taxes
What is an appropriate Template Superclass?
class OhioTax {
float countyTax = .09;
float stateTax = .10;
float tax( float price ) {
countyTax*price + stateTax*price;
}
}
class TexasTax {
float countyTax = .08;
float stateTax = .03;
float tax( float price ) {
countyTax*price + stateTax*price;
}
}
what are
the hook
methods?
you have
to know
how to
generalize
machines
can’t do
this
Ref2-63
Solution
abstract class Tax {
tax(price) { countyTax()*price + stateTax()*price; }
abstract float countyTax(); // hook
abstract float stateTax();
// hook
}
class OhioTax extends Tax {
float countyTax() { return .09; } // hooks for Ohio
float stateTax() { return .10; } // plug-in
}
class TexasTax extends Tax {
float countyTax() { return .08; } // hooks for Texas
float stateTax() { return .03; } // plug-m
}
Ref2-64
Pull Up Class
A superclass and subclass are not that different.
Merge them together.
Employee
Salesman
Employee
what constraints
would you insist
upon?
Ref2-65
Extract Superclass Variant
You have two classes with similar features.
Create a superclass and move the common features to the superclass.
Department
Party
+getTotalAnnualCost()
+getName()
+getHeadCount()
+getAnnualCost()
+getName()
Employee
+getAnnualCost()
+getName()
+getId()
Employee
Department
+getAnnualCost()
+getId()
+getAnnualCost()
+getHeadCount()
This looks really familiar –
How would you code it?
Ref2-66
8th Grade Math
Vector v1 = [cos(30°)*sqrt(4), sin(30°)*sqrt(4)]
Vector v2 = [cos(50°)*sqrt(7), sin(50°)*sqrt(7)]
Vector v3 = [cos(72°)*sqrt(43), sin(72°)*sqrt(43)]
• above smells bad
static Vector v(double angle, double sqrLength) {
double len = sqrt(sqrLength);
return new Vector(cos(angle)*len, sin(angle)*len);
Vector v1 = v(30,4);
Vector v2 = v(50,7);
Vector v3 = v(72,43);
Ref2-67
And There is a Lot More…
http://refactoring.com/catalog/index.html
• Consolidate Conditional Expression – how is this different than extract method?
• Hide Delegate
• Take your pick…
• The next slides will tell you the significance of refactorings
Ref2-68
skip
cultural enrichment –
view slide animations as hard-copies don’t convey full story
ADVANCES IN PROGRAM
REFACTORING
Ref2-69
Evolution of APIs
• Interesting refactoring problem
• Use of components frameworks, libraries are common in software development
• build systems faster and cheaper
• Application Program Interface (API) of a component – set of Java interfaces and
classes that are exported to application developers
• ideally, APIs don’t change, but of course they do!
• when APIs change, client code must also change
• very disruptive event in program development
• Need an easy and safe way to update applications when component’s API changes
Ref2-70
A Common API Change
• Dig’s Move Method
• instance method becomes static method of host class
• moved method takes instance of home class as extra argument
• all references to old method are replaced
with m()
call to new method update
move
update
to class
callhost
call
class home {
class bar {
class host {Note: although component code changes,
void y() {
X m(..) { ... }
static X m(..,home
f)
client code must also change
{ ... }
host.m(..,f)
void b() { f.m(..);
f.m(..)
host.m(..,f)
...
}
}
}But a component developer doesn’t have the client
code
}
}
Component
Client Code
Ref2-71
This Change is a Transformation
Pnew =   Pold
class host {
static X m(..,home f)
{ ... }
...
}
class home {
X m(..) { ... }
}
void b() { f.m();
host.m(..,f)
}
Component
class bar {
void y() {
}
}
f.m(..)
host.m(..,f)
Client Code
Ref2-72
Other Common API Changes
• Move Field
• Delete Method
• usually done after method is renamed or moved
• Change Argument Type
• ex: replace argument type with its super type
• Replace Method Call
• with another that is semantically equivalent and in the same class
• Lots of others…
Ref2-73
Dig & Johnson Paper
“How do APIs Evolve: A Story of Refactoring”
Journal of Software Maintenance & Evolution:
Research & Practice 2006
• Manually analyzed change logs, documentation, etc. of different versions of 5
medium to large systems ex: 50K to 2M LOC
• Eclipse, Struts, JHotDraw...
• Found over 80% of API changes are refactorings
• means LOTS of tedious & error-prone updates can be automated
• explain elegance of their solution using transformations
Ref2-74
In the Future
• Programmers will use advanced IDEs that “mark” API classes, methods, fields
• only way marked elements can change is by refactorings (b)
• “private” component edits modeled by transformations (e)
b3e3e2b2b1e1
b2b1
b3
b=
version
0
=
version
1
transformations to be applied
to update client code w.r.t.
changes in API
• API updates b is a projection of changes where “private” edits are removed
Ref2-75
Client Update Transformation U
U
U
client
program
client
program
= b
= b
= b
–
client
program
client
code
client
code
+
version
0
+
version
1
version
0
–
+
version
0
version
1
+
version
1
this is not how
result was originally
presented;
it is an transformational
representation of their
results
Ref2-76
In the Future
•
IDEs will be component manipulators or calculators – part of Eclipse since 2007
•
IDEs will create update functions like U for distribution
• distribute meta-functions, not components
U(x)
U(x)
•
IDEs will apply functions to code bases to automatically update them
Ref2-77
Recap
• Refactorings are behavior-preserving transformations that map an initial OO
program model to a revised OO program model
• Backbone of automated updates of programs
• Refactorings are the backbone of certain design technologies
• XP – extreme programming
which doesn’t really believe in up-front designs
• Agile Program Development
• And Design Patterns our next topic
Ref2-78
Download