refactoring and its role in test-driven development

49
Refactoring and its role in Test-Driven Development Miguel J. T. Pessoa Monteiro Escola Superior de Tecnologia de Castelo Branco

Upload: lana-kane

Post on 03-Jan-2016

18 views

Category:

Documents


0 download

DESCRIPTION

Refactoring and its role in Test-Driven Development. Miguel J. T. Pessoa Monteiro Escola Superior de Tecnologia de Castelo Branco. Overview. Characterisation of Refactoring Brief History of Refactoring Examples of refactoring steps How refactorings are performed - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Refactoring and its role in Test-Driven Development

Refactoringand its role in

Test-Driven Development

Miguel J. T. Pessoa Monteiro

Escola Superior de Tecnologiade Castelo Branco

Page 2: Refactoring and its role in Test-Driven Development

2

Overview

Characterisation of Refactoring Brief History of Refactoring Examples of refactoring steps How refactorings are performed When to refactor (code smells) Role of unit tests in refactoring Resources

Page 3: Refactoring and its role in Test-Driven Development

3

Refactoring

Tenet of Refactoring Program source code

is a mechanism of communication between humans, not between the programmer and the computer.

Page 4: Refactoring and its role in Test-Driven Development

4

public void add(Object element) {if(!readOnly) {

int newSize = size + 1;if(newSize > elements.length) {

Object[] newElements = new Object[elemnts.length + 10];for(int i=0; i<size; i++)

newElements[i] = elements[i];elements = newElements;

}elements[size++] = element;

}}

public void add(Object element) {if(readOnly)

return;if(atCapacity())

grow();addElement(element);

}

Intentionality is Important

Page 5: Refactoring and its role in Test-Driven Development

5

Characterising Refactoring

Martin Fowler: “a disciplined technique for

restructuring an existing body of code, altering its internal structure without changing its external behaviour.”

Page 6: Refactoring and its role in Test-Driven Development

6

Characterising Refactoring

Martin Fowler: “Each transformation does little, but a sequence of

transformations can produce a significant restructuring.

Since each refactoring is small, it's less likely to go wrong”.

Page 7: Refactoring and its role in Test-Driven Development

7

The “Two Hat” Metaphor Programmer always wearing one of 2

hats: The developer hat The refactoring hat

If the task can be made easier if the code is structured differently,

Programmer swaps hats and refactors for a while.

Then he swaps hats again, and adds the functionality.

Page 8: Refactoring and its role in Test-Driven Development

8

What is not Refactoring

Adding new functionalityis not refactoring

Optimisation is not refactoring Changing code that does not

compileis not refactoring(what would be the behaviour?)

Page 9: Refactoring and its role in Test-Driven Development

9

Overview

Characterisation of Refactoring Brief History of Refactoring Examples of refactoring steps How refactorings are performed When to refactor (code smells) Role of unit tests in refactoring Resources

Page 10: Refactoring and its role in Test-Driven Development

10

Brief History of Refactoring Griswold W., Program restructuring as an

aid to software maintenance. PhD thesis, University of Washington, USA, 1991.

Opdyke W., Refactoring Object-Oriented Frameworks, Ph.D. Thesis, University of Illinois at Urbana-Champaign, USA, 1992.

Roberts D., Brant J., Johnson R., A refactoring tool for smalltalk. Theory and Practice of Object Systems 3(4), pp. 253–263, 1997.

Page 11: Refactoring and its role in Test-Driven Development

11

Brief History of Refactoring

Advent of unit tests (e.g. xUnit) Made manual refactoring possible.

Advent of Extreme Programming (XP) Test-driven development: Unit testing,

Refactoring, Pair programming, etc. Martin Fowler’s book

Promoted refactoring to buzzword status

Page 12: Refactoring and its role in Test-Driven Development

12

Overview

Characterisation of Refactoring Brief History of Refactoring Examples of refactoring steps How refactorings are performed When to refactor (code smells) Role of unit tests in refactoring Resources

Page 13: Refactoring and its role in Test-Driven Development

13

Reverse ConditionalYou have a conditional that would be easier to understand if you reversed its sense.

Reverse the sense of the conditional and reorder the conditional's clauses.

if ( !isSummer( date ) ) charge = winterCharge( quantity );else charge = summerCharge( quantity );

            

if ( isSummer( date ) ) charge = summerCharge( quantity );else charge = winterCharge( quantity );

Page 14: Refactoring and its role in Test-Driven Development

14

Rename MethodThe name of a method does not reveal its purpose.Change the name of the method.

Page 15: Refactoring and its role in Test-Driven Development

15

Move MethodA method is, or will be, (using or) used by more features of another class than the class on which it is defined.

Create a new method with a similar body in the class it uses most. Either turn the old method into a simple delegation, or remove it altogether.

Page 16: Refactoring and its role in Test-Driven Development

16

Pull Up MethodYou have methods with identical results on subclasses.

