cs51Refactoring.pptx
cs51Refactoring.pptx
Refactoring
• Refactoring (noun): a change made to the
internal structure of software to make it
easier to understand and cheaper to
modify without changing its observable
behavior.
• Refactor (verb): to restructure software by
applying a series of refactorings without
changing its observable behavior.
Why Refactoring?
• Easier to understand and modify
• Two hats approach
– Adding functionality
– Refactoring
Reason
• Improve design of software
• Easier to understand software
• Find bugs
• Helps in Program faster
Refactoring improves the design
• Design decay
– Putting on weight!
• Eliminate duplicate code
Refactoring makes software easier
to understand
Reasons to Refactor(smells)
• Code is duplicated
– DRY
– “Copy and paste is a design error”
• A routine is too long
• A loop is too long or too deeply nested
• A class has poor cohesion
• A class interface does not provide a
consistent level of abstraction
Reasons to Refactor(smells)..
• A parameter list has too many components
• Changes within a class tends to be
compartmentalized
• Changes require parallel modifications to
multiple classes
• Inheritance hierarchies have to be
modified in parallel
Reasons to Refactor(smells)..
• Case statements have to be modified in
parallel
• Related data items that are used together
are not organized into classes
• A routine uses more features of another
class than of its own class
• A primitive data type is overloaded
• A class doesn't do very much
Reasons to Refactor(smells)..
• A chain of routine passes tramp data
• A middleman object isn’t doing anything
• One class is overly intimate with another
• A routine has a poor name
• Data members are public
• A subclass uses only a small percentage
of its parents’ routines
Reasons to Refactor(smells)..
• Comments are used to explain difficult
code
• Global variables are used
• A routine uses setup code before a routine
call or takedown code after a routine call
• A program contains code that seems like it
might be needed someday
Refactoring catalog
• Data-level Refactorings
• Statement-level Refactorings
• Routine-level Refactorings
• Class implementation Refactorings
• Class interface Refactorings
• System-level Refactorings
Data-level Refactoring
• Replace a magic number with a named constant
• Rename variable with a clearer or more informative name
• Move an expression inline
• Replace an expression with a routine
• Introduce an intermediate variable
• Convert a multiuse variable to multiple single-use variables
• Use a local variable for local purposes rather than a parameter
• Convert a data primitive to a class
• Convert a set of type codes to a class or enumeration
• Convert a set of type codes to a class with subclasses
• Change an array to an object
• Encapsulate a collection
• Replace a traditional record with a data class
Statement-level Refactorings
• Decompose a Boolean expression
• Move a complex Boolean expression into a well-named
Boolean function
• Consolidate fragments that are duplicated within different
parts of a conditional
• Use break or return instead of a loop control variable
• Return as soon as you know the answer instead of
assigning a return value within nested if-then-else
statements
• Replace conditionals with polymorphism
• Create and use null objects instead of testing for null
values
Routine-level Refactoring
• Extract routine/extract method
• Make a routine’s code inline
• Convert a long routine to a class
• Substitute a simple algorithms for a complex algorithm
• Add a parameter
• Remove a parameter
• Separate query operations from modifications operations
• Combine similar routines by parameterizing them
• Separate routines whose behavior depends on parameters passed
in
• Pass a whole object rather than specific fields
• Pass specific fields rather than whole object
• Encapsulate downcasting
Class implementation refactoring
• Change value objects to reference objects
• Change reference objects to value objects
• Replace virtual routines with data initialization
• Change member routines or data placement
– Pull/push routine/field/constructor
• Extract specialized code into a subclass
• Combine similar code into a superclass
Class Interface refactoring
• Move a routine to another class
• Convert one class to two
• Eliminate a class
• Hide a delegate
• Remove a middleman
• Replace inheritance with delegation
• Replace delegation with inheritance
• Introduce a foreign routine
• Introduce an extension class
• Encapsulate an exposed member variable
• Remove set() routines for fields that cannot be changed
• Hide routines that are not intended to be used outside the class
• Encapsulate unused routines
• Collapse a superclass and subclass if their implementations are very similar
System-level refactoring
• Create a definitive reference source for
data you can’t control
• Change unidirectional class association to
bidirectional class association
• Change bi-directional to unidirectional
• Provide a factory method rather than a
simple constructor
• Replace error codes with exceptions or
vice versa
Refactoring guidelines
• Save the code you start with
• Keep refactoring small
• Do refactoring one at a time
• Make a list of steps you intend to take
• Make a parking lot
• Make frequent checkpoints
• Use your compiler warnings
• Retest
• Add test cases
• Review the changes
• Adjust your approach depending on the risk level of the
refactoring
When not to Refactor
• Don’t use refactoring as a cover for code
and fix
• Avoid refactoring instead of rewriting
Refactoring strategies
• Refactor when you add a routine
• Refactor when you add a class
• Refactor when you fix a defect
• Target error-prone modules
• Target high-complexity modules
• In a maintenance environment, improve the
parts you touch
• Define an interface between clean code and ugly
code, and then move code across the interface
When to refactor
• Rule of three
• Refactor when you add function
• Refactor when you need to fix a bug
• Refactor as you do a code review
Code smells
• Indicators of trouble
• Duplicated code
– Same expression in two methods of same
class
• Extract Method
• Same expression in two sibling classes
– Extract method, pull up field
• Extract class
Long method
• Signal-
– Need for comments
– Conditions, loops
• Decompose conditional
• Extract method
• Replace Temp with query
• Introduce parameter object
• Preserve the whole object
• Replace method with method object
Large class
• Too many instance variables
– Followed by duplicated code!
• Extract class
• Extract subclass
Long parameter list
• Replace parameter with method
Divergent change
• When one class is commonly changed in
different ways for different reasons
• Extract class
•
Shotgun surgery
• Every time a change is made, lot of
classes need to change
• Move method, move field
Feature envy
• Method of one class making calls to get
data of other class
• Move method
Data clumps
• Same data items used together
• Extract class
Extract Method
void printOwing(double amount) {
printBanner();
//print details
System.out.println ("name:" + _name); System.out.println ("amount" + amount);
}
int getRating()
{ return (_numberOfLateDeliveries > 5) ? 2 : 1;
}
Inline Temp
• double basePrice = anOrder.basePrice();
return (basePrice > 1000)