Presentation is loading. Please wait.

Presentation is loading. Please wait.

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

Similar presentations


Presentation on theme: "Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool."— Presentation transcript:

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.

2 16/05/2015Dr Andy Brooks2 Case Study Dæmisaga Reference A Refactoring Micro-Example, David Parsons, http://www.dparsons.co.uk/Refactoring.html

3 16/05/2015Dr Andy Brooks3 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

4 16/05/2015Dr Andy Brooks4 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...

5 16/05/2015Dr Andy Brooks5 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

6 16/05/2015Dr Andy Brooks6 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. R D

7 16/05/2015Dr Andy Brooks7 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<1 1<=x<7 (int) truncates fraction

8 16/05/2015Dr Andy Brooks8 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.

9 16/05/2015Dr Andy Brooks9 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; }

10 16/05/2015Dr Andy Brooks10 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; }

11 16/05/2015Dr Andy Brooks11 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();}

12 16/05/2015Dr Andy Brooks12 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); }

13 16/05/2015Dr Andy Brooks13 Refactoring 5 – Move Method public 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.

14 16/05/2015Dr Andy Brooks14 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;

15 16/05/2015Dr Andy Brooks15 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.random setFaceValue(random.nextInt(5) + 2); break; default: setFaceValue(1); } The roll() method now has a switch. inclusive of 0 exclusive of 5

16 16/05/2015Dr Andy Brooks16 Refactor 6 – Replace conditional with polymorphism Die NormalLoaded //Normal Die implementation public void roll() { setFaceValue((int)(Math.random() * 6) + 1); } //Loaded Die implementation public void roll() { setFaceValue(random.nextInt(5) + 2); } abstract superclass

17 16/05/2015Dr Andy Brooks17 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.

18 16/05/2015Dr Andy Brooks18 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();

19 16/05/2015Dr Andy Brooks19 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);

20 16/05/2015Dr Andy Brooks20 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...

21 16/05/2015Dr Andy Brooks21 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?

22 16/05/2015Dr Andy Brooks22 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.

23 16/05/2015Dr Andy Brooks23 Some refactoring examples explained with the help of UML. http://www.uml.org

24 16/05/2015Dr Andy Brooks24 Pull Up Field Eliminating duplicate fields can help reduce defects and allows methods that use the fields to be moved to the superclass.

25 16/05/2015Dr Andy Brooks25 Push Down Field Push a field down if it is not needed in the superclass.

26 16/05/2015Dr Andy Brooks26 Pull Up Method Eliminating duplicate methods can help reduce defects.

27 16/05/2015Dr Andy Brooks27 Push Down Method Methods should be pushed down if the they are not used by all the subclasses.

28 16/05/2015Dr Andy Brooks28 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.

29 16/05/2015Dr Andy Brooks29 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 }

30 16/05/2015Dr Andy Brooks30 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 }

31 16/05/2015Dr Andy Brooks31 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 {...}

32 32 Hide Delegate Hide a delegate class (Department) by creating a method on the server (Person). manager = andy.getDepartment().getManager(); manager = andy.getManager();

33 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();

34 16/05/2015Dr Andy Brooks34 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.

35 16/05/2015Dr Andy Brooks35 Hide Method If a method is not used by any other class make the visibility private.

36 16/05/2015Dr Andy Brooks36 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.


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

Similar presentations


Ads by Google