Move them to the superclass.

Page 17: Refactoring and its role in Test-Driven Development

17

Extract MethodYou have a code fragment that can be grouped together.

Turn the fragment into a method whose name explains the purpose of the method.

void printOwing() {printBanner();

//print detailsSystem.out.println ("name: " + _name);System.out.println ("amount " + getOutstanding());

}             

void printOwing() {printBanner();printDetails(getOutstanding());

}void printDetails (double outstanding) {

System.out.println ("name: " + _name);System.out.println ("amount " + outstanding);

}

Page 18: Refactoring and its role in Test-Driven Development

18

Extract MethodYou have a code fragment that can be grouped together.

Turn the fragment into a method whose name explains the purpose of the method.

void printOwing() {printBanner();

//print detailsSystem.out.println ("name: " + _name);System.out.println ("amount " + getOutstanding());

}             

void printOwing() {printBanner();printDetails(getOutstanding());

}void printDetails (double outstanding) {

System.out.println ("name: " + _name);System.out.println ("amount " + outstanding);

}

Page 19: Refactoring and its role in Test-Driven Development

19

Inline MethodA method's body is just as clear as its name.

Put the method's body into the body of its callers and remove the method.

int getRating() {return (moreThanFiveLateDeliveries()) ? 2 : 1;

}boolean moreThanFiveLateDeliveries() {

return _numberOfLateDeliveries > 5;}

int getRating() {return (_numberOfLateDeliveries > 5) ? 2 : 1;

}

Page 20: Refactoring and its role in Test-Driven Development

20

Inline MethodA method's body is just as clear as its name.

Put the method's body into the body of its callers and remove the method.

int getRating() {return (moreThanFiveLateDeliveries()) ? 2 : 1;

}boolean moreThanFiveLateDeliveries() {

return _numberOfLateDeliveries > 5;}

int getRating() {return (_numberOfLateDeliveries > 5) ? 2 : 1;

}

Opposite to Extract Method

Page 21: Refactoring and its role in Test-Driven Development

21

Replace Conditional with PolymorphismYou have a conditional that chooses different behavior depending on the type of an object.Move each leg of the conditional to an overriding method in a subclass. Make the original method abstract.

double getSpeed() { switch (_type) { case EUROPEAN: return getBaseSpeed(); case AFRICAN: return getBaseSpeed() - getLoadFactor() * _numberOfCoconuts; case NORWEIGIAN_BLUE: return (_isNailed) ? 0 : getBaseSpeed(_voltage); } throw new RuntimeException ("Should be unreachable");}

Page 22: Refactoring and its role in Test-Driven Development

22

Replace Conditional with PolymorphismYou have a conditional that chooses different behavior depending on the type of an object.Move each leg of the conditional to an overriding method in a subclass. Make the original method abstract.

Page 23: Refactoring and its role in Test-Driven Development

23

Overview

• Characterisation of Refactoring

• Brief History of Refactoring

• Examples of refactoring steps

• How refactorings are performed

• When to refactor (code smells)

• Role of unit tests in refactoring

• Resources

Page 24: Refactoring and its role in Test-Driven Development

24

How Refactorings are Performed

Either manually or automatically.

When done manually, it is always done in small steps (called refactorings).

Larger refactorings are sequences of smaller ones

Page 25: Refactoring and its role in Test-Driven Development

25

Manual Refactoring

Manual refactoring steps should always be small, because: They are safer this way, because the

steps are simpler It is easier to backtrack

Pay attention to the mechanics: Mechanics should stress safety

Page 26: Refactoring and its role in Test-Driven Development

26

How Refactorings are Performed When automatic support is

available, it should be preferred, but ...

... only if the tool is really safe. Example: Rename Method

Does it check for another method with the same name?

Does it account for overloading? Does it account for overriding?

Page 27: Refactoring and its role in Test-Driven Development

27

Overview

Characterisation of Refactoring Brief History of Refactoring Examples of refactoring steps How refactorings are performed When to refactor (code smells) Role of unit tests in refactoring Resources

Page 28: Refactoring and its role in Test-Driven Development

28

When to Refactor

We should refactor when the code stinks.

“If it stinks, change it.”Grandma Beck,discussing child-rearing philosophy

Page 29: Refactoring and its role in Test-Driven Development

29

Refactoring and code smells

Refactorings remove Bad Smells in the Code i.e., potential problems or flaws

Some will be strong, some will be subtler

Some smells are obvious, some aren’t Some smells mask other problems Some smells go away unexpectedly

when we fix something else

Page 30: Refactoring and its role in Test-Driven Development

30

Refactoring and code smells

Examples of code smells: Duplicated Code, Large Class, Lazy

Class, Long Method, Long Parameter List, Primitive Obsession, Speculative Generality, Temporary Field, Inappropriate Intimacy, Data Class, Refused Bequest, Comments, ...

Frequent cause:the paradigm shift problem

