Refactoringand its role in
Test-Driven Development
Miguel J. T. Pessoa Monteiro
Escola Superior de Tecnologiade Castelo Branco
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
3
Refactoring
Tenet of Refactoring Program source code
is a mechanism of communication between humans, not between the programmer and the computer.
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
5
Characterising Refactoring
Martin Fowler: “a disciplined technique for
restructuring an existing body of code, altering its internal structure without changing its external behaviour.”
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”.
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.
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?)
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
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.
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
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
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 );
14
Rename MethodThe name of a method does not reveal its purpose.Change the name of the method.
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.
16
Pull Up MethodYou have methods with identical results on subclasses.
Move them to the superclass.
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);
}
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);
}
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;
}
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
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");}
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.
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
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
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
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?
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
28
When to Refactor
We should refactor when the code stinks.
“If it stinks, change it.”Grandma Beck,discussing child-rearing philosophy
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
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
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,...
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
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
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
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
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)
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)
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)
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)
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
41
Resources – TDD & refactoring
Refactoring home pagewww.refactoring.com/
Refactoring mailing list at Yahoogroups.yahoo.com/group/refactoring/
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
43
Refactoring:Improving the Design of Existing CodeMartin FowlerAddison-Wesley, 1999ISBN 0-201-48567-2
Resources – TDD & refactoring
44
Refactoring Workbook
William WakeAddison-Wesley, 2003ISBN 0-32-110929-5
Resources – TDD & refactoring
45
Refactoring to PatternsJoshua KerievskyAddison-Wesley, 2004ISBN 0-321-21335-1
Resources – TDD & refactoring
46
JUnit Recipes –Practical Methods for Programmer Testing J.B. Rainsberger
Manning 2005
ISBN 1932394230
Resources – TDD & refactoring
47
Working Effectively with Legacy CodeMichael FeathersAddison-Wesley, 2005ISBN 0-13-117705-2
Resources – TDD & refactoring
48
Agile Java - Crafting Code with Test-Driven Development Jeff Langr
Prentice Hall 2005
ISBN 0-13-148239-4
Resources – TDD & refactoring
49
Refactoring and its role inTest-Driven Development
Questions?
Miguel J. T. Pessoa Monteiro
Escola Superior de Tecnologiade Castelo Branco