Introduction to Refactoring Jim Cooper Falafel Software
Jan 05, 2016
Introduction to Refactoring
Jim Cooper
Falafel Software
Refactoring
Refactoring. Improving the Design of Existing Code
Martin Fowler
2000, Addison-Wesley
ISBN 0-201-48567-2
We will use that terminology, guidelines and naming
What is Refactoring?
“Refactoring is the process of changing a software system in such a way that it does not
alter the external behaviour of the code yet improves its internal structure.”
Term applies both to the process and the individual techniques
What is Refactoring? - 2
Each refactoring is a series of steps
Each step is simple and small
Minimises introduction of new bugs
Unit tests used to verify changes
Behavioural changes to a program are not refactorings
Why Refactor?
Code is not for computers to read, it’s for us to read
90% of the lifetime of most software is in maintenance mode
Source code must be easy for humans to read, understand and modify
Refactoring helps make the code more usable by programmers
Aims of Refactoring
Improved design
Make code easier to understand
Can use it on other people’s code
Help find bugs
Faster programming in the long term
Formalise and name best practices
Easier to talk about
Reduce chaos in long-lived code
Opportunities for Refactoring
When adding functionality
Make adding new feature easier
Keep refactoring separate, though
When fixing a bug
During a code review
Pair programming
Refactoring takes time
Sneak it past managers
Refactoring Techniques
Too many to look at all of them
Will not discuss unit testing in detail
Start with the main ones, and then browse the book looking at others
No need to read the book cover to cover (it’s not that interesting)
Points to Note
Refactoring relies heavily on having object oriented code
Refactorings are usually more atomic than patterns, but some use patterns
Often language dependent
Refactoring book is very Java oriented
We will cover converting to Delphi
Not many refactorings use interfaces
Points to Note - 2
Many refactorings make use of other, simpler refactorings
Some are opposites
Use the one that makes your code easier to understand
Can apply some mechanically
It is possible to go too far!
Extract Method
Probably the most used technique
You should have done this many times yourself
Identify code to reuse, or that is making a method too long, so we make a new method out of it
Difference here is the formal definition of the process, and the guidelines for its use
Structure of Extract Method
Name – Extract Method
Summary – describes when to use
You have a code fragment that can be grouped together
Turn the fragment into a method whose name explains the purpose of the method
Structure of Extract Method - 2
Short code example
Motivation
Describes why the refactoring should be done, and also when it shouldn’t
Mechanics
Step by step instructions
One or more longer examples, usually with discussion
Structure of Extract Method - 3
Motivation
A method is too long
A section of code needs a comment to explain it
Short (well-named) methods easier to reuse and override
Higher-level methods easier to read
Good naming is key
Structure of Extract Method - 4
Mechanics
Create a new method with a good name
Copy extracted code to new method
Deal with variables and parameters in the original method
Dealing with Variables
Local variables only used in the extracted code can be copied to the new method
One original variable modified
Make the new method a function
Several original variables modified
Use var parameters
Use other refactorings first
Dealing with Variables - 2
Replace Temp with Query
Remove local variable, move expression to a method and call it each time the variable was used
Split Temporary Variable
Use a different local variable for each assignment
Structure of Extract Method - 5
Pass any original parameters used to the new method
Compile
Replace extracted code with method call
Remove any local variables no longer used
Compile and test
Don’t forget to test!!
Extract Class
Used when a class is violating the principle of separation of concerns
Often the result of feature creep
Can result from too many Extract Method refactorings
Splits out related subset of data and methods into a new class
May need to rename the old class if its duties have changed
Extract Class - 2
Normally need a reference to an object of the new class in the old one
Leave the new class in the implementation section if only used internally
Uses Move Field and Move Method refactorings to move elements of the new class across (test after each move)
Inline Class
The opposite of Extract Class
Applied when a class is doing too little
Move fields and methods into a class that uses them (there won’t be many)
Fowler humour :
The last step of the refactoring reads “Hold a short, simple funeral service”
Move Method
Moves a method from one class to another
May change name in the new class
Original class probably needs to refer to an instance of the new one
If the method is declared in an ancestor or descendant class, may not be able to move it easily
Inline Temp
Replace a local variable assigned to with a simple expression, with the expression
Removing local variables can make other refactorings easier
Local variable may be doing no harm, or may be there to avoid breaking the Law of Demeter
Leave it there
Rename Method
If the task of a method has changed, rename it to reflect the new duties
Seems trivial, but is very important
Bad naming defeats the whole purpose of encapsulation
Code is confusing, in the worst case it can be completely misinterpreted
Replace Magic Number with Symbolic Constant
Encapsulates a standard piece of programming advice
Applies to strings etc, as well, of course
This sort of refactoring useful when training new programmers
Replace Error Code with Exception
If you don’t already do this, line up at the front for a slapping
Code can be written assuming it works, and is therefore much easier to read
Error handling code separated out
Encapsulate Field
Needs to be modified for Delphi
Replace Field with Property
Replace a public field with a property
Otherwise the Delphi Style Police will come and kick you around
Use the Delphi naming convention
Move field to private, rename with F
Make a property named without the F
Self Encapsulate Field
We might allow direct access to a field within a class, if field is private
If field needs to be protected or better, or has side effects when used, then make it into a property
Direct access in constructor, destructor and property accessor methods
Use Replace Field with Property
Remove Control Flag
Some people use a local variable as a control flag to break out of loops
I’ve even seen goto used this way!
Use Break, Continue and Exit instead
Replace Type Code with State/Strategy
This refactoring introduces either the State or Strategy pattern
Used when the class behaviour varies depending on some state value
Lots of case statements are a giveaway
Demo code
Finite State Machine
This example is from ToD, with the kind permission of Julian Bucknall
Convert Refactorings to Delphi
Use const instead of final
To make an immutable class, make all the properties read only, and set their values in the constructor
Query = Function
Temporary variable = local variable
Some refactorings cannot be applied
e.g. garbage collection
When to Refactor – Bad Smells
Kent Beck’s idea
Combination of experience and intuition sometimes makes us feel code just isn’t right
There are some indicators we can look for
Bad Smells
Have names and recommended treatments
Bad Smells
Duplicated Code
Long Method
Large Class
Long Parameter List
Divergent Change
Shotgun Surgery
Feature Envy
Bad Smells - 2
Data Clumps
Primitive Obsession
Switch Statements
Parallel Inheritance Hierachies
Lazy Class
Speculative Generality
Data Class, Refused Bequest
Comments
Problems
Do not apply refactorings without thought for the consequences
Threads
Discipline is new, so not all problems found yet
Databases
Changing interfaces
Designs difficult to refactor
Code is beyond all help
Miscellaneous
Still need upfront design, but can design for ease of refactoring
Don’t make design too flexible
Don’t make optimisation decisions before finding bottlenecks
Refactor first, optimise after
Tools exist for Java (some in JBuilder) and C#, but little for Delphi ...
Refactoring in Delphi
Until now!
Diamondback has the following refactorings built in, with a promise of many more to follow
Rename
Extract Method
Extract Resource String
Refactoring in Delphi - 2
In addition, the new refactoring engine makes possible some handy things which are not, strictly speaking, refactorings
SyncEdit mode
Find References
Declare Variable
Declare Field
Import Namespace
Questions?
Thank You
You can contact me further [email protected]