24
Refactoring - Improving the smell of your code Vlad Mandrychenko October 2011

Refactoring - improving the smell of your code

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Refactoring - improving the smell of your code

Refactoring - Improving the smell of your codeVlad Mandrychenko

October 2011

Page 2: Refactoring - improving the smell of your code

Agenda

• What is refactoring?• Why refactor?• When NOT to refactor?• When to refactor?• Code Smells• How to refactor?• Refactoring Tools

Page 3: Refactoring - improving the smell of your code

What is refactoring?

• Disciplined technique for restructuring existing code without changing its external behavior.

• Series of small (measured in minutes) behavior preserving code transformations.

Page 4: Refactoring - improving the smell of your code

Why refactor?

• To make code easier to work with in the future 

• Speed up development

• Code is written once but is read many times

• Developers of all skill levels must be able to understand the code

Page 5: Refactoring - improving the smell of your code

Why refactor?

• To improve design o Improve reusability and remove duplicationo Allow for easier extensions and align code with

functionality and usageo Reduce complexity

• Improving code quality and rigidity, reduce bugs

• Simplify testing

Page 6: Refactoring - improving the smell of your code

Why refactor?

• Dramatically reduce development cost and headaches

Page 7: Refactoring - improving the smell of your code

When NOT to refactor?

• When it has no immediate business valueo Refactoring should be done as part of fixing a defect

or adding new feature

• Code does not work

• Inadequate test coverage

• Breaking used interfaces

• Requires expensive data migrations 

• Tight deadline

Page 8: Refactoring - improving the smell of your code

When to refactor?

• During defect fix or addition of a new feature

• When code is hard to read and understand

 • When code requires complex unit

tests • When upcoming changes are not

easily supported by existing code • Existing code requires a change

every time new feature is added • As result of code reviews

Page 9: Refactoring - improving the smell of your code

How to refactor

• Know your end goal

• Add missing unit tests

• Ensure unit tests pass before you start and in between each small refactoring

• Small, incremental, purposeful commits 

• Stop when you are unsure

• Backtrack 

• Pairing/Code Reviews

Page 10: Refactoring - improving the smell of your code

Refactoring and Design Patterns

• Go hand in hand

• Using patterns to improve existing design is better then using patterns in the new design

o  When designing new system, devs: Don't know all the requirements

Don't have a full working application

Guessing as to which patterns are actually applicable

Tend to over-engineer

Page 11: Refactoring - improving the smell of your code

Code smell? 

• Code smell is a possible symptom of the deeper problem

Duplicate codeif (isSpecialDeal()) {      total = price * 0.95;      send(); } else {     total = price * 0.98;     send(); }

Long and complicated methods/classespublic class PromotionFilterServiceImpl{    public LoyaltyProgramVO filter(... ...){        //1 method, 2 nested loops, 13 if statements, 80 lines of code = 1000+ lines test class    }}

Page 12: Refactoring - improving the smell of your code

Code smell? 

Too many method params    public void calculate(int from, int to, int x, int y, int ...){}

Ungrouped related fieldsclass DayCalculator {    private Date to;     private Date from;    private boolean skipSaturday;     private boolean skipSunday;       ..... }

God classesclass ManagerServiceHelperImpl {    public BigInt calculatePrice() {         //calculate stuff    }     public void handleResponse(){       //handle stuff    }  

   public Report manageReportPrinter(){       // manage stuff    }   

   public boolean isCanDoEverything()   {        return true;   }}

Page 13: Refactoring - improving the smell of your code

Code smell? 

Unused/temporary object fieldspublic class SessionVO {    private PartnerFeatureVO partnerFeatureVO = null;   private ReserveCertificateVO reserveCertificateVO; // only used for claim    private boolean giftOrTransfer;   ......   ......   }

Complicated VOs and Data Classespublic class SessionVO {    // contains 20 different nested mutable objects     // contains over 100 variables    // unknown lifecycle}

Page 14: Refactoring - improving the smell of your code

Code smells (cont'd)

Numerous switch/if/else statements   public double calculateArea(Object shape) {       double area = 0;       if (shape instanceof Square) {          Square square = (Square) shape;          area = square.getA() * square.getA();       } else if (shape instanceof Rectangle) {          Rectangle rectangle = (Rectangle) shape;          area = rectangle.getA() * rectangle.getB(); }       } else if (shape instanceof Circle) {          Circle circle = (Circle) shape;          area = Math.PI * cirle.getR() * cirle.getR();       }      return area;    }

Deep method chains   getHelper(){       getHandlerHelper(){           handleResponse(){              processReport();{              }           }       }   }

Page 15: Refactoring - improving the smell of your code

Code smells (cont'd)

Commentsclass DistanceCalculator(){   // FIXME: rename this method    public int process(Coordinates coords){    //this method calculates the distance between 2 coordinates    ..... .   .....   }}

Cascading change• Small change in 1 place cascades into multiple

changes in other parts of the code

Page 16: Refactoring - improving the smell of your code

Refactoring Tools

• IDE

Page 17: Refactoring - improving the smell of your code

How to refactor: catalog of techniques

http://refactoring.com/catalog/index.html 

Page 18: Refactoring - improving the smell of your code

How to refactor: some techniques

Rename Method

class DistanceCalculator(){   // FIXME: rename this method    public int process(Coordinates coords){    //this method calculates the distance between 2 coordinates    ..... .   .....   }}

class DistanceCalculator(){   public int calculateDistance(Coordinates coords){    ..... .   .....   }}

Page 19: Refactoring - improving the smell of your code

How to refactor: some techniques

Extract Interface

class Employee(){   double getRate(){ ... }   boolean hasSpecialSkill(){ ... }   getName (){ ... }   getDepartment(){ ... }   

}

interface Billable{   double getRate();   boolean hasSpecialSkill();}

class Employee implements Billable(){}class Contractor implements Billable(){} 

Page 20: Refactoring - improving the smell of your code

How to refactor: some techniques

Introduce Parameter Object

   public void calculate(int from, int to, int x, int y){ ... }   public void calculate(Range range, Location location){ ... }

Page 21: Refactoring - improving the smell of your code

How to refactor: some techniques

Replace Conditional with Polymorphismpublic class Client {       public double calculateArea(Object shape) {       double area = 0;       if (shape instanceof Square) {          Square square = (Square) shape;          area = square.getA() * square.getA();       } else if (shape instanceof Rectangle) {          Rectangle rectangle = (Rectangle) shape;          area = rectangle.getA() * rectangle.getB(); }       } else if (shape instanceof Circle) {          Circle circle = (Circle) shape;          area = Math.PI * cirle.getR() * cirle.getR();       }      return area;     }}

public class Square implements Shape {   private double a;    ...        public double getArea() {       return a * a;     }}public class Rectangle implements Shape {   private double a;   private double b;   ...   public double getArea() {      return a * b;   }}public class Client {   private Shape shape;   ...   public double calculateArea() {      return shape.getArea();   }}

Page 22: Refactoring - improving the smell of your code

How to refactor: some techniques

Replace Type Code with State/Strategy

Page 23: Refactoring - improving the smell of your code

How to refactor: some techniques

Replace Inheritance with Delegation

Page 24: Refactoring - improving the smell of your code

Reference Material

Books:• M Fowler -

Refactoring: Improving the Design of Existing Code • Gang Of Four - Design Patterns• Joshua Karievsky - Refactoring to Patterns

Websites:• refactoring.com• https://mwiki.points.com/wiki/SoftwareEngineering