introduction to refactoring excerpted from ‘what is refactoring?’ by william c. wake and...
Post on 15-Jan-2016
232 views
TRANSCRIPT
Introduction to Introduction to RefactoringRefactoring
Excerpted from ‘What is Excerpted from ‘What is Refactoring?’ by William C. Wake Refactoring?’ by William C. Wake and and Refactoring: Improving the Refactoring: Improving the
Design of Existing CodeDesign of Existing Code by Martin by Martin FowlerFowler
OutlineOutline
What is Refactoring?What is Refactoring? Why Refactor?Why Refactor? When to Refactor?When to Refactor? Why Refactoring Works?Why Refactoring Works? Bad SmellsBad Smells Types of RefactoringsTypes of Refactorings
What is Refactoring?What is Refactoring?
The process of improving the design The process of improving the design of code without affecting its external of code without affecting its external behavior.behavior.
Refactor to keep your code as simple Refactor to keep your code as simple as possible.as possible.
Refactored code is clearer, simpler Refactored code is clearer, simpler and of higher quality.and of higher quality.
Refactoring is not performance Refactoring is not performance optimization.optimization.
What is Refactoring? What is Refactoring? (cont…)(cont…)
Side EffectsSide Effects Often, code size is reducedOften, code size is reduced Confusing structures are transformed Confusing structures are transformed
into simpler constructsinto simpler constructs Lessons LearnedLessons Learned
Management buy-in is necessaryManagement buy-in is necessary Must follow systematic approach to Must follow systematic approach to
refactoringrefactoring
Why Refactor?Why Refactor?
Refactor to improve the design of Refactor to improve the design of software.software. Refactoring can “tidy up” sloppy code.Refactoring can “tidy up” sloppy code. Reducing the amount of code can make Reducing the amount of code can make
future modifications easier.future modifications easier. Refactoring makes code easier to Refactoring makes code easier to
understand.understand. Refactoring helps you find bugs.Refactoring helps you find bugs. Refactoring helps you program faster.Refactoring helps you program faster.
When to Refactor?When to Refactor?
Refactoring is something you do all Refactoring is something you do all the time in small bursts.the time in small bursts.
The Rule of Three – Three strikes, The Rule of Three – Three strikes, you refactor.you refactor.
Refactor when you add features.Refactor when you add features. Refactor when you need to fix a bug.Refactor when you need to fix a bug. Refactor as you do a code review.Refactor as you do a code review.
Why Refactoring WorksWhy Refactoring Works
Programs that are hard to read are Programs that are hard to read are hard to modify.hard to modify.
Programs that have duplicated logic Programs that have duplicated logic are hard to modify.are hard to modify.
Programs that require additional Programs that require additional behavior that requires you to change behavior that requires you to change running code are hard to modify.running code are hard to modify.
Programs with complex conditional Programs with complex conditional logic are hard to modify.logic are hard to modify.
Bad SmellsBad Smells Duplicate CodeDuplicate Code Long MethodLong Method Large ClassLarge Class Long Parameter ListLong Parameter List Divergent Change – one type of change requires Divergent Change – one type of change requires
changing one subset of modules; another type of changing one subset of modules; another type of change requires changing another.change requires changing another.
Shotgun Surgery – the opposite of Shotgun Surgery – the opposite of divergent changedivergent change, a , a change requires a lot of little changes to a lot of change requires a lot of little changes to a lot of different classes.different classes.
Feature Envy – a method in a class seems to not belong.Feature Envy – a method in a class seems to not belong. Data Clumps –member fields that clump together but Data Clumps –member fields that clump together but
are not part of the same classare not part of the same class Primitive Obsession – characterized by the use of Primitive Obsession – characterized by the use of
primitives in place of class methods.primitives in place of class methods.
Bad Smells (cont…)Bad Smells (cont…) Switch Statements – often duplicated code that Switch Statements – often duplicated code that
can be replaced by polymorphism.can be replaced by polymorphism. Parallel Inheritance Hierarchies – duplicated code Parallel Inheritance Hierarchies – duplicated code
in subclasses that share a common ancestor.in subclasses that share a common ancestor. Lazy Class – a class that has little meaning in the Lazy Class – a class that has little meaning in the
of the software.of the software. Speculative Generality – methods (often stubs) Speculative Generality – methods (often stubs)
that are placeholders for future features.that are placeholders for future features. Temporary Field – a member variable that is only Temporary Field – a member variable that is only
used under certain circumstances.used under certain circumstances. Message Chains – object that requests an object Message Chains – object that requests an object
for another object which asks…for another object which asks…
Bad Smells (cont…)Bad Smells (cont…) Middle Man – a class that is just a “pass-through” Middle Man – a class that is just a “pass-through”
method with little logic.method with little logic. Inappropriate Intimacy – violation of private parts.Inappropriate Intimacy – violation of private parts. Alternate Class with Different Interfaces - two Alternate Class with Different Interfaces - two
methods that do the same thing, but have different methods that do the same thing, but have different interfaces.interfaces.
Incomplete Library Classes – a framework that Incomplete Library Classes – a framework that doesn’t do everything you need.doesn’t do everything you need.
Data Class – classes that have getters and setters, Data Class – classes that have getters and setters, but no real function.but no real function.
Refused Bequest – a subclass that over-rides most of Refused Bequest – a subclass that over-rides most of the functionality provided by its superclass.the functionality provided by its superclass.
Comments – text that explains bad code.Comments – text that explains bad code.
Types of RefactoringsTypes of Refactorings Moving Features Between ObjectsMoving Features Between Objects
Goal: ensure tight cohesionGoal: ensure tight cohesion Organizing DataOrganizing Data
Goal: encapsulate data appropriatelyGoal: encapsulate data appropriately Simplifying Conditional ExpressionsSimplifying Conditional Expressions
Goal: unclutter decision pointsGoal: unclutter decision points Making Method Calls SimplerMaking Method Calls Simpler
Goal: user parameterization sensiblyGoal: user parameterization sensibly Dealing With GeneralizationDealing With Generalization
Goal: use inheritance structure properlyGoal: use inheritance structure properly Big RefactoringsBig Refactorings
Goal: re-architect if necessaryGoal: re-architect if necessary Composing MethodsComposing Methods
Goal: ensure loose couplingGoal: ensure loose coupling
Moving Features Between Moving Features Between ObjectsObjects
Extract ClassExtract Class You have one class doing work that You have one class doing work that
should be done by two.should be done by two. Create a new class and move the Create a new class and move the
relevant fields and methods from the relevant fields and methods from the old class into the new class.old class into the new class.
SmellsSmells Large Class, Data ClumpsLarge Class, Data Clumps
Organizing DataOrganizing Data
Replace Magic Number with Replace Magic Number with Symbolic ConstantSymbolic Constant You have a literal number with a You have a literal number with a
particular meaningparticular meaning Create a constant, name it after the Create a constant, name it after the
meaning, and replace the number with meaning, and replace the number with it.it.
Simplifying Conditional Simplifying Conditional ExpressionsExpressions
Decompose ConditionalDecompose Conditional You have a complicated conditional (if-You have a complicated conditional (if-
then-else) statement.then-else) statement. Extract methods from the condition, Extract methods from the condition,
then part, and else parts.then part, and else parts.
Making Method Calls Making Method Calls SimplerSimpler
Rename MethodRename Method The name of a method does not reveal The name of a method does not reveal
its purpose.its purpose. Change the name of the method.Change the name of the method.
Dealing with Dealing with GeneralizationGeneralization
Extract SubclassExtract Subclass A class has features that are used only A class has features that are used only
in some instances.in some instances. Create a subclass for that subset of Create a subclass for that subset of
features.features.
Big RefactoringsBig Refactorings
Convert Procedural Design to Convert Procedural Design to ObjectsObjects You have code written in a procedural You have code written in a procedural
stylestyle Turn the data records into objects, Turn the data records into objects,
break up the behavior, and move the break up the behavior, and move the behavior to the objects.behavior to the objects.
Composing MethodsComposing Methods
Extract MethodExtract Method You have a code fragment that can be You have a code fragment that can be
grouped togethergrouped together Turn the fragment into a method whose Turn the fragment into a method whose
name explains the purpose of the name explains the purpose of the method.method.
SmellsSmells Large MethodLarge Method CommentsComments
Extract MethodExtract Method MechanicsMechanics
create new method create new method name by what it does, not how it does itname by what it does, not how it does it rule of thumb: if you can’t come up with a meaningful name, rule of thumb: if you can’t come up with a meaningful name,
then don’t extractthen don’t extract copy extracted code from source to targetcopy extracted code from source to target locate variables used in target but defined in source locate variables used in target but defined in source
scope. Choices:scope. Choices: if modified by target, consider method as a queryif modified by target, consider method as a query make variables params to methodmake variables params to method if can be used only in extracted code, make tempsif can be used only in extracted code, make temps
compile (and test, as appropriate)compile (and test, as appropriate) replace extracted code in source with callreplace extracted code in source with call
remove extraneous variablesremove extraneous variables compile and testcompile and test
Extract Method (cont…)Extract Method (cont…)void printOwing()void printOwing(){{
Enumeration e = _order.elements();Enumeration e = _order.elements();double outstanding = 0.0;double outstanding = 0.0;
System.out.println (“******************************”);System.out.println (“******************************”);System.out.println (“***** Customer Owes *****”);System.out.println (“***** Customer Owes *****”);System.out.println (“******************************”);System.out.println (“******************************”);
while (e.hasMoreElements())while (e.hasMoreElements()){{
Order each (Order) e.nextElement();Order each (Order) e.nextElement();outstanding += each.getAmount();outstanding += each.getAmount();
}}
System.out.println(“name: “ + _name);System.out.println(“name: “ + _name);System.out.println(“amount “ + outstanding);System.out.println(“amount “ + outstanding);
}}
“Islands” of abstraction
Extract Method (cont…)Extract Method (cont…)void printOwing()void printOwing(){{
Enumeration e = _order.elements();Enumeration e = _order.elements();double outstanding = 0.0;double outstanding = 0.0;
System.out.println (“******************************”);System.out.println (“******************************”);System.out.println (“***** Customer Owes *****”);System.out.println (“***** Customer Owes *****”);System.out.println (“******************************”);System.out.println (“******************************”);
while (e.hasMoreElements())while (e.hasMoreElements()){{
Order each (Order) e.nextElement();Order each (Order) e.nextElement();outstanding += each.getAmount();outstanding += each.getAmount();
}}
System.out.println(“name: “ + _name);System.out.println(“name: “ + _name);System.out.println(“amount “ + outstanding);System.out.println(“amount “ + outstanding);
}}
Extract Method (cont…)Extract Method (cont…)void printOwing()void printOwing(){{
Enumeration e = _order.elements();Enumeration e = _order.elements();double outstanding = 0.0;double outstanding = 0.0;
printBanner();printBanner();
while (e.hasMoreElements())while (e.hasMoreElements()){{
Order each (Order) e.nextElement();Order each (Order) e.nextElement();outstanding += each.getAmount();outstanding += each.getAmount();
}}
System.out.println(“name: “ + _name);System.out.println(“name: “ + _name);System.out.println(“amount “ + outstanding);System.out.println(“amount “ + outstanding);
}}
Extract Method (cont…)Extract Method (cont…)void printBanner()void printBanner(){{
System.out.println (“******************************”);System.out.println (“******************************”);System.out.println (“***** Customer Owes *****”);System.out.println (“***** Customer Owes *****”);System.out.println (“******************************”);System.out.println (“******************************”);
}}
Extract Method (cont…)Extract Method (cont…)void printOwing()void printOwing(){{
Enumeration e = _order.elements();Enumeration e = _order.elements();double outstanding = 0.0;double outstanding = 0.0;
printBanner();printBanner();
while (e.hasMoreElements())while (e.hasMoreElements()){{
Order each (Order) e.nextElement();Order each (Order) e.nextElement();outstanding += each.getAmount();outstanding += each.getAmount();
}}
System.out.println(“name: “ + _name);System.out.println(“name: “ + _name);System.out.println(“amount “ + outstanding);System.out.println(“amount “ + outstanding);
}}
Extract Method (cont…)Extract Method (cont…)void printOwing()void printOwing(){{
Enumeration e = _order.elements();Enumeration e = _order.elements();double outstanding = 0.0;double outstanding = 0.0;
printBanner();printBanner();
while (e.hasMoreElements())while (e.hasMoreElements()){{
Order each (Order) e.nextElement();Order each (Order) e.nextElement();outstanding += each.getAmount();outstanding += each.getAmount();
}}
printDetails(outstanding);printDetails(outstanding);}}
Extract Method (cont…)Extract Method (cont…)
void printDetails(double outstanding)void printDetails(double outstanding){{
System.out.println(“name: “ + _name);System.out.println(“name: “ + _name);System.out.println(“amount “ + outstanding);System.out.println(“amount “ + outstanding);
}}
Extract Method (cont…)Extract Method (cont…)void printOwing()void printOwing(){{
Enumeration e = _order.elements();Enumeration e = _order.elements();double outstanding = 0.0;double outstanding = 0.0;
printBanner();printBanner();
while (e.hasMoreElements())while (e.hasMoreElements()){{
Order each (Order) e.nextElement();Order each (Order) e.nextElement();outstanding += each.getAmount();outstanding += each.getAmount();
}}
printDetails(outstanding);printDetails(outstanding);}}
Extract Method (cont…)Extract Method (cont…)void printOwing()void printOwing(){{
printBanner();printBanner();double outstanding = getOutstanding();double outstanding = getOutstanding();printDetails(outstanding);printDetails(outstanding);
}}
void getOutstanding()void getOutstanding(){{
Enumeration e = _order.elements();Enumeration e = _order.elements();double result = 0.0;double result = 0.0;while (e.hasMoreElements())while (e.hasMoreElements()){{
Order each (Order) e.nextElement();Order each (Order) e.nextElement();result += each.getAmount();result += each.getAmount();
}}return result;return result;
}}
SummarySummary
Most code should be human-readable Most code should be human-readable first, machine readable second.first, machine readable second.
Refactoring improves code Refactoring improves code comprehension, thus making maintenance comprehension, thus making maintenance easier.easier.
Although identifying what to refactor is an Although identifying what to refactor is an art, the process of refactoring is very art, the process of refactoring is very algorithmic.algorithmic.
ALWAYS, ALWAYS TEST YOUR CODE ALWAYS, ALWAYS TEST YOUR CODE BEFORE AND AFTER YOU REFACTOR!BEFORE AND AFTER YOU REFACTOR!