33
Refactoring

Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

Embed Size (px)

Citation preview

Page 1: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

Refactoring

Page 2: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

What 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

Page 3: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

What 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]

Page 4: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

What 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

Page 5: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

Something 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

Page 6: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

Metaphor: 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 Kerievsky’s Refactoring to Patterns

Page 7: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

What 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. You’ll do less mistakes and it’s easier to keep your head around things that way.

Page 8: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

• What happens if you don’t refactor?

you incur Design Debt

• Design Debt refers to the unwanted consequences of letting sloppy design and programming exist in the codebase – it’s the software design equivalent for Technical Debt

Workarounds instead of “form fit” additions

• Over-engineering is Design Debt as well!

[Cunningham]

Design Debt

Page 9: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

Design Income?

If there’s Design Debt, then is there equivalent “Design Income” in the other end of the scale?

• Up-front design could be considered Design Income. However, there’s 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

Page 10: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

Refactoring 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]

Page 11: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

Preventing Regression

• Unit tests– A good enough coverage lets us refactor with

confidence that nothing was broken.– Automated tests get run. Manual tests don’t.

• Functional tests– For the random situations where unit tests aren’t

sufficient for preventing regression– Automated tests get run. Manual tests don’t.

• Side-track: Test-Driven Development

Page 12: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

Rewriting 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 team’s performance

Page 13: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

Metaphor: John Thompson(from Refactoring to Patterns)

John Thompson, hatter, makesand sells hats for ready money.

Page 14: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

Metaphor: John Thompson (cont’d)

John Thompson

Page 15: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

Next Up…

… a bunch of sample refactorings in Java

Page 16: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

RefactoringsRename Method

• Mechanics:

1. 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.

2. 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.

3. Compile.

4. Change the body of the old method so that it calls the new one.

5. Compile and test.

6. Find all references to the old method and change them to call the new one instead. Compile and test after each change.

7. Remove the old method.

8. Compile and test.

Page 17: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

Exercise 1-4-1:Rename Method

• Task:– Rename the setAmount(float) method in

example.Money to setValue(float) without using Eclipse’s refactoring wizard, relying on the steps described in exercise-1.4-1.txt

Page 18: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

RefactoringsRename Method (cont’d)

• 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 IDE’s such as Eclipse.

Page 19: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

RefactoringsPull Up Method

• A slightly more complex refactoring involving inheritance• Mechanics:

– Inspect the methods to ensure they are identical (yes, identical – if they aren’t, 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.

Page 20: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

Exercise 1-4-2:Pull Up Field & Pull Up Method

• Task:– Pull Up Field ‘name’ without using Eclipse’s

refactoring wizard, relying on the steps described in exercise-1.4-2.txt

– Pull Up Method ‘getName()’ without using Eclipse’s refactoring wizard, relying on the steps described in exercise-1.4-2.txt

Page 21: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

RefactoringsPull Up Method (cont’d)

• Observations– Uses other, lower-level refactorings to

accomplish a slightly bigger refactoring

– Clearly more complex, but still feasible to automate

Page 22: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

RefactoringsIntroduce 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.

if (customer == null) { plan = BillingPlan.basic();} else { plan = customer.getPlan();}

Page 23: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

Exercise 1-4-3:Introduce 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

Page 24: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

RefactoringsIntroduce Null Object (cont’d)

• Observations– Transformation towards a design pattern

– Seems difficult to automate

– Has the potential of cleaning up significant amounts of error-prone, distracting code

Page 25: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

RefactoringsReplace Inheritance with Delegation

• This doesn’t 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.

Page 26: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

Exercise 1-4-4:Replace Inheritance with Delegation

• Task:– Replace Inheritance with Delegation in the

CollectionOfItems class, relying on the steps described in exercise-1.4-4.txt

Page 27: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

RefactoringsReplace Inheritance with Delegation (cont’d)

• Observations– A relatively simple refactoring, clearly less

complex than Introduce Null Object……so what’s the big deal?

Page 28: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

RefactoringsReplace 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.

Page 29: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

Exercise 1-4-5:Replace Delegation with Inheritance

• Task:– Replace Delegation with Inheritance in the

CollectionOfItems class, relying on the steps described in exercise-1.4-5.txt

Page 30: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

RefactoringsReplace Delegation with Inheritance

• Observations– Exact reverse of Replace Inheritance with

Delegation• Refactorings are often like this – a nice side-effect of

being well-defined…

Page 31: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

RefactoringsReplace Type Code …

…with Subclasses

…with Strategy

There’s no one-to-one mapping between code smells and solutions. Sometimes multiple refactorings provide slightly varying ways to climb out of the same hole…

Page 32: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

My 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 IDE’s.

Page 33: Refactoring. What is Refactoring? “ Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure

Tool 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)