Refactoring and its role in TestDriven Development Miguel

  • Slides: 49
Download presentation
Refactoring and its role in Test-Driven Development Miguel J. T. Pessoa Monteiro Escola Superior

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

Overview n n n n Characterisation of Refactoring Brief History of Refactoring Examples of

Overview n n n n 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 2

Refactoring Tenet of Refactoring n Program source code is a mechanism of communication between

Refactoring Tenet of Refactoring n Program source code is a mechanism of communication between humans, not between the programmer and the computer. 3

Intentionality is Important public void add(Object element) { if(!read. Only) { int new. Size

Intentionality is Important public void add(Object element) { if(!read. Only) { int new. Size = size + 1; if(new. Size > elements. length) { Object[] new. Elements = new Object[elemnts. length + 10]; for(int i=0; i<size; i++) new. Elements[i] = elements[i]; elements = new. Elements; } elements[size++] = element; } } public void add(Object element) { if(read. Only) return; if(at. Capacity()) grow(); add. Element(element); } 4

Characterising Refactoring Martin Fowler: n “a disciplined technique for restructuring an existing body of

Characterising Refactoring Martin Fowler: n “a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behaviour. ” 5

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

Characterising Refactoring Martin Fowler: n “Each transformation does little, n but a sequence of transformations can produce a significant restructuring. n Since each refactoring is small, it's less likely to go wrong”. 6

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

The “Two Hat” Metaphor n Programmer always wearing one of 2 hats: n n n 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. 7

What is not Refactoring n n n Adding new functionality is not refactoring Optimisation

What is not Refactoring n n n Adding new functionality is not refactoring Optimisation is not refactoring Changing code that does not compile is not refactoring (what would be the behaviour? ) 8

Overview n n n n Characterisation of Refactoring Brief History of Refactoring Examples of

Overview n n n n 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 9

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

Brief History of Refactoring n n n Griswold W. , Program restructuring as an aid to software maintenance. Ph. D 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. 10

Brief History of Refactoring n Advent of unit tests (e. g. x. Unit) n

Brief History of Refactoring n Advent of unit tests (e. g. x. Unit) n n Advent of Extreme Programming (XP) n n Made manual refactoring possible. Test-driven development: Unit testing, Refactoring, Pair programming, etc. Martin Fowler’s book n Promoted refactoring to buzzword status 11

Overview n n n n Characterisation of Refactoring Brief History of Refactoring Examples of

Overview n n n n 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 12

Reverse Conditional You have a conditional that would be easier to understand if you

Reverse Conditional You 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 ( !is. Summer( date ) ) charge = winter. Charge( quantity ); else charge = summer. Charge( quantity ); if ( is. Summer( date ) ) charge = summer. Charge( quantity ); else charge = winter. Charge( quantity ); 13

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

Rename Method The name of a method does not reveal its purpose. Change the name of the method. 14

Move Method A method is, or will be, (using or) used by more features

Move Method A 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. 15

Pull Up Method You have methods with identical results on subclasses. Move them to

Pull Up Method You have methods with identical results on subclasses. Move them to the superclass. 16

Extract Method You have a code fragment that can be grouped together. Turn the

Extract Method You have a code fragment that can be grouped together. Turn the fragment into a method whose name explains the purpose of the method. void print. Owing() { print. Banner(); //print details System. out. println ("name: " + _name); System. out. println ("amount " + get. Outstanding()); } void print. Owing() { print. Banner(); print. Details(get. Outstanding()); } void print. Details (double outstanding) { System. out. println ("name: " + _name); System. out. println ("amount " + outstanding); } 17

Extract Method You have a code fragment that can be grouped together. Turn the

Extract Method You have a code fragment that can be grouped together. Turn the fragment into a method whose name explains the purpose of the method. void print. Owing() { print. Banner(); //print details System. out. println ("name: " + _name); System. out. println ("amount " + get. Outstanding()); } void print. Owing() { print. Banner(); print. Details(get. Outstanding()); } void print. Details (double outstanding) { System. out. println ("name: " + _name); System. out. println ("amount " + outstanding); } 18

Inline Method A method's body is just as clear as its name. Put the

Inline Method A 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 get. Rating() { return (more. Than. Five. Late. Deliveries()) ? 2 : 1; } boolean more. Than. Five. Late. Deliveries() { return _number. Of. Late. Deliveries > 5; } int get. Rating() { return (_number. Of. Late. Deliveries > 5) ? 2 : 1; } 19

Inline Method Opposite to Extract Method A method's body is just as clear as

Inline Method Opposite to Extract Method A 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 get. Rating() { return (more. Than. Five. Late. Deliveries()) ? 2 : 1; } boolean more. Than. Five. Late. Deliveries() { return _number. Of. Late. Deliveries > 5; } int get. Rating() { return (_number. Of. Late. Deliveries > 5) ? 2 : 1; } 20

Replace Conditional with Polymorphism You have a conditional that chooses different behavior depending on

Replace Conditional with Polymorphism You 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 get. Speed() { switch (_type) { case EUROPEAN: return get. Base. Speed(); case AFRICAN: return get. Base. Speed() - get. Load. Factor() * _number. Of. Coconuts; case NORWEIGIAN_BLUE: return (_is. Nailed) ? 0 : get. Base. Speed(_voltage); } throw new Runtime. Exception ("Should be unreachable"); } 21

Replace Conditional with Polymorphism You have a conditional that chooses different behavior depending on

Replace Conditional with Polymorphism You 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. 22

Overview • • Characterisation of Refactoring Brief History of Refactoring Examples of refactoring steps

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 23

How Refactorings are Performed Either manually or automatically. n When done manually, it is

How Refactorings are Performed Either manually or automatically. n When done manually, it is always done in small steps (called refactorings). n Larger refactorings are sequences of smaller ones n 24

Manual Refactoring n Manual refactoring steps should always be small, because: n n They

Manual Refactoring n Manual refactoring steps should always be small, because: n n They are safer this way, because the steps are simpler It is easier to backtrack Pay attention to the mechanics: n Mechanics should stress safety 25

How Refactorings are Performed n n n When automatic support is available, it should

How Refactorings are Performed n n n When automatic support is available, it should be preferred, but. . . only if the tool is really safe. Example: Rename Method n n n Does it check for another method with the same name? Does it account for overloading? Does it account for overriding? 26

Overview n n n n Characterisation of Refactoring Brief History of Refactoring Examples of

Overview n n n n 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 27

When to Refactor We should refactor when the code stinks. “If it stinks, change

When to Refactor We should refactor when the code stinks. “If it stinks, change it. ” Grandma Beck, discussing child-rearing philosophy 28

Refactoring and code smells Refactorings remove Bad Smells in the Code i. e. ,

Refactoring and code smells Refactorings remove Bad Smells in the Code i. e. , potential problems or flaws n Some will be strong, some will be subtler n Some smells are obvious, some aren’t n Some smells mask other problems n Some smells go away unexpectedly when we fix something else 29

Refactoring and code smells Examples of code smells: n Duplicated Code, Large Class, Lazy

Refactoring and code smells Examples of code smells: n Duplicated Code, Large Class, Lazy Class, Long Method, Long Parameter List, Primitive Obsession, Speculative Generality, Temporary Field, Inappropriate Intimacy, Data Class, Refused Bequest, Comments, . . . n Frequent cause: the paradigm shift problem 30

Refactoring and code smells Code smells motivate use of refactorings to remove them, e.

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, . . . 31

Overview n n n n Characterisation of Refactoring Brief History of Refactoring Examples of

Overview n n n n 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 32

Unit Tests n Essential prerequisite for refactoring: Solid tests (i. e. good unit test

Unit Tests n Essential prerequisite for refactoring: Solid tests (i. e. good unit test coverage) n n n 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 33

Unit Tests Essential characteristic of unit tests: n They must be automatic n n

Unit Tests Essential characteristic of unit tests: n They must be automatic n n n 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) n They must be fast 34

Unit Tests A test is not an unit test if: n It talks to

Unit Tests A test is not an unit test if: n It talks to a database n It communicates across a network n It touches the file system Such tests are good, but not fast enough to run in a suite of thousands of tests 35

Ciclo RED-GREEN-REFACTOR Escrever um teste Refabricar o código (e testar) Correr os testes e

Ciclo RED-GREEN-REFACTOR Escrever um teste Refabricar o código (e testar) Correr os testes e ver a barra verde Escrever novo código Compilar Corrigir os erros do compilador Correr os testes e ver a barra vermelha 36

Escrever um teste Refabricar o código (e testar) Correr os testes e ver a

Escrever um teste Refabricar o código (e testar) Correr os testes e ver a barra verde Escrever novo código Fase RED Compilar Corrigir os erros do compilador Correr os testes e ver a barra vermelha 37

Escrever um teste Refabricar o código (e testar) Correr os testes e ver a

Escrever um teste Refabricar o código (e testar) Correr os testes e ver a barra verde Escrever novo código Fase RED Compilar Corrigir os erros do compilador Correr os testes e ver a barra vermelha Fase GREEN 38

Fase REFACTOR Escrever um teste Refabricar o código (e testar) Correr os testes e

Fase REFACTOR Escrever um teste Refabricar o código (e testar) Correr os testes e ver a barra verde Escrever novo código Fase RED Compilar Corrigir os erros do compilador Correr os testes e ver a barra vermelha Fase GREEN 39

Overview n n n n Characterisation of Refactoring Brief History of Refactoring Examples of

Overview n n n n 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 40

Resources – TDD & refactoring n n Refactoring home page www. refactoring. com/ Refactoring

Resources – TDD & refactoring n n Refactoring home page www. refactoring. com/ Refactoring mailing list at Yahoo groups. yahoo. com/group/refactoring/ 41

Resources – TDD & refactoring test-driven development: A Practical Guide Dave Astels Prentice-Hall/Pearson Education,

Resources – TDD & refactoring test-driven development: A Practical Guide Dave Astels Prentice-Hall/Pearson Education, 2003 ISBN 0 -13 -101649 -0 ______________ Test-Driven Development: By Example Kent Beck Addison-Wesley, 2003 ISBN 0 -321 -14653 -0 42

Resources – TDD & refactoring Refactoring: Improving the Design of Existing Code Martin Fowler

Resources – TDD & refactoring Refactoring: Improving the Design of Existing Code Martin Fowler Addison-Wesley, 1999 ISBN 0 -201 -48567 -2 43

Resources – TDD & refactoring Refactoring Workbook William Wake Addison-Wesley, 2003 ISBN 0 -32

Resources – TDD & refactoring Refactoring Workbook William Wake Addison-Wesley, 2003 ISBN 0 -32 -110929 -5 44

Resources – TDD & refactoring Refactoring to Patterns Joshua Kerievsky Addison-Wesley, 2004 ISBN 0

Resources – TDD & refactoring Refactoring to Patterns Joshua Kerievsky Addison-Wesley, 2004 ISBN 0 -321 -21335 -1 45

Resources – TDD & refactoring JUnit Recipes – Practical Methods for Programmer Testing J.

Resources – TDD & refactoring JUnit Recipes – Practical Methods for Programmer Testing J. B. Rainsberger Manning 2005 ISBN 1932394230 46

Resources – TDD & refactoring Working Effectively with Legacy Code Michael Feathers Addison-Wesley, 2005

Resources – TDD & refactoring Working Effectively with Legacy Code Michael Feathers Addison-Wesley, 2005 ISBN 0 -13 -117705 -2 47

Resources – TDD & refactoring Agile Java - Crafting Code with Test-Driven Development Jeff

Resources – TDD & refactoring Agile Java - Crafting Code with Test-Driven Development Jeff Langr Prentice Hall 2005 ISBN 0 -13 -148239 -4 48

Refactoring and its role in Test-Driven Development Questions? Miguel J. T. Pessoa Monteiro Escola

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