impossible to reuse any of the behavior of the current statement method for an HTML statement.
Your only recourse is to write a whole new method that duplicates much of the behavior of
statement. Now, of course, this is not too onerous. You can just copy the statement method and
make whatever changes you need.
But what happens when the charging rules change? You have to fix both statement and
htmlStatement and ensure the fixes are consistent. The problem with copying and pasting
code comes when you have to change it later. If you are writing a program that you don't expect
to change, then cut and paste is fine. If the program is long lived and likely to change, then cut
and paste is a menace.
This brings me to a second change. The users want to make changes to the way they classify
movies, but they haven't yet decided on the change they are going to make. They have a number
of changes in mind. These changes will affect both the way renters are charged for movies and
the way that frequent renter points are calculated. As an experienced developer you are sure that
whatever scheme users come up with, the only guarantee you're going to have is that they will
change it again within six months.
The statement method is where the changes have to be made to deal with changes in
classification and charging rules. If, however, we copy the statement to an HTML statement, we
need to ensure that any changes are completely consistent. Furthermore, as the rules grow in
complexity it's going to be harder to figure out where to make the changes and harder to make
them without making a mistake.
You may be tempted to make the fewest possible changes to the program; after all, it works fine.
Remember the old engineering adage: "if it ain't broke, don't fix it." The program may not be
broken, but it does hurt. It is making your life more difficult because you find it hard to make the
changes your users want. This is where refactoring comes in.
Tip
When you find you have to add a feature to a program, and the program's code is not
structured in a convenient way to add the feature, first refactor the program to make it
easy to add the feature, then add the feature.
The First Step in Refactoring
Whenever I do refactoring, the first step is always the same. I need to build a solid set of tests for
that section of code. The tests are essential because even though I follow refactorings structured
to avoid most of the opportunities for introducing bugs, I'm still human and still make mistakes.
Thus I need solid tests.
Because the statement result produces a string, I create a few customers, give each customer a
few rentals of various kinds of films, and generate the statement strings. I then do a string
comparison between the new string and some reference strings that I have hand checked. I set
up all of these tests so I can run them from one Java command on the command line. The tests
take only a few seconds to run, and as you will see, I run them often.
An important part of the tests is the way they report their results. They either say "OK," meaning
that all the strings are identical to the reference strings, or they print a list of failures: lines that
turned out differently. The tests are thus self-checking. It is vital to make tests self-checking. If
you don't, you end up spending time hand checking some numbers from the test against some
numbers of a desk pad, and that slows you down.