Page 31: Refactoring and its role in Test-Driven Development

31

Refactoring and code smells

Code smells motivate use of refactorings to remove them, e.g.

Duplicated Code → Extract Method, Extract Class,

Form Template Method, ...

Long Method → Extract Method,Replace Temp with Query,Introduce Parameter

Object,Decompose Conditional,...

Page 32: Refactoring and its role in Test-Driven Development

32

Overview

Characterisation of Refactoring Brief History of Refactoring Examples of refactoring steps How refactorings are performed When to refactor (code smells) Role of unit tests in refactoring Resources

Page 33: Refactoring and its role in Test-Driven Development

33

Unit Tests

Essential prerequisite for refactoring:Solid tests (i.e. good unit test coverage) Tests warn programmers of problems if

they unknowningly break other parts of the application

Tests give an immediate/quick analysis of the effects of a change

Therefore tests give Courage

Page 34: Refactoring and its role in Test-Driven Development

34

Unit Tests

Essential characteristic of unit tests: They must be automatic

No need to see console outputs No need to specially prepare them to run

They should independent of each other They should run often They should make it easy to run often

(otherwise developers will stop running them) They must be fast

Page 35: Refactoring and its role in Test-Driven Development

35

Unit Tests

A test is not an unit test if: It talks to a database It communicates across a network It touches the file system

Such tests are good, but not fast enough to run in a suite of thousands of tests

Page 36: Refactoring and its role in Test-Driven Development

Ciclo RED-GREEN-REFACTOR

Escrever um teste

Compilar

Corrigir os erros do compilador

Correr os testes e ver

a barra vermelha

Escrever novo código

Correr os testes e ver

a barra verde

Refabricar o código

(e testar)

Page 37: Refactoring and its role in Test-Driven Development

Fase REDEscrever um teste

Compilar

Corrigir os erros do compilador

Correr os testes e ver

a barra vermelha

Escrever novo código

Correr os testes e ver

a barra verde

Refabricar o código

(e testar)

Page 38: Refactoring and its role in Test-Driven Development

Fase RED

Fase GREEN

Escrever um teste

Compilar

Corrigir os erros do compilador

Correr os testes e ver

a barra vermelha

Escrever novo código

Correr os testes e ver

a barra verde

Refabricar o código

(e testar)

Page 39: Refactoring and its role in Test-Driven Development

Fase RED

Fase GREEN

Fase REFACTOR

Escrever um teste

Compilar

Corrigir os erros do compilador

Correr os testes e ver

a barra vermelha

Escrever novo código

Correr os testes e ver

a barra verde

Refabricar o código

(e testar)

Page 40: Refactoring and its role in Test-Driven Development

40

Overview

Characterisation of Refactoring Brief History of Refactoring Examples of refactoring steps How refactorings are performed When to refactor (code smells) Role of unit tests in refactoring Resources

Page 41: Refactoring and its role in Test-Driven Development

41

Resources – TDD & refactoring

Refactoring home pagewww.refactoring.com/

Refactoring mailing list at Yahoogroups.yahoo.com/group/refactoring/

Page 42: Refactoring and its role in Test-Driven Development

42

test-driven development:A Practical GuideDave AstelsPrentice-Hall/Pearson Education, 2003ISBN 0-13-101649-0

___________________________Test-Driven Development:By Example Kent BeckAddison-Wesley, 2003ISBN 0-321-14653-0

Resources – TDD & refactoring

Page 43: Refactoring and its role in Test-Driven Development

43

Refactoring:Improving the Design of Existing CodeMartin FowlerAddison-Wesley, 1999ISBN 0-201-48567-2

Resources – TDD & refactoring

Page 44: Refactoring and its role in Test-Driven Development

44

Refactoring Workbook

William WakeAddison-Wesley, 2003ISBN 0-32-110929-5

Resources – TDD & refactoring

Page 45: Refactoring and its role in Test-Driven Development

45

Refactoring to PatternsJoshua KerievskyAddison-Wesley, 2004ISBN 0-321-21335-1

Resources – TDD & refactoring

Page 46: Refactoring and its role in Test-Driven Development

46

JUnit Recipes –Practical Methods for Programmer Testing J.B. Rainsberger

Manning 2005

ISBN 1932394230

Resources – TDD & refactoring

Page 47: Refactoring and its role in Test-Driven Development

47

Working Effectively with Legacy CodeMichael FeathersAddison-Wesley, 2005ISBN 0-13-117705-2

Resources – TDD & refactoring

Page 48: Refactoring and its role in Test-Driven Development

48

Agile Java - Crafting Code with Test-Driven Development Jeff Langr

Prentice Hall 2005

ISBN 0-13-148239-4

Resources – TDD & refactoring

Page 49: Refactoring and its role in Test-Driven Development

49

Refactoring and its role inTest-Driven Development

Questions?

Miguel J. T. Pessoa Monteiro

Escola Superior de Tecnologiade Castelo Branco