230 likes | 395 Views
Software Engineering. Refactoring. Objectives. Describe the purpose of code refactoring. List code smells. Apply code refactoring. What is Code Refactoring. The process of changing a software system in such a way that it: improves the internal code structure
E N D
Software Engineering Refactoring
Objectives • Describe the purpose of code refactoring. • List code smells. • Apply code refactoring.
What is Code Refactoring • The process of changing a software system in such a way that it: • improves the internal code structure • does not alter external behavior of code public class Student { public String name; public static void main(String[] args) { Student s1 = new Student(); s1.name = “Tan Ah Beng”; Student s2 = new Student(); s2.name = “Lim Ah Seng”; }} Any problems with this code?
Code Refactoring in Action • Use getter and setter methods • Step 1: Create getter and setter methods public class Student { public String name;public String getName() { return name; } public void setName(String newName) { name = newName; } public static void main(String[] args) { Student s1 = new Student(); s1.name = “Tan Ah Beng”; Student s2 = new Student(); s2.name = “Lim Ah Seng”; }}
Code Refactoring in Action • Step 2: Find all clients; replace references with calls. Do this one at a time public class Student { public String name; public String getName() { return name; } public String setName(String newName) { name = newName; } public static void main(String[] args) { Student s1 = new Student();s1.setName(“Tan Ah Beng”); Student s2 = new Student(); s2.name = “Lim Ah Seng”; }}
Code Refactoring in Action • Step 3: Compile and test • Back to step 2: Replace other references public class Student { public String name; public String getName() { return name; } public String setName(String newName) { name = newName; } public static void main(String[] args) { Student s1 = new Student(); s1.setName(“Tan Ah Beng”); Student s2 = new Student();s2.setName(“Lim Ah Seng”); }}
Code Refactoring in Action • Back to step 3: Compile and test • Step 4: Once all clients are changed, make the field private • Step 5: Compile and test one last time public class Student {private String name; public String getName() { return name; } public String setName(String newName) { name = newName; } public static void main(String[] args) { Student s1 = new Student(); s1.setName(“Tan Ah Beng”); Student s2 = new Student(); s2.setName(“Lim Ah Seng”); }}
Refactoring • Why refactor? • Improves the design of software • Makes software easier to understand • Helps you find bugs • Helps you program faster • When do we refactor? • When you add function • When you need to fix a bug • When you do a code review
Detecting Code Smells • Code smells are warning signs about problems within the code • Common smells • Duplicated code • Long methods • Long parameter list • Large classes (in terms of instance variables, methods and lines) • Data clumps (groups of data items appearing together in lots of places) • Comments (is it really a bad smell?)
Refactoring Cycle • Start with a working program • While smells remain • Choose the worst smell • Select a refactoring that will address the smell • Apply the refactoring • Remember: the condition for refactoring safely is to have tests to cover those code we want to refactor
Code Refactoring • Parameterize method • Pass Whole Object • Replace Magic Number with Named Constants
Toy Toy getTenPercentDiscountedPrice():double getFivePercentDiscountedPrice():double getDiscountedPrice(percent):double Parameterize Method • Several methods do similar things but each uses different values • Replace them with one method that uses a parameter for the different values
Parameterize Method Example public class Wizard { private int willPower; public int castFireSpell(int damage) { return damage + (willPower * 1.1); } public int castColdSpell(int damage) { return damage + (willPower * 2.1); } public static void main(String[] args) { …………………………… damage = wizard.castFireSpell(damage); damage = wizard.castColdSpell(damage); …………………………… }}
Parameterize Method in Action public class Wizard { private int willPower; public int castFireSpell(int damage) { return damage + (willPower * 1.1); } public int castColdSpell(int damage) { return damage + (willPower * 2.1); }public int castSpell(int damage, int factor) { return damage + (willPower * factor); } public static void main(String[] args) { …………………………… damage = wizard.castFireSpell(damage); damage = wizard.castColdSpell(damage); …………………………… }}
Parameterize Method in Action public class Wizard { private int willPower; public int castFireSpell(int damage) { return damage + (willPower * 1.1); } public int castColdSpell(int damage) { return damage + (willPower * 2.1); } public int castSpell(int damage, int factor) { return damage + (willPower * factor); } public static void main(String[] args) { ……………………………damage = wizard.castSpell(damage,1.1); damage = wizard.castColdSpell(damage); …………………………… }}
Parameterize Method in Action public class Wizard { private int willPower; public int castFireSpell(int damage) { return damage + (willPower * 1.1); } public int castColdSpell(int damage) { return damage + (willPower * 2.1); } public int castSpell(int damage, int factor) { return damage + (willPower * factor); } public static void main(String[] args) { …………………………… damage = wizard.castSpell(damage,1.1);damage = wizard.castSpell(damage,2.1); …………………………… }}
int low = tempRange.getLow(); int high = tempRange.getHigh(); int ave = monitor.computeAverage(low, high); int ave = monitor.computeAverage(tempRange); Pass Whole Object • You get several values from an object and pass these values as parameters in a method call • Send the whole object instead
Pass Whole Object Example class Game { void throwGrenade(Person rambo, Grenade g) { int xPos = rambo.getX(); int yPos = rambo.getY(); if (g.isWithinRange(xPos, yPos)) rambo.addDamage(10); }}class Grenade { boolean isWithinRange(int xPos, int yPos) { if ((xPos >= gx) && (xPos <= gx + 25) && (yPos >= yx) && (yPos <= yx + 25)) return true; else return false; }}
Pass Whole Object in Action class Game { void throwGrenade(Person rambo, Grenade g) { int xPos = rambo.getX(); int yPos = rambo.getY(); if (g.isWithinRange(rambo, xPos, yPos)) rambo.addDamage(10); }}class Grenade { boolean isWithinRange(Person r, int xPos, int yPos) { if ((xPos >= gx) && (xPos <= gx + 25) && (yPos >= yx) && (yPos <= yx + 25)) return true; else return false; }}
Pass Whole Object in Action class Game { void throwGrenade(Person rambo, Grenade g) { int xPos = rambo.getX(); int yPos = rambo.getY(); if (g.isWithinRange(rambo, xPos, yPos)) rambo.addDamage(10); }}class Grenade { boolean isWithinRange(Person r, int xPos, int yPos) { if ((r.getX() >= gx) && (r.getX() <= gx + 25) && (r.getY() >= yx) && (r.getY() <= yx + 25)) return true; else return false; }}
Pass Whole Object In Action class Game { void throwGrenade(Person rambo, Grenade g) {int xPos = rambo.getX(); int yPos = rambo.getY(); if (g.isWithinRange(rambo, xPos, yPos)) rambo.addDamage(10); }}class Grenade { boolean isWithinRange(Person r, int xPos, int yPos) { if ((r.getX() >= gx) && (r.getX() <= gx + 25) && (r.getY() >= yx) && (r.getY() <= yx + 25)) return true; else return false; }}
Replace Magic Number with Named Constant • In your code, you use literals directly • Instead of using the literals directly, create a constant giving it an appropriate name, and use the constant instead double parcelAmount (double wt) { return 0.50 * wt; } private final static double AIRMAIL_RATE = 0.50; double parcelAmount (double wt) { return AIRMAIL_RATE * wt; }
Recap • What is refactoring and why is it important? • Describe 3 code smells. • Give examples on the application of the following refactorings: • Parameterize Method • Pass Whole Object • Replace Magic Number with Named Constant