Refactoring???

  • Thread starter Thread starter Frank Rizzo
  • Start date Start date
F

Frank Rizzo

I keep hearing this term thrown around. What does it mean in the
context of code? Can someone provide a definition and example using
concrete code?

Thanks.
 
Frank Rizzo said:
I keep hearing this term thrown around. What does it mean in the
context of code? Can someone provide a definition and example using
concrete code?

Thanks.

Refactoring can be defined as "improving the design of existing code". It's
a kind of glorified "code tidying" exersise. There are many tasks you can
perform on some code to improve it, and Martin Fowlers "Refactoring" book
walks through many of them. Refactorings can range from extremely simple or
extremely complex. A simple one is called "Rename Method", which involves
changing the name of a method so that the purpose of the method is revealed
by the name.

function getttlordval(){ ... }

becomes

function getTotalOrderValue(){ ... }

There are loads of them explained in the refactoring book, which is a great
read and teaches some nifty techniques IMHO.

Hope this helps,

Tobin
 
Tobin said:
Refactoring can be defined as "improving the design of existing code". It's
a kind of glorified "code tidying" exersise. There are many tasks you can
perform on some code to improve it, and Martin Fowlers "Refactoring" book
walks through many of them. Refactorings can range from extremely simple or
extremely complex. A simple one is called "Rename Method", which involves
changing the name of a method so that the purpose of the method is revealed
by the name.

function getttlordval(){ ... }

becomes

function getTotalOrderValue(){ ... }

There are loads of them explained in the refactoring book, which is a great
read and teaches some nifty techniques IMHO.

Sounds like a fancy name for something people have been doing since
assembly code. Or am I oversimplifying it?
 
Frank Rizzo said:
Sounds like a fancy name for something people have been doing since
assembly code. Or am I oversimplifying it?

A bit. There are two sides to refactoring: working out what you want to
do (e.g. renaming a method) and doing it (renaming the method and
fixing up all the calls to it). The latter part is the one which is
relatively recent in terms of IDEs - it's been common in the last few
years in Java IDEs, and makes things *much* easier.

For instance, in Eclipse if I rename a class, it finds all the places
where that class is used and renames them. It can alter comments for
you if you want to. It then renames the file as well - basically
everything you'd want to do to rename the class and keep everything
tidy.

This means you don't have to concentrate on getting things like names
right to start with, and that you can *confidently* do things like
extracting part of one method to be a separate method in its own right,
called from the original one.

I was quite surprised when VS.NET 2002 didn't have it, and very
surprised when VS.NET 2003 didn't. Fortunately I gather Whidbey will
have it.
 
Sounds like a fancy name for something people have been
doing since assembly code. Or am I oversimplifying it?

In essence, yes - all you are doing is taking code and cleaning it up so
that it may become:

* More understandable, hence more maintainable
* Possibly more resuable
* Possibly more efficient

The cleaning up, of course, may involve many things from adopting a
different, perhaps more meaningful or uniform naming convention, breaking
up 'public' methods into sets of smaller methods, or adding new methods [say
'private' helper methods that might be reused in several methods], through
to breaking up a class into several smaller, closely co-operating classes,
or maybe more conforming to one or more of the well-known 'design patterns'.

It should be noted, also, that the original code does not necessarily have
to be 'crappy' or otherwise poor or deficient in order to be refactored
[although such code will probably exhibit more dramatic improvements
(depending on what is being measured) from such activities].

The dividing line between refactoring and redesign hinges, I believe, on
whether user requirements have changed. Thus, any later code refinement that
did not involve changes directly attributable to new or altered user
requirements could probably be classed as refactoring.

Anyway, a very simple [and contrived] refactoring example follows. Here, we
have a 'SalesReport' class which is used [surprise, surprise] to print a
report [it is assumed the relevant raw data is made available, either via
the constructor, or some sort of data lookup method]:

class SalesReport
{
...
public void PrintReport()
{
Console.Writeline("...<Header>...");
Console.Writeline("...<Detail Line>...");
Console.Writeline("...<Detail Line>...");
Console.Writeline("...<Detail Line>...");
...
Console.Writeline("...<Header>...");
}
...
}

To print a report we invoke the 'PrintReport' method of a suitable object
instance:

aSalesReport.PrintReport();

Easy !

There are, however, two problems with the current design:

* The report destination [the console] is hardcoded, making
it difficult to send the report output elsewhere like a
file, or printer [yes we could redirect console output, but
the design, as is, is limited]

* It is not possible to extract the various report sub-sections
[i.e. header, detail lines, footer, etc] making it impossible
to alter their formatting, or printing order. At present, there
is a single report format

An initial refactoring of this class might see the report destination
generalised. So, instead of generating output via:

Console.WriteLine()

we might consider passing a reference to a 'StreamWriter' instance so that
output could be easily redirected. The intial refactoring might, therefore,
look like this:

public void PrintReport(StreamWriter sw)
{
...
sw.WriteLine("...<Header>...");
...
...
}

In one, relatively small, and simple step, you have improved the utility of
this class by making it more general-purpose. Note, though, that the basic
functionality of the class has not been altered but been retained - the
altered code can simply do a little more than before.

The class can be further improved by replacing each hardcoded print step,
such as:

sw.WriteLine("...<Header>...");

with a method that performs that task. So, for example, we might be able to
replace the 'printReport' version above with:

public void PrintReport(StreamWriter sw)
{
printHeader(sw);
printDetails(sw);
printFooter(sw);
}

These new methods could be implemented as 'private' helper methods. Now, in
making these changes, we have not added any functionality but simply better
compartmentalised code so that any future additions / changes might be
easier to make. For example, it should now be easier for a maintenance
programmer to find, and alter the header code, and there is less danger of
such maintenance impacting on other parts of the class.

A related refactoring might involve the simple step of making these new
methods [i.e. 'printHeader' etc] into 'public' methods. This single step
would, quite significantly, improve the usefulness of this class by making
it far more general purpose: clients can now use the individual parts of the
report, and have the opportunity of overriding these methods. It is worth
mentioning, though, that *this* particular refactoring really stradles the
fence between code improvement and design change, and may, perhaps, be
considered by some as going a little too far.

Well, there you have it - a simple refactoring example, one that has at
least help clear the mystery a little. Reading Martin Fowler's 'Refactoring'
is *most* enligthening, and very highly recommended.

I hope this helps.

Anthony Borla
 
Sounds like a fancy name for something people have been doing since
assembly code. Or am I oversimplifying it?

Except most programmers don't actually do it and continue to let code rot by
letting method sizes get out of hand and using names that don't describe
anything other than the programmers desire to save keystrokes (to name just
two code smells that can be remedied by refactoring).

You are oversimplifying it though. What Fowler does in his book is shows
detailed steps for each refactoring - where after each small step you still
have a working system. Instead of going in one big leap from the code's
starting point to its ending point, where nothing is working during the
leap, he shows us how to transform the code in a series of small steps where
the code continues to work after each step.

The book is a great read.
 
These new methods could be implemented as 'private' helper methods. Now, in
making these changes, we have not added any functionality but simply better
compartmentalised code so that any future additions / changes might be
easier to make.

Indeed, this is a very important part of refactoring - it shouldn't
change behaviour *at all*. (Okay, I guess some very small performance
changes due to changed levels of indirection etc are okay, but not
functional changes.) Even bug fixing shouldn't be done as part of
refactoring - it should just make it easier to fix the bugs after the
refactoring is complete.
 
Tobin said:
Martin
Fowlers "Refactoring" book walks through many of them.

Is this the "Refactoring" book to which you refer?

http://www.bookpool.com/.x/r3shgdther/sm/0201485672

--
Reginald Blue
"I have always wished that my computer would be as easy to use as my
telephone. My wish has come true. I no longer know how to use my
telephone."
- Bjarne Stroustrup (originator of C++) [quoted at the 2003
International Conference on Intelligent User Interfaces]
 
Back
Top