Refactoring Fest

38

Click here to load reader

description

Intent of this tutorial is to provide the participants with a hands-on-experience of real world refactoring by taking an open source project and refactoring it. Benefits After attending this session, the participants should be able to: Build a common vocabulary in the refactoring space Identify code smells Eliminate code smells by applying the simple refactoring techniques explained in Martin Fowler‘s “Refactoring” Write better unit/functional tests for legacy code Understand some of the techniques and pitfalls in refactoring legacy code in the absence of unit and functional tests [”Working effectively with legacy code “] Take existing code and refactor it to standard design patterns [Refactoring to patterns] Learn about the internals of the open source project chosen to refactor Know where to look to continue learning the techniques of refactoring

Transcript of Refactoring Fest

Page 2: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

Tutorial Schedule

What, Why, When and How... Refactor?

How to Refactor to Patterns

How to deal with Legacy Code?

Refactoring Hands-on session

2

Page 3: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

Three Golden Rules

Once and only once [DRY]

Express intent

Tell, don’t ask

3

Page 4: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

Definitions

Loose Usage

Reorganize a program (or something)

As a noun

a change made to the internal structure of some software to make it easier to understand and cheaper to modify, without changing the observable behavior of that software

As a verb

the activity of restructuring software by applying a series of refactorings without changing the observable behavior of that software.

4

Page 5: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

What is Refactoring?

A series of small steps, each of which changes the program’s

internal structure without changing its external behavior - Martin Fowler

Verify no change in external behavior by

Testing

Using the right tool - IDE

Formal code analysis by tool

Being very, very careful

5

Page 6: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

What if you hear...

We’ll just refactor the code to add logging support

Can you refactor the code so that it authenticates against LDAP instead of Database?

We have too much duplicate code, we need to refactor the code to eliminate duplication

This class is too big, we need to refactor it

Caching?

6

Page 7: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

Origin

Ward Cunningham and Kent Beck

Smalltalk style

Ralph Johnson at University of Illinois at Urbana-Champaign

Bill Opdyke’s Thesis

ftp://st.cs.uiuc.edu/pub/papers/refactoring/opdyke-thesis.ps.Z

John Brant and Don Roberts: The Refactoring Browser

7

Page 8: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

Why do we Refactor?

Helps us deliver more business value faster

Improves the design of our software

Combat’s “bit rot”

Easier to maintain and understand

Easier to facilitate change

More flexibility

Increased re-usability

8

Page 9: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

Why do we Refactor?...

Minimizes technical debt

Keep development at speed

To make the software easier to understand

Write for people, not the compiler

Understand unfamiliar code

To help find bugs

refactor while debugging to clarify the code

To “Fix broken windows” - Pragmatic Programmers

9

Page 10: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

ReadabilityWhich code segment is easier to read?

Sample 1

if (date.before(Summer_Start) || date.after(Summer_End)){ charge = quantity * winterRate + winterServiceCharge;else charge = quantity * summerRate;}

Sample 2

if (isSummer(date)) { charge = summerCharge(quantity);Else charge = winterCharge(quantity);}

10

Page 11: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

When should you refactor?

To add new functionality

refactor existing code until you understand it

refactor the design to make it simple to add

To find bugs

refactor to understand the code

For code reviews

immediate effect of code review

allows for higher level suggestions

Like championship snooker players we are setting ourselves up for

our next shot

11

Page 12: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

The Two Hats

Adding Function

Add new capabilities to the system

Adds new tests

Get the test working

Refactoring

Does not add any new featuresDoes not add tests (but may change some)Restructure the code to remove redundancy

Swap frequently between the hats, but only wear one at a time

12

Page 13: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

Refactoring and TDD

TDD Rhythm - Test, Code, Refactor

Add a Test

Run the Test

Make a little change

Run the Test

Refactor

Fail

Pass

Fail

Pass

13

Page 14: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

Team Techniques

Encourage refactoring culture

nobody gets things right first time

nobody can write clear code without reviews

refactoring is forward progress

14

Page 15: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

Team Techniques...

Provide sound testing base

tests are essential for refactoring

build system and run tests daily

Pair Programming

two programmers working together can be quicker than working separately

refactor with the class writer and a class user

15

Page 16: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

How do we Refactor?

We looks for Code-Smells

Things that we suspect are not quite right or will cause us severe pain if we do not fix

16

Page 17: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

Common Code Smells

The Big Stinkers

Duplicated code

Feature Envy

Inappropriate Intimacy

Comments

Long Method

Long Parameter List

Switch Statements

Improper Naming

17

Page 18: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

Duplicated Code

There is obvious duplication

Such as copy and paste

There are unobvious duplications

Such as parallel inheritance hierarchies.

Similar algorithms

Remedies

Extract Method

Pull Up Field

18

Page 19: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

Feature Envy

A method that seems more interested in some other class than the one it is in.

Remedies:

Move Method

