Title: Refactoring
1Refactoring
2What is Refactoring?
- Refactoring is a disciplined technique for
restructuring an existing body of code, altering
its internal structure without changing its
external behavior. - Its heart is a series of small behavior
preserving trans-formations. Each transformation
(called a 'refactoring') does little, but a
sequence of transformations can produce a
significant restructuring. Since each refactoring
is small, it's less likely to go wrong. The
system is also kept fully working after each
small refactoring, reducing the chances that a
system can get seriously broken during the
restructuring. - http//refactoring.com
3What Motivates Us to Refactor?
- Make it easier to add new code
- Improve the design of existing code
- Gain a better understanding of code
- Make coding less annoying
- Kerievsky
4What Alerts Us to Refactor?
- Code Smells
- Signs that there might be something ugly in the
design waiting to be refactored away - Examples
- Long Method
- Long Parameter List
- Duplicate Code
- Large Class
- Comments
- Feature Envy
- Middle Man
- Message Chains
- Shotgun Surgery
5Something to think about
- The longer you wait before paying your debt, the
bigger the bill common sense - The bigger the mess, the less you want to clean
it up Joshua Kerievsky - Perfection is reached not when there remains
nothing to add, but when there remains nothing to
remove Antoine de Saint-Exupéry, 1900-1944
6Metaphor Clean As You Go
- Mrs. Beeton The Book of Household Management
CLEAN AS YOU GO
Quoted by Kevlin Henney and James Newkirk at
JAOO 2004,featured in Joshua Kerievskys
Refactoring to Patterns
7What is mercilessly?
- The bigger the mess, the less you want to clean
it up Joshua Kerievsky - Continuously.
- Refactor as often as you possibly can
- If you decide to leave a particular refactoring
for later, know the cost of doing so! - Before or after. Not during.
- Keep focused. Youll do less mistakes and its
easier to keep your head around things that way.
8Design Debt
- What happens if you dont refactor?? you incur
Design Debt - Design Debt refers to the unwanted consequences
of letting sloppy design and programming exist in
the codebase its the software design
equivalent for Technical Debt? Workarounds
instead of form fit additions - Over-engineering is Design Debt as well!
- Cunningham
9Design Income?
- If theres Design Debt, then is there equivalent
Design Income in the other end of the scale? - Up-front design could be considered Design
Income. However, theres a big risk of the
potential Design Income becoming Design Debt
because of over-engineering and wrongful
assumptions.? Due to this risk, up-front design
should only be done for sure things. Then
again, sure things are rarely big winners,
so ? Up-front design is often a bad investment
10Refactoring and Design Patterns
- Design Patterns are closely related to
Refactoring - Refactorings are transformations from one state
to another - These states are often Design Patterns!
- Alexander, GoF, Hillside
11Preventing Regression
- Unit tests
- A good enough coverage lets us refactor with
confidence that nothing was broken. - Automated tests get run. Manual tests dont.
- Functional tests
- For the random situations where unit tests arent
sufficient for preventing regression - Automated tests get run. Manual tests dont.
- Side-track Test-Driven Development
12Rewriting vs. Refactoring
- Rewriting ! Refactoring
- The word refactoring is often used in the
context of a plain rewrite of existing code,
which is most often a blatant mistake - however
- Refactoring Rewriting
- Some refactorings can be thought of as controlled
rewrites in well-defined, small steps - and sometimes
- Refactoring Deleting
- Deleting code can boost a teams performance
13Metaphor John Thompson(from Refactoring to
Patterns)
John Thompson, hatter, makes and sells hats for
ready money.
14Metaphor John Thompson (contd)
John Thompson
15Next Up
- a bunch of sample refactorings in Java
16RefactoringsRename Method
- Mechanics
- Check to see whether the method signature is
implemented by a super class or a subclass. If it
is, these steps must be performed for each
implementation. - Declare a new method with the new name. Copy the
old body of code over to the new name and make
any alterations to fit. - Compile.
- Change the body of the old method so that it
calls the new one. - Compile and test.
- Find all references to the old method and change
them to call the new one instead. Compile and
test after each change. - Remove the old method.
- Compile and test.
17Exercise 1-4-1Rename Method
- Task
- Rename the setAmount(float) method in
example.Money to setValue(float) without using
Eclipses refactoring wizard, relying on the
steps described in exercise-1.4-1.txt
18RefactoringsRename Method (contd)
- Observations
- Lot of work for a small refactoring, and
- Very mechanical work, but also
- Easy to automate
- which leads to this particular refactoring (and
many others, of course) being well-supported by
modern IDEs such as Eclipse.
19RefactoringsPull Up Method
- A slightly more complex refactoring involving
inheritance - Mechanics
- Inspect the methods to ensure they are identical
(yes, identical if they arent, use Substitute
Algorithm to make them identical) - If the methods have different signatures, change
the signatures to the one you want to use
eventually in the super class - Create a new method in the super class, copy the
body of one of the methods to it, adjust, and
compile. (you might need to Pull Up Field, first) - Delete one subclass method.
- Compile and test.
- Keep deleting subclass methods one at a time,
testing until only the super class method
remains. - Check if you can change any callers to refer to
the super type instead.
20Exercise 1-4-2Pull Up Field Pull Up Method
- Task
- Pull Up Field name without using Eclipses
refactoring wizard, relying on the steps
described in exercise-1.4-2.txt - Pull Up Method getName() without using
Eclipses refactoring wizard, relying on the
steps described in exercise-1.4-2.txt
21RefactoringsPull Up Method (contd)
- Observations
- Uses other, lower-level refactorings to
accomplish a slightly bigger refactoring - Clearly more complex, but still feasible to
automate
22RefactoringsIntroduce Null Object
- Again, a slightly more complex refactoring.
- Mechanics
- Create a subclass of the source class to act as a
NullObject. - Create an isNull() method on the source class and
the null class for the source class the method
should return false, for the null class it should
return true. - Compile.
- Find all places that can return a null when asked
for a source object. Replace them to give out an
instance of the null class instead. Compile and
test after each change. - Find all places that compare a variable of the
source type with null and replace them with a
call to isNull(). Compile and test after each
change. - Look for cases in which client code invokes a
method if not null and do some alternative
behavior if null. For each of these cases
override the method in question in the null class
with the alternative behavior originally
implemented in client code. Remove the condition
check for those that use the overridden behavior. - Compile and test.
23Exercise 1-4-3Introduce Null Object
- Task
- Introduce a Null Object to replace the null-check
in the PricingMachine class, relying on the steps
described in exercise-1.4-3.txt
24RefactoringsIntroduce Null Object (contd)
- Observations
- Transformation towards a design pattern
- Seems difficult to automate
- Has the potential of cleaning up significant
amounts of error-prone, distracting code
25RefactoringsReplace Inheritance with Delegation
- This doesnt look too difficult, does it?
- Mechanics
- Create a field in the subclass that refers to an
instance of the super class. Initialize the field
to this. - Change each method defined in the subclass to use
the delegate field. Compile and test after
changing each method. - Remove the subclass declaration and replace the
delegate assignment with an assignment to a new
object of the ex-super class type. - For each super class method, add a simple
delegating method to the ex-subclass. - Compile and test.
26Exercise 1-4-4Replace Inheritance with
Delegation
- Task
- Replace Inheritance with Delegation in the
CollectionOfItems class, relying on the steps
described in exercise-1.4-4.txt
27RefactoringsReplace Inheritance with Delegation
(contd)
- Observations
- A relatively simple refactoring, clearly less
complex than Introduce Null Objectso whats
the big deal?
28RefactoringsReplace Delegation with Inheritance
- This is exactly the reverse of Replace
Inheritance with Delegation! - Mechanics
- Make the delegating object a subclass of the
delegate. - Compile. Use Rename Method to fix any name
clashes between the two classes methods. - Set the delegate field to be the object itself.
- Remove the simple delegation methods.
- Compile and test.
- Replace all other delegations with calls to the
object itself. - Remove the delegate field.
29Exercise 1-4-5Replace Delegation with
Inheritance
- Task
- Replace Delegation with Inheritance in the
CollectionOfItems class, relying on the steps
described in exercise-1.4-5.txt
30RefactoringsReplace Delegation with Inheritance
- Observations
- Exact reverse of Replace Inheritance with
Delegation - Refactorings are often like this a nice
side-effect of being well-defined
31RefactoringsReplace Type Code
with Subclasses
with Strategy
Theres no one-to-one mapping between code smells
and solutions. Sometimes multiple refactorings
provide slightly varying ways to climb out of the
same hole
32My Favorite Refactorings
- There are some refactorings that one uses more
than others. For me, the following are probably
the ones I use the most - Rename Method
- Extract Method
- Move Method
- Rename Class
- Extract Class
- Inline Temp
- Extract Constant
- Low-level refactorings thus encountered more
often than e.g. Introduce Null Object and thus
better supported by IDEs.
33Tool Support
- JAVA
- Eclipse
- IntelliJ IDEA
- Borland JBuilder
- NetBeans
- RefactorIT plug-in for Eclipse, Borland JBuilder,
NetBeans, Oracle JDeveloper - .NET
- IntelliJ Resharper for Visual Studio .NET
- Visual Studio .NET Team Studio 2005 (Forthcoming)