lectures 17 and 18 a refactoring micro-example for0383 software quality assurance 5/16/20151dr andy...

36
Lectures 17 and 18 A Refactoring Micro- Example FOR0383 Software Quality Assurance 05/22/22 1 Dr Andy Brooks Refactoring is really easy using this tool.

Upload: camron-lambert

Post on 17-Dec-2015

246 views

Category:

Documents


12 download

TRANSCRIPT

Page 1: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

Lectures 17 and 18 A Refactoring Micro-Example

FOR0383 Software Quality Assurance

04/18/23 1Dr Andy Brooks

Refactoring is really easy using this tool.

Page 2: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 2

Case StudyDæmisaga

ReferenceA Refactoring Micro-Example, David Parsons,http://www.dparsons.co.uk/Refactoring.html

Page 3: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 3

What is refactoring?

• There is a dedicated website: www.refactoring.com

“Refactoring is the process of improving the design of existing code without changing its observable behaviour.”

“It is an ongoing process of continual cleanup.”Dave Parsons

Page 4: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 4

Replace smelly code• Signs of decay include:

– Duplicated code– Switch statements– Long methods– Large classes– Data classes (only getters and setters in the API)– Long parameter lists– Use of primitives rather than objects– Temporary variables and fields

When you write smelly code you are hacking...

Page 5: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 5

Test the changes

• Every refactoring change should be tested.

• Recompile and test after every change.

“If we want to refactor, the essential precondition is having solid tests.”

Martin Fowler

Page 6: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 6

Fowler´s ‘Rule of Three’

• The first time you write something you just do it.• The second time, you wince at the duplication.• The third time, you refactor.

‘Two hats rule’• Do not try to develop code at the same time as

you refactor code. Refactor while you wear your refactoring hat: do not develop.

RD

Page 7: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 7

The micro example• A method of some dice game class that throws a

couple of dice and returns a result. • ‘dice’ is an array of ‘Die’.

public int getScore(){

int result;result = (int)(Math.random() * 6) + 1;dice[0].setFaceValue(result);result = (int)(Math.random() * 6) + 1;dice[1].setFaceValue(result);int score = dice[0].getFaceValue() + dice[1].getFaceValue();return score;

}

0<=x<11<=x<7(int) truncates fraction

Page 8: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 8

Refactoring 1 – Self Encapsulate Field

• Use accessor methods, do not directly access an object´s fields within its methods.

public int getScore(){

int result;result = (int)(Math.random() * 6) + 1;getDice(0).setFaceValue(result);result = (int)(Math.random() * 6) + 1;getDice(1).setFaceValue(result);int score =getDice(0).getFaceValue()

+getDice(1).getFaceValue(); return score;

}

The underlying representation of a die can be changed.

Page 9: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 9

Refactoring 2 – Extract Method• Split up a longer method into smaller methods.public int getScore(){

int result;result = rollDie();getDice(0).setFaceValue(result);result = rollDie();getDice(1).setFaceValue(result);int score = getDice(0).getFaceValue() + getDice(1).getFaceValue();return score;

} public int rollDie(){

return (int)(Math.random() * 6) + 1;}

Page 10: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 10

Refactoring 3 – Rename class/method/field

• Change names to be more meaningful.

public int throwDice(){

int result;result = rollDie();getDice(0).setFaceValue(result);result = rollDie();getDice(1).setFaceValue(result);int score = getDice(0).getFaceValue() + getDice(1).getFaceValue();return score;

} public int rollDie(){

return (int)(Math.random() * 6) + 1;}

Page 11: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 11

Refactoring 4 – Replace Temp with Query• Use a query method instead of a temporary variable.

public int throwDice(){ int result;

result = rollDie();getDice(0).setFaceValue(result);result = rollDie();getDice(1).setFaceValue(result);return getDiceValue();}

 public int rollDie(){ return (int)(Math.random() * 6) + 1;} int getDiceValue(){ return getDice(0).getFaceValue() +

getDice(1).getFaceValue();}

Page 12: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 12

Refactoring 5 – Move Method• Dice objects are data objects.• It would be better to move the rollDie() method to

the Dice class and have this method set the state of the object.

• The rollDie() method can also be renamed to roll().

public void roll(){

setFaceValue((int)(Math.random() * 6) + 1);}

Page 13: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 13

Refactoring 5 – Move Methodpublic int throwDice(){

getDice(0).roll();getDice(1).roll();return getDiceValue();

} int getDiceValue(){

return getDice(0).getFaceValue() +getDice(1).getFaceValue();

}

The code is beginning to look much cleaner.

Page 14: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 14

Refactor 6 – Replace conditional with polymorphism

• Switch statements that depend on the type of an object should be replaced with class hierarchies and polymorphic methods.

• Suppose the Die class had code to model two kinds of dice: NORMAL or LOADED.

static final int NORMAL = 1;static final int LOADED = 2;private int type;

Page 15: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 15