Extract Method

19

Page 20: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

Extract Methodvoid printOwning(double amount){

printBanner();

// print detailsSystem.Console.WriteLine(string.Format(“name: “, name);System.Console.WriteLine(string.Format(“amount: “, amount);

}

void printOwning(double amount){printBanner();printDetails(amount);

}

void printDetails(double amount){System.Console.WriteLine(string.Format(“name: “, name);System.Console.WriteLine(string.Format(“amount: “, amount);

}

20

Page 21: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

Inappropriate Intimacy

Two or more classes fiddling with each other’s private parts.

Remedies

Move Method and Move Field

Change Bi-directional Association to Unidirectional

Extract Class

21

Page 22: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

Extract Class

PersonnameofficeAreaCodeofficeNumber

getTelephoneNumber

TelephoneNumber

areaCodenumber

getTelephoneNumber

Person

nametelephoneNumber

getTelephoneNumber

22

Page 23: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

Comments

Comments – be suspicious!

Comments are a deodorant.

Comments represent a failure to express an idea in the code.

Remedies:

Extract Method

Rename Method

Introduce Assertion

23

Page 24: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

Introduce Assertiondouble GetExpenseLimit() { // should have either expense limit or a primary project return(_expenseLimit != NULL_EXPENSE) ? _expenseLimit : _primaryProject.GetMemberExpenseLimit();}

double GetExpenseLimit() {assert(_expenseLimit != NULL_EXPENSE || _primaryProject != null, “Expense Limit and Primary Project must not be null”);

return(_expenseLimit != NULL_EXPENSE) ? _expenseLimit : _primaryProject.GetMemberExpenseLimit();}

24

Page 25: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

Long Method

Good OO code is easiest to understand and maintain with shorter methods with good names

Long methods tend to be harder to read and understand

Remedies:

Extract Method

Replace Temp with Query

Replace Method with Method Object.

Decompose Conditional

25

Page 26: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

Replace Temp with Query

double basePrice = _quanity * _itemPrice;

if(basePrice > 1000){

return basePrice * 0.95;}else{ return basePrice * 0.98; }

if(getBasePrice() > 1000) {return getBasePrice() * 0.95;

}else { return getBasePrice() * 0.98; }

double getBasePrice() { return _quanitiy * _itemPrice;}

26

Page 27: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

Long parameter list

Functions should have as few parameters as possible.

Remedies:

Replace Parameter with Method

Preserve Whole Object

Introduce Parameter Object

27

Page 28: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

Introduce Parameter Object

Customer

AmoutInvoicedIn(Date start, Date end)AmoutRecivedIn(Date start, Date end)AmoutOverdueIn(Date start, Date end)

Customer

AmoutInvoicedIn(DateRange range)AmoutRecivedIn(DateRange range)AmoutOverdueIn(DateRange range)

28

Page 29: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

Switch Statements

Type cases are evil because they tend to be duplicated many times.

Remedies:

Replace Type Code with Subclasses

Replace Type Code with State / Strategy

Replace Conditional with Polymorphism.

Replace Parameter with Explicit Methods

Introduce Null Object.

29

Page 30: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

Replace Parameter with Explicit Methods

void SetValue(String name, int value){

if(name.Equals(“height”)) {

_height = value; return;}if(name.Equals(“width”)){ _width = value; return;}Trace.Assert(false, “Should never reach here”);

}

void SetHeight(int value){

_height = value;}

void SetWidth(int value){

_width = value;}

30

Page 31: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

Inappropriate NamingNames given to variables (fields) and methods should be clear and meaningful.

A variable name should say exactly what it is.

Which is better?

private string s; OR private string salary;

A method should say exactly what it does.

Which is better?

public double calc (double s)

public double calculateFederalTaxes (double salary)

31

Page 32: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

Refactoring & Patterns

There is a natural relation between patterns and refactorings. Patterns are where you want to be; refactorings are ways to get there from somewhere else. - Martin Fowler

32

Page 33: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

Refactoring to Patterns

Creation – creation of objects

Simplification – code simplification

Generalization – code abstraction

Protection – improve protection of existing code

Accumulation – information accumulation code

Utilities – misc

33

Page 34: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

How to refactor Legacy Code?

Identify change points

Find an inflection point

Cover the inflection point

Break external dependencies

Break internal dependencies

Write tests

Make changes

Refactor the covered code.

34

Page 36: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

Refactoring Hands-on

We’ll use an open source project to apply refactoring lessons

Make sure your laptops are setup with the project

Form pairs and each pair picks up a module/package of the open source project.

36

Page 37: Refactoring Fest

Licensed Under Creative Commons by Naresh Jain

Refactoring Hands-on...

You will be introduced to 2-3 code smells at a time

Apply lessons form working with legacy code to write tests around your inflection point

Apply lessons from refactoring and refactoring to patterns to eradicate the code smells

Repeat last 3 steps, till we run out of time

37