KEMBAR78
Refactoring - improving the smell of your code | PPT
Refactoring - Improving the smell of your code Vlad Mandrychenko October 2011
Agenda What is refactoring? Why refactor? When NOT to refactor? When to refactor? Code Smells How to refactor? Refactoring Tools
What is refactoring? Disciplined  technique for restructuring existing code without changing its external behavior. Series of  small (measured in minutes)  behavior preserving code transformations.
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
Why refactor? To improve design  Improve reusability and remove duplication Allow for easier extensions and align code with functionality and usage Reduce complexity Improving code quality and rigidity, reduce bugs Simplify testing
Why refactor? Dramatically reduce  development  cost and headaches
When NOT to refactor? When it has no immediate business value 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
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
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
Refactoring and Design Patterns Go hand in hand Using patterns to improve existing design is better then using patterns in the new design   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
Code smell?  Code smell is a possible symptom of the deeper problem Duplicate code if   ( isSpecialDeal ())   {         total  =  price  *   0.95 ;         send();   }  else   {        total  =  price  *   0.98 ;        send();   } Long and complicated methods/classes public class PromotionFilterServiceImpl{      public LoyaltyProgramVO  filter (... ...){          // 1 method, 2  nested loops,  13   if  statements,  80  lines of code =  1000+  lines test  class      } }
Code smell?  Too many method params      public   void  calculate ( int   from ,  int   to ,  int   x ,  int   y ,  int  ... ){} Ungrouped related fields class  DayCalculator  {      private  Date to;        private  Date from;      private   boolean  skipSaturday;       private   boolean  skipSunday;          .....   } God classes class  ManagerServiceHelperImpl  {       public  BigInt  calculatePrice () {            //calculate stuff       }        public   void   handleResponse (){         //handle stuff       }        public  Report  manageReportPrinter (){          // manage stuff       }         public   boolean   isCanDoEverything ()     {           return true;     } }
Code smell?  Unused/temporary object fields public class SessionVO  {       private PartnerFeatureVO partnerFeatureVO  =   null ;     private ReserveCertificateVO reserveCertificateVO;  // only used for claim       private boolean giftOrTransfer;     ......     ......    } Complicated VOs and Data Classes public   class  Session VO   {      // contains 20 different nested mutable objects        // contains over 100 variables      // unknown lifecycle }
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();{                }             }         }     }
Code smells (cont'd) Comments class 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
Refactoring Tools IDE
How to refactor: catalog of techniques http://refactoring.com/catalog/index.html  
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){      ..... .     .....     } }
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() {} 
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 ){ ... }
How to refactor: some techniques Replace Conditional with Polymorphism public   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();     } }
How to refactor: some techniques Replace Type Code with State/Strategy
How to refactor: some techniques Replace Inheritance with Delegation
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

Refactoring - improving the smell of your code

  • 1.
    Refactoring - Improvingthe smell of your code Vlad Mandrychenko October 2011
  • 2.
    Agenda What isrefactoring? Why refactor? When NOT to refactor? When to refactor? Code Smells How to refactor? Refactoring Tools
  • 3.
    What is refactoring?Disciplined  technique for restructuring existing code without changing its external behavior. Series of small (measured in minutes) behavior preserving code transformations.
  • 4.
    Why refactor? Tomake 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
  • 5.
    Why refactor? Toimprove design  Improve reusability and remove duplication Allow for easier extensions and align code with functionality and usage Reduce complexity Improving code quality and rigidity, reduce bugs Simplify testing
  • 6.
    Why refactor? Dramaticallyreduce  development  cost and headaches
  • 7.
    When NOT torefactor? When it has no immediate business value 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
  • 8.
    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
  • 9.
    How to refactorKnow 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
  • 10.
    Refactoring and DesignPatterns Go hand in hand Using patterns to improve existing design is better then using patterns in the new design   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
  • 11.
    Code smell?  Codesmell is a possible symptom of the deeper problem Duplicate code if ( isSpecialDeal ()) {         total = price * 0.95 ;         send();   }  else {       total = price * 0.98 ;       send();   } Long and complicated methods/classes public class PromotionFilterServiceImpl{     public LoyaltyProgramVO filter (... ...){         // 1 method, 2  nested loops,  13   if  statements,  80  lines of code =  1000+  lines test  class      } }
  • 12.
    Code smell?  Toomany method params     public void calculate ( int from , int to , int x , int y , int ... ){} Ungrouped related fields class DayCalculator  {     private Date to;       private  Date from;     private boolean skipSaturday;      private boolean skipSunday;         .....   } God classes class  ManagerServiceHelperImpl  {       public BigInt calculatePrice () {           //calculate stuff       }        public void handleResponse (){         //handle stuff       }       public Report manageReportPrinter (){          // manage stuff       }        public boolean isCanDoEverything ()     {           return true;     } }
  • 13.
    Code smell?  Unused/temporaryobject fields public class SessionVO {       private PartnerFeatureVO partnerFeatureVO = null ;     private ReserveCertificateVO reserveCertificateVO; // only used for claim       private boolean giftOrTransfer;     ......     ......    } Complicated VOs and Data Classes public class Session VO {     // contains 20 different nested mutable objects       // contains over 100 variables     // unknown lifecycle }
  • 14.
    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();{               }             }         }     }
  • 15.
    Code smells (cont'd)Comments class 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
  • 16.
  • 17.
    How to refactor:catalog of techniques http://refactoring.com/catalog/index.html  
  • 18.
    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){      ..... .     .....     } }
  • 19.
    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() {} 
  • 20.
    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 ){ ... }
  • 21.
    How to refactor:some techniques Replace Conditional with Polymorphism public 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();     } }
  • 22.
    How to refactor:some techniques Replace Type Code with State/Strategy
  • 23.
    How to refactor:some techniques Replace Inheritance with Delegation
  • 24.
    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