Refactor 6 – Replace conditional with polymorphism

public void roll(){

switch(getType()){

case NORMAL:setFaceValue((int)(Math.random() * 6) + 1);break;

case LOADED:// random is a static java.util.Random object – easier// to fix a range of integers (2 – 6) than Math.randomsetFaceValue(random.nextInt(5) + 2);break;

default:setFaceValue(1);

}}

The roll() method now has a switch.

inclusive of 0exclusive of 5

Page 16: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 16

Refactor 6 – Replace conditional with polymorphism

Die

Normal Loaded

//Normal Die implementationpublic void roll(){

setFaceValue((int)(Math.random() * 6) + 1);} //Loaded Die implementationpublic void roll(){

setFaceValue(random.nextInt(5) + 2);}

abstract superclass

Page 17: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 17

Refactor 7 – Replace Magic Number with Symbolic Constant

public static final int MAX_RANDOM = 6;public static final int MIN_DICE_VALUE = 2;

public void roll(){ setFaceValue(random.nextInt(MAX_RANDOM - 1) + MIN_DICE_VALUE);}

6 rather than 5 because we want to express the maximum value of a die.

Page 18: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 18

Replace indexed access with iteration?

• The real question is: do we need indexed access if we just have two die objects?

• The answer is no. We will ‘never’ need to be able to use a different number of dice. The use of an array or collection provides too much functionality. We just need two named die objects:

public int throwDice() {

getDice(0).roll();getDice(1).roll();return getDiceValue();

}

indexed access

getFirstDie().roll();getSecondDie().roll();

Page 19: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 19

Replace polymorphism with parameterised algorithm

• Do we really need to use inheritance and have a polymorphic roll() method?

• No. We could make use of a parameterised method. If you have two algorithms that do something similar, consider if they can be combined into a single algorithm in a parameterised method.

int getRandomInt(int min, int max);

Page 20: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 20

Knowing that we will only ever have two die and recognising that a parameterised method can be used to model a normal and loaded die ... completely changes the look of the code...

Page 21: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 21

Reflections

• Were the refactorings carried out in the right order?

• Can refactorings be prioritised?

• Should refactoring first consider core architectural issues?

• Should we start with the simplest refactorings?

Page 22: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 22

Reflections

• Refactorings are often reversible. ‘Replace Inheritance with Delegation’ and ‘Replace Delegation with Inheritance’. We may do a refactoring only to undo it.

• A tool providing a direct link between software metric scores and suggested refactorings would be very useful.

Page 23: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 23

Some refactoring examples explained with the help of UML.

http://www.uml.org

Page 24: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 24

Pull Up Field

• Eliminating duplicate fields can help reduce defects and allows methods that use the fields to be moved to the superclass.

Page 25: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 25

Push Down Field

• Push a field down if it is not needed in the superclass.

Page 26: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 26

Pull Up Method

• Eliminating duplicate methods can help reduce defects.

Page 27: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 27

Push Down Method

• Methods should be pushed down if the they are not used by all the subclasses.

Page 28: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 28

Replace inheritance with delegation

class Sub extends Super {...}

• Suppose an object of Sub never uses the methods ying() and yang().

• Class Sub should then not inherit from class Super.

Page 29: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 29

Replace inheritance with delegation

class Sub {            Super s = new Super();           int foo() { return s.foo(); } // delegation           void bar() { s.bar(); }         // delegation           int baz() {...} // new method }

Page 30: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 30

Replace delegation with inheritance

class Sub {            Super s = new Super();           int foo() { return s.foo(); } // delegation           void bar() { s.bar(); }         // delegation char ying() {return s.ying();} // delegation char yang() {return s.yang();} // delegation           int baz() {...} // new method }

Page 31: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 31

Replace delegation with inheritance

• Suppose an object of Sub uses all of the methods foo(), bar(), ying() and yang().

• Class Sub should then inherit from class Super.

class Sub extends Super {...}

Page 32: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

32

Hide Delegate

• Hide a delegate class (Department) by creating a method on the server (Person).

manager = andy.getDepartment().getManager();manager = andy.getManager();

Page 33: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

33

Remove Middle Man

• The server class (Person) is delegating too much, so have the client call the delegate class (Department) directly.

manager = andy.getManager();manager = andy.getDepartment().getManager();

Page 34: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 34

Hide Delegate and Remove Middle Man:

Which refactoring is appropriate depends on the number of delegating methods involved (such as getManager()).

If there are a lot of delegating methods then the client should access the delegated class directly.

Page 35: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 35

Hide Method

• If a method is not used by any other class make the visibility private.

Page 36: Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool

18/04/23 Dr Andy Brooks 36

Do no forget the Two Hats Rule.Refactor code in the context of a testing framework.Each change has to be tested.

Do not forget many refactorings come in pairs.A refactoring may be reversed at a later date.

The part played by data members can influence a refactoring decision.

There are many more recognised refactorings.