This is not a challenge so much as a new (to me) way of looking at refactoring. As always, complete in your language of choice. First, some background:
The ruby example below maximizes simplicity at the expense of flexibility.
class Bottles
def sing
verses(99, 0)
end
def verses(upper_bound, lower_bound)
upper_bound.downto(lower_bound).map {|n| verse(n) + "\n"}.join
end
def verse(number)
case number
when 0
"No more bottles of beer on the wall, no more bottles of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall.\n"
when 1
"1 bottle of beer on the wall, 1 bottle of beer.\nTake it down and pass it around, no more bottles of beer on the wall.\n"
when 2
"2 bottles of beer on the wall, 2 bottles of beer.\nTake one down and pass it around, 1 bottle of beer on the wall.\n"
else
"#{number} bottles of beer on the wall, #{number} bottles of beer.\nTake one down and pass it around, #{number-1} bottles of beer on the wall.\n"
end
end
end
We have a change request, though. When there are 6 bottles of beer left, we will need to display "1 six pack" instead of "6 bottles" in the song. The challenge is not to implement this change yet. We're going to Kent Beck this shit up.
for each desired change, make the change easy (warning: this may be hard), then make the easy change
— Kent Beck (@KentBeck) September 25, 2012
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
https://twitter.com/KentBeck/status/250733358307500032
Ultimately we want to make the Bottles
class open closed to the type of change that would allow us to arbitrarily say 1 six pack instead of 6 bottles. (I had to ask what open closed meant in this context in class.) Open closed here means open to the change but closed to modification. That's going to be too much for a single refactor in the style I'm about to describe so please allow me to enumerate what I would like for the next submission.
###Challenge Goal
- No hard coded strings left in the
verse
method.
###Refactor Under Green Restrictions
- Tests may never go red.
- Tests must be run at every file save.
- Try to save every time you make a change. Only change 2+ "things" without saving if you're stuck.
- If your tests go red, hit undo until they're back to green.
###The Refactor Under Green Process
- Look for similar structures.
- Look for the smallest possible change that can be made to make them look more similar.
- Change your system so making that change is easy. (Almost always additive. Tests can't go red, right?)
- Make the easy change.
- Delete dead code.
Setting aside for a moment the argument that the change would only require 2 additional special cases... Here's my refactor.