Refactoring
Refactoring
Refactoring is the process of restructuring code, while not changing its original
functionality. The goal of refactoring is to improve internal code by making
many small changes without altering the code's external behavior.
Reasons to Refactor:
1) Code is duplicated:
If your code is duplicated, whenever you have to make changes in one place,
you have to make parallel changes in another place.
Specific Refactorings:
Data Level Refactorings:
Replace a magic number with a named constant
If you’re using a numeric or string literal like 3.14, replace that literal with a
named constant like PI.
Rename a variable with a clearer or more informative name
If a variable’s name isn’t clear, change it to a better name.
Move an expression inline
Replace an intermediate variable that was assigned the result of an expression
with the expression itself.
Replace an expression with a routine
Replace an expression with a routine (usually so that the expression isn’t
duplicated in the code).
Introduce an intermediate variable
Assign an expression to an intermediate variable whose name summarizes the
purpose of the expression.
Convert a multi-use variable to multiple single-use variables
If a variable is used for more than one purpose, create separate variables for
each usage.
Take code from a routine whose body is simple and self-explanatory, and move
that routine's code inline where it is used.
If a routine is too long, sometimes turning it into a class and then further
factoring the former routine into multiple routines will improve readability.
Add a parameter
If a routine needs more information from its caller, add a parameter so that
that information can be provided.
Remove a parameter
If a routine no longer uses a parameter, remove it.
If two subclasses have similar code, combine that code and move it into the
superclass.
If a class has two or more distinct areas of responsibility, break the class into
multiple classes, each of which has a clearly defined responsibility.
Eliminate a class
If a class isn’t doing very much, move its code into other classes that are more
cohesive and eliminate the class.
If Class A calls B, and Class B calls Class C, sometimes it works better to have
Class A call Class C directly.
If member data is public, change the member data to private and expose the
member data’s value through a routine instead.
If you have two classes that need to use each other’s features, but only one
class can know about the other class, then change the classes so that they both
know about each other.
If you have two classes that know about each other’s features, but only one
class that really needs to know about the other, change the classes so that one
knows about the other, but not vice versa.
Depending on your error-handling strategy, make sure the code is using the
standard approach.
Refactoring Safely:
Save the code you start with — Before you begin refactoring, make sure
you can get back to the code you started with.
Keep refactorings small — Keep the refactorings small so that you fully
understand all the impacts of the changes you make.
Do refactorings one at a time — Do the refactorings one at a time,
recompile, and retest, then do the next refactoring.
Make a list of steps you intend to take — Making a list helps you keep
each change in context.
Make frequent checkpoints — Save checkpoints at various steps in a
refactoring session so that you can get back to a working program if you
code yourself into a dead end.
Use your compiler warnings — Setting your compiler to the pickiest
warning level possible will help catch many errors almost as soon as you
type them.
Add test cases — In addition to retesting with your old tests, add new
unit tests to exercise the new code.
Refactoring Strategies:
Refactor when you add a routine:
When you add a routine, check whether related routines are well organized. If
not, refactor them.
Adding a class often brings issues with existing code so it’s better to refactor
when you add a class.
Use the understanding you gain from fixing a bug to improve other code that
might be prone to similar defects.
Code that is never modified doesn’t need to be refactored. But when you do
touch a section of code, be sure you leave it better than you found it.