refactoringrefactoring. realities code evolves substantially during development requirements changes...

30
REFACTORING REFACTORING

Upload: vernon-carroll

Post on 05-Jan-2016

212 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

REFACTORINGREFACTORING

Page 2: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

RealitiesRealities

• Code evolves substantially during development

• Requirements changes 1%-4% per month on a project

• Current methodologies are code-centered, resulting in more frequent code changes

• Code evolves substantially during development

• Requirements changes 1%-4% per month on a project

• Current methodologies are code-centered, resulting in more frequent code changes

Page 3: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

Origin of RefactoringOrigin of Refactoring

• Martin Fowler is the thought-leader on this topic

• His definition of refactoring: “a change made to the internal structure of the software to make it easier to understand and cheaper to modify without changing its observable behavior.”

• Martin Fowler is the thought-leader on this topic

• His definition of refactoring: “a change made to the internal structure of the software to make it easier to understand and cheaper to modify without changing its observable behavior.”

Page 4: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

Reasons to RefactorReasons to Refactor

• Code is duplicated• A routine is too long• A loop is too long or too deeply nested• A class has poor cohesion• A class interface does not provide a

consistent level of abstraction

• Code is duplicated• A routine is too long• A loop is too long or too deeply nested• A class has poor cohesion• A class interface does not provide a

consistent level of abstraction

Page 5: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

Reasons to Refactor (cont’d)Reasons to Refactor (cont’d)

• A parameter list has too many parameters• Changes within a class tend to be

compartmentalized• Changes require parallel modifications to

multiple classes• Inheritance hierarchies have to be modified

in parallel

• A parameter list has too many parameters• Changes within a class tend to be

compartmentalized• Changes require parallel modifications to

multiple classes• Inheritance hierarchies have to be modified

in parallel

Page 6: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

Reasons to Refactor (cont’d)Reasons to Refactor (cont’d)

• Case statements have to be modified in parallel

• Related data items that are used together are not organized into classes

• A routine uses more features of another class than of its own class

• A primitive data type is overloaded

• Case statements have to be modified in parallel

• Related data items that are used together are not organized into classes

• A routine uses more features of another class than of its own class

• A primitive data type is overloaded

Page 7: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

Reasons to Refactor (cont’d)Reasons to Refactor (cont’d)

• A class doesn’t do very much• A chain of routines passes tramp data• A middleman object doesn’t do anything• One class is overly intimate with another• A routine has a poor name

• A class doesn’t do very much• A chain of routines passes tramp data• A middleman object doesn’t do anything• One class is overly intimate with another• A routine has a poor name

Page 8: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

Reasons to Refactor (cont’d)Reasons to Refactor (cont’d)

• Data members are public• A subclass uses only a small percentage of

its parent’s routines• Comments are used to explain difficult code• Global variables are used• A routine uses setup code before a method

call or takedown code after a method call

• Data members are public• A subclass uses only a small percentage of

its parent’s routines• Comments are used to explain difficult code• Global variables are used• A routine uses setup code before a method

call or takedown code after a method call

Page 9: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

Reasons to Refactor (cont’d)Reasons to Refactor (cont’d)

• A program contains code that seems like it might be needed someday

• A program contains code that seems like it might be needed someday

Page 10: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

Data-level RefactoringsData-level Refactorings

• Replace a magic number with a named constant

• Rename a variable with a clearer or more informative name

• Move an expression inline• Replace an expression with a method• Introduce an intermediate variable

• Replace a magic number with a named constant

• Rename a variable with a clearer or more informative name

• Move an expression inline• Replace an expression with a method• Introduce an intermediate variable

Page 11: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

Data-level Refactorings (cont’d)Data-level Refactorings (cont’d)

• Convert a multi-use variable to multiple single-use variables

• Use a local variable for local purposes rather that as a parameter

• Convert a data primitive to a class• Convert a set of type codes to a class or an

