Principles in
Refactoring
Defining Refactoring
Refactoring (noun): a change made to the internal
structure of software to make it easier to understand
and cheaper to modify without changing its
observable behavior.
Refactor (verb): to restructure software by
applying a series of refactorings without changing its
observable behavior.
Defining Refactoring
• Refactoring is cleaning up code in a more
efficient and controlled manner
• Purpose is to make the software easier to
understand and modify
• Does not change the observable behavior of
the software
The Two Hats
• Adding function and refactoring
• Frequent hat swapping
• Should be aware of the current hat
Why Should You
Refactor?
• Not a “silver bullet”
• Yet a valuable tool
• Serves several purposes
Refactoring Improves the
Design of Software
• Without refactoring, the design of the program
will decay
• Important to eliminate duplicate code
Simplifies future modifications
Refactoring Makes Software
Easier to Understand
• Two users of the code
Computer
Future developers
• Refactoring makes your code more readable
Refactoring Helps You
Find Bugs
• Help in understanding the code also helps in
spotting bugs
Refactoring Helps You
Program Faster
• Counterintuitive
• good design is essential for rapid software
development
poor design slows you down
Time is spent on finding and fixing bugs instead of
adding new function
When Should You
Refactor?
• refactoring is not an activity you set aside
time to do
you do it all the time in little bursts
The Rule of Three
Tip
Three strikes and you refactor.
Refactor When You Add
Function
• The most common time to refactor is when
you want to add a new feature
Refactoring helps in understanding the code that
needs modification
The other driver of refactoring here is a design
that hinders adding a feature easily
Refactor When You Need
to Fix a Bug
• In fixing bugs much of the use of refactoring
comes from making code more
understandable
• if you do get a bug report, it's a sign you need
refactoring
the code was not clear enough for you to see
there was a bug
Refactor As You Do a
Code Review
• Some organizations do regular code reviews
Others should too
help spread knowledge through a development team
help more experienced developers pass knowledge
to less experienced people
help more people understand more aspects of a large
software system
important in writing clear code
give the opportunity for more people to suggest
useful ideas
• Refactoring helps in reviewing someone else's
code
• Refactoring helps the code review have more
concrete results
Problems with
Refactoring
• Databases
• Changing Interfaces
• Design Changes That Are Difficult to Refactor
• When Shouldn't You Refactor?
Databases
• A problem area for refactoring
• Most business applications are tightly coupled
to the database schema that supports them
database is difficult to change
• data migration
changing the database schema forces you to
migrate the data
• Some OO databases provide automatic
migration
Changing Interfaces
• Objects allow you to change the
implementation separately from the interface
• Many of the refactorings do change an
interface
• If a refactoring changes a published interface
retain both the old interface and the new one
• Don't publish interfaces unless you really need
to
Design Changes That Are
Difficult to Refactor
• This is an area in which we have very
incomplete data
When Shouldn't You
Refactor?
• There are times when the existing code is such
a mess that although you could refactor it, it
would be easier to start from the beginning
This decision is not an easy one to make
A clear sign of the need to rewrite is when the
current code just does not work
code has to work mostly correctly before you
refactor
• The other time you should avoid refactoring is
when you are close to a deadline.
Bad Smells in
Code
Duplicated Code
Contd..
• Duplication usually occurs when multiple
programmers are working on different parts of the
same program at the same time.
• There’s also more subtle duplication, when specific
parts of code look different but actually perform the
same job. This kind of duplication can be hard to find
and fix.
• Sometimes duplication is purposeful. When rushing
to meet deadlines and the existing code is “almost
right” for the job, novice programmers may not be
able to resist the temptation of copying and pasting
the relevant code. And in some cases, the
programmer is simply too lazy to de-clutter.
Duplicated Code
• If the same code is found in two or more methods in
the same class: use Extract Method and place calls
for the new method in both places.
• same expression in two sibling subclasses
Extract method
Pull up field
• code is similar but not completely identical
Extract method
Form template method
• methods do the same thing with a different algorithm
Substitute algorithm
• duplicated code in two unrelated classes
Extract class
Long Method
Long Method
• longer a procedure is, the more difficult it is to
understand.
• Aggressively decompose methods
whenever we feel the need to comment something,
we write a method instead
Extract method
• method with lots of parameters and temporary
variables
Replace Temp with Query, Introduce Parameter
Object, Preserve Whole Object
Replace Method with Method Object.
• Conditionals and loops also give signs for
extractions
Decompose Conditional
Large Class
Large Class
• a class is trying to do too much
Too many instance variables, duplicated code
• Extract Class, extract subclass
• a class with too much code
eliminate redundancy in the class itself
• a class with a huge wad of variables
Extract Class or Extract Subclass
Extract Interface
Solution
Long Parameter List
Long Parameter List
• long parameter lists are hard to understand
Replace Parameter with Method
Preserve Whole Object
Introduce Parameter Object
• important exception
when you explicitly do not want to create a
dependency from the called object to the larger
object
Unpacking data and sending it along as
parameters is reasonable
Solution
Divergent Change
• one class is commonly changed in different
ways for different reasons.
• identify everything that changes for a
particular cause
• Use Extract Class to put them all together.
Divergent change
Solution
Shotgun Surgery
• every time you make a kind of change, you
have to make a lot of little changes to a lot of
different classes
Opposite of divergent change
easy to miss an important change.
Move Method and Move Field to put all the
changes into a single class
Inline Class
• ideally, there is a one-to-one link between
common changes and classes
Feature Envy
• a method that seems more interested in a
class other than the one it actually is in
The most common focus of the envy is the data
Move Method
Extract Method and Move Method
• a method uses features of several classes
determine which class has most of the data and
put the method with that data
easier if Extract Method is used to break the
method into pieces.
Data Clumps
• Bunches of data that hang around together
really ought to be made into their own object
Extract Class
Introduce Parameter Object or Preserve Whole
Object
• A good test is to consider deleting one of the
data values
would the others make any sense?
• once you have the objects, look for cases of
feature envy
Switch Statements
• Good OO code lacks switch statements
• switch statements causes duplication
• polymorphism should replace switch
statement
• to extract the switch statement
Extract Method
• to get it onto the right class
Move Method
• Replace Type Code with Subclasses or Replace
Type Code with State/Strategy
Parallel Inheritance
Hierarchies
• Every time you make a subclass of one class,
you also have to make a subclass of another
a special case of shotgun surgery
• Move Method and Move Field
Lazy Class
• A class that isn't doing enough should be
eliminated
Often a class that has been downsized with
refactoring
Or a class that was added because of changes
that were planned but not made
• If subclasses aren't doing enough
Collapse Hierarchy
• Nearly useless components
Inline Class
Speculative Generality
• When people say, "Oh, I think we need the ability
to this kind of thing someday"
want all sorts of hooks and special cases to handle
things that aren't required
often is harder to understand and maintain
• abstract classes that aren't doing much
Collapse Hierarchy
• Unnecessary delegation
Inline Class
• Methods with unused parameters
Remove Parameter
• Methods named with odd abstract names
Rename Method
Message Chains
Message Chains
• when a client asks one object for another
object
which the client then asks for yet another object
which the client then asks for yet another object
and so on
• to every object in the chain
Hide Delegate
turns every intermediate object into a middle man
Middle Man
Middle Man
• One of the prime features of objects is
encapsulation
Encapsulation often comes with delegation
• this can go too far
half the methods of a class interface are
delegating to another class
Remove Middle Man
Inappropriate Intimacy
• Sometimes classes become far too intimate
• to reduce the intimacy
Move Method and Move Field
• Change Bidirectional Association to
Unidirectional
• If the classes have common interests
Extract Class to put the commonality
Or Hide Delegate to let another class act as go-
between
Solution
Alternative Classes with
Different Interfaces
• Methods that do the same thing but have
different signatures
Rename Method
• If the classes aren't yet doing enough
Keep using Move Method to move behavior to the
classes until the protocols are the same
• If you have to redundantly move code to
accomplish this
Extract Superclass
Incomplete Library Class
• Library builders have a really tough job
usually impossible to modify a library class
Move Method is useless
• If there are just a couple of methods that you
wish the library class had
Introduce Foreign Method
• If there is lot of extra behavior
Introduce Local Extension
Refused Bequest
• Subclasses get to inherit the methods and
data of their parents
what if they don't want or need what they are
given?
• this means the hierarchy is wrong
need to create a new sibling class
Push Down Method and Push Down Field to push
all the unused methods to the sibling
Comments
• If you need a comment to explain what a block
of code does
Extract Method
• If the method is already extracted but you still
need a comment to explain what it does
Rename Method
• If you need to state some rules about the
required state of the system
Introduce Assertion