Software Refactoring
Benjamin Culkin
[email protected]
Abstract This paper overviews what refactoring is, the
benefits of refactoring, and some of the most common types of
refactoring
Keywords Software Engineering, Refactoring, Code
Improvement, Overview
I.
INTRODUCTION
What is refactoring, and why is it a good thing? Well,
Martin Fowler, who wrote one of the seminal books on the
topic, defines it as a disciplined technique for
restructuring an existing body of code, altering its internal
structure without changing its external behavior. [1]. I find
that considering it as making changes to code that affect its
structure, without affecting its externally visible behavior
usually leads to it being much more clear exactly what a
refactoring is, and what a refactoring isnt. Further on in the
paper, I will explain why refactoring is something you want
to do, as well as examples of some of the most commonly
use refactorings (the noun used to describe more than one
refactoring).
II.
a program that is identical to one that hasnt had the
refactorings applied to it. Fourth, finally and most
importantly, a program and its refactored version have the
same externally visible behavior. Fig. 1 is a diagrammatic
illustration of this fact) With that little bit of definitional
clarity handled, we can turn to the important part, which is
why refactorings are explicitly mentioned as being small.
WHAT IS REFACTORING (IN DEPTH)
The definition of refactoring I provided before reveals the
most essential part of refactoring, but misses several details
that help provide insight into what makes a given code
change a refactoring. The first is that refactoring (the general
practice) is usually done as a series of small behaviorpreserving transformations on your program, each of which
is called a refactoring. (To clarify further what a refactoring
is, and the qualities it needs to satisfy, I will borrow a
mathematical term and define a refactoring as an
isomorphism over the set of valid programs. This implies
four things. One, if a refactoring is applied is applied to a
valid program, it will always result in a valid program.
Second, two refactorings may be combined into a single
larger refactoring that is equivalent to applying the
component refactorings in series. Third, for every
refactoring, there is a refactoring that does the exact
opposite, such that applying one then the other will result in
X-actions
f(y)
f(y')
f
y
Y-action
y'
!
Fig. 1: An illustration of what the behavior-independence of refactorings
means. f is the refactoring, but the refactoring is also the transform that
converts X-actions to Y-actions.
III.
WHY ARE REFACTORINGS SMALL?
In general, refactorings are small because making a small
change is much less likely to cause something to
unexpectedly change or go wrong, and this reduce the chance
that the system being refactored will break severely.
However, just because refactorings are generally small,
that does not mean that the impact of an individual
refactoring cannot be large. To borrow an example from later
in the paper, the Move Method refactoring is very simple
to understand, and only does one small thing, but (for
example) moving a heavily utilized method from a under
used class can lead to large portions of the code that referred
to that class suddenly not referring to it, and making
reducing it further by refactoring seem more tractable.
IV. WHY REFACTOR?
Now that we have defined what a refactoring is, why
should it be done? To simply put it, most refactoring is done
so as to make adding new features and changing existing
features simpler. It can also be done to improve the way code
looks and feels, as well as make it easier to find sources of
bugs. To quote a oft-quoted rule of software engineering: It
is easier to move a problem around than it is to solve it.
with its associated corollary It is always possible to add
another level of indirection. [2] Thus, a large number of
refactorings have to do with either adding or subtracting
layers of abstraction (Mostly adding abstraction, because
removing abstraction is substantially harder to do). However
we must keep in mind a fairly obvious exception that springs
to mind, which is that the only problem not solvable by the
introduction of more abstraction, is that of having too much
abstraction. So, when you refactor, be careful not to go crazy
with it. Too much of a good thing is usually bad.
V. COMMON TYPES OF REFACTORINGS
This section is an index of several types of refactorings
that are common to most languages, and several that are
more specific to object-orient languages.
TABLE 1: COMMON REFACTORINGS AND BRIEF DESCRIPTIONS OF THEM [3]
Refactoring Name
Refactoring Situation
Refactoring Description
Add Parameter
A method needs extra data provided to it by its callers
Add a parameter to a method to provide extra info to it
Collapse Hierarchy
A subclass and a superclass are fairly similiar
Convert the subclass and superclass into a single class
Extract Interface
Multiple classes have a group of methods in common
Create an interface that contains that group of methods,
and have all the classes implement it.
Extract Method
You have a piece of code you wish to use elsewhere
Put the code into a new method
Inline Method
A method contains a small, self explanatory piece of
code
Replace the method with the code in contains
Lazily Initialize Field
A field of a class is used rarely
Initialize the contents of the field whenever it is first
used
Move Method
A method in a class uses more features of another class
that it does of the class it belongs to
Move that method from its current class to the class it
uses the most from
Parameterize Method
Multiple methods do similar things, but with slight
differences
Add a parameter to the method that indicates which of
the things to do.
Pull Up Field
Two subclasses have the same field
Move the field to the superclass
Push Down Method
A superclass has a method that is only valid for some
of its subclasses
Move that method into the subclasses it is valid for
Rename Method
The name of a method doesnt explain what it does
Rename the method to something more indicative of its
purpose
Replace Hash with
Object
You have a hash (think map from strings to arbitrary
objects) where certain keys have special rules for valid
values for them
Replace the hash with an object that has the specific
fields, as well as a hash associated with it for any
necessary special cases
This table shows that there are a variety of different types
of refactorings, but what it doesnt necessarily show is that
some of these refactorings are more specific versions of
others. Consider the Push Down Method refactoring. Is it
not simply a special case of Move Method where the
method is being moved from a superclass into subclasses.
The only real distinction is that, in moving it down the
hierarchy, the method may be copied into multiple
subclasses. You can also consider Parameterize Method as a
combination of Add Parameter where you make the
methods behavior dependent on the parameter, and then
extract method where you extract the now-common code
between the methods.
VI. CONCLUSION
In conclusion, I have shown what refactoring is, why
refactoring is a good thing to do, as well as some of the most
common types of refactoring that are commonly performed.
Leave with this thought: Refactor as much as possible, but
only do so if it leads to greater simplicity and elegance. If it
doesnt, youve either refactored incorrectly, or you need to
do it more
REFERENCES
1.
2.
3.
M. Fowler. (2000) Refactoring. [Online].
Available: http://
refactoring.com
R. Callon. (1996) The Twelve Networking Truths. [Online].
Available: https://tools.ietf.org/html/rfc1925"
M. Fowler. (2000) Catalog of Refactorings. [Online]. Available:
http://refactoring.com/catalog/