enumeration

• Convert a multi-use variable to multiple single-use variables

• Use a local variable for local purposes rather that as a parameter

• Convert a data primitive to a class• Convert a set of type codes to a class or an

enumeration

Page 12: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

Data-level Refactorings (cont’d)Data-level Refactorings (cont’d)

• Convert a set of type codes to a class with subclasses

• Change an array to an object• Encapsulate a collection• Replace a traditional record with a

data class

• Convert a set of type codes to a class with subclasses

• Change an array to an object• Encapsulate a collection• Replace a traditional record with a

data class

Page 13: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

Statement-level RefactoringsStatement-level Refactorings

• Decompose a boolean expression• Move a complex boolean expression into a

well-named boolean function• Consolidate fragments that are duplicated

within different parts of a conditional• Use break or return instead of a loop control

variable

• Decompose a boolean expression• Move a complex boolean expression into a

well-named boolean function• Consolidate fragments that are duplicated

within different parts of a conditional• Use break or return instead of a loop control

variable

Page 14: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

Statement-level Refactorings (cont’d)

Statement-level Refactorings (cont’d)

• Return as soon as you know the answer instead of assigning a return value with nested if-then-else statements

• Replace conditionals (especially repeated case statements) with polymorphism

• Create and use null objects instead of testing for null values

• Return as soon as you know the answer instead of assigning a return value with nested if-then-else statements

• Replace conditionals (especially repeated case statements) with polymorphism

• Create and use null objects instead of testing for null values

Page 15: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

Routine-level RefactoringsRoutine-level Refactorings

• Extract routine/extract method

• Move a routine’s code inline

• Convert a long routine into a class

• Substitute a simple algorithm for a complex algorithm

• Extract routine/extract method

• Move a routine’s code inline

• Convert a long routine into a class

• Substitute a simple algorithm for a complex algorithm

Page 16: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

Routine-level Refactorings (cont’d)Routine-level Refactorings (cont’d)

• Add a parameter• Remove a parameter• Separate query operations from

modification operations• Combine similar routines by

parameterizing them

• Add a parameter• Remove a parameter• Separate query operations from

modification operations• Combine similar routines by

parameterizing them

Page 17: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

Routine-level Refactorings (cont’d)Routine-level Refactorings (cont’d)

• Separate routines whose behavior depends on parameters passed in

• Pass a whole object rather than specific fields

• Pass specific fields rather than a whole object

• Encapsulate downcasting

• Separate routines whose behavior depends on parameters passed in

• Pass a whole object rather than specific fields

• Pass specific fields rather than a whole object

• Encapsulate downcasting

Page 18: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

Class Implementation RefactoringsClass Implementation Refactorings

• Change value objects to reference objects

• Change reference objects to value objects

• Replace virtual routines with data initialization

• Change value objects to reference objects

• Change reference objects to value objects

• Replace virtual routines with data initialization

Page 19: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

Class Implementation Refactorings (cont’d)

Class Implementation Refactorings (cont’d)

• Change member routine or data placement– Pull a routine up into its superclass– Pull a field up into its superclass– Push a routine down into its derived class– Push a field down into it derived class– Push a constructor body down into is derived

class

• Change member routine or data placement– Pull a routine up into its superclass– Pull a field up into its superclass– Push a routine down into its derived class– Push a field down into it derived class– Push a constructor body down into is derived

class

Page 20: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

Class Implementation Refactorings (cont’d)

Class Implementation Refactorings (cont’d)

• Extract specialized code into a subclass

• Combine similar code into a superclass

• Extract specialized code into a subclass

• Combine similar code into a superclass

Page 21: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

Class Interface RefactoringsClass Interface Refactorings

• Move a routine to another class

• Convert one class to two

• Eliminate a class

• Hide a delegate

• Remove a middleman

• Move a routine to another class

• Convert one class to two

• Eliminate a class

• Hide a delegate

• Remove a middleman

Page 22: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

Class Interface Refactorings (cont’d)Class Interface Refactorings (cont’d)

• Replace inheritance with delegation• Replace delegation with inheritance• Introduce a foreign routine• Introduce an extension class• Encapsulate an exposed member variable

• Replace inheritance with delegation• Replace delegation with inheritance• Introduce a foreign routine• Introduce an extension class• Encapsulate an exposed member variable

Page 23: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

Class Interface Refactorings (cont’d)Class Interface Refactorings (cont’d)

• Remove Set() routines for field that cannot be changed

• Hide routines that are not intended to be used outside the class

• Encapsulate unused routines• Collapse a superclass and subclass if their

implementations are very similar

• Remove Set() routines for field that cannot be changed

• Hide routines that are not intended to be used outside the class

• Encapsulate unused routines• Collapse a superclass and subclass if their

implementations are very similar

Page 24: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

System-Level RefactoringsSystem-Level Refactorings

• Create a definitive data source for data you can’t control

• Change unidirectional class association to bidirectional class association

• Change bidirectional class association to unidirectional class association

• Provide a factory method rather than a simple constructor

• Repalce error codes with exceptions or vice versa

• Create a definitive data source for data you can’t control

• Change unidirectional class association to bidirectional class association

• Change bidirectional class association to unidirectional class association

• Provide a factory method rather than a simple constructor

• Repalce error codes with exceptions or vice versa

Page 25: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

Refactoring SafelyRefactoring Safely

• Save the code you start with• Keep refactorings small• Do refactorings one at a time• Make a list of steps you intend to take• Make a parking lot• Make frequent checkpoints

• Save the code you start with• Keep refactorings small• Do refactorings one at a time• Make a list of steps you intend to take• Make a parking lot• Make frequent checkpoints

Page 26: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

Refactoring Safely (cont’d)Refactoring Safely (cont’d)

• Use your compiler warnings• Retest• Add test cases• Review the changes• Adjust your approach depending on the risk

level of the refactoring

• Use your compiler warnings• Retest• Add test cases• Review the changes• Adjust your approach depending on the risk

level of the refactoring

Page 27: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

When Not to RefactorWhen Not to Refactor

• Don’t use refactoring as a cover for code and fix

– This is a misuse of refactoring– Refactoring applies to changes in working code

• Avoid refactoring instead of rewriting– Should the code be tossed out and completely

redesigned and rewritten?

• Don’t use refactoring as a cover for code and fix

– This is a misuse of refactoring– Refactoring applies to changes in working code

• Avoid refactoring instead of rewriting– Should the code be tossed out and completely

redesigned and rewritten?

Page 28: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

Refactoring StrategiesRefactoring Strategies

• Focus on the refactorings that produce the highest level of benefit

• Refactor when you add a method

• Refactor when you add a class

• Refactor when you fix a defect

• Focus on the refactorings that produce the highest level of benefit

• Refactor when you add a method

• Refactor when you add a class

• Refactor when you fix a defect

Page 29: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

Refactoring Strategies (cont’d)Refactoring Strategies (cont’d)

• Target error-prone modules• Target highest complexity modules• In a maintenance environment, improve the

parts you touch• Define an interface between clean code and

ugly code, and then move code across the interface

• Target error-prone modules• Target highest complexity modules• In a maintenance environment, improve the

parts you touch• Define an interface between clean code and

ugly code, and then move code across the interface

Page 30: REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies

Refactoring Legacy SystemsRefactoring Legacy Systems

• Any time you touch messy code in the legacy system:

– Bring it across to the ideal side of the interface– Bring the code up to current coding standards– Provide clear variable names– Create classes with high cohesion– Etc.

• Any time you touch messy code in the legacy system:

– Bring it across to the ideal side of the interface– Bring the code up to current coding standards– Provide clear variable names– Create classes with high cohesion– Etc.