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