“Puts”, my best friend & my enemy

I have recently be working on some refactoring katas. These katas have ever so slightly blown my mind. A reason for one of these explosions is that I’m really scrutinising someone else’s code and I always find this very challenging. It’s even harder in this case because in these katas the code is deliberately repetitive, hard to understand and, in all honestly, hard to digest.

I have been using some very cool katas by Emily Blanche and I will be referring to her Tennis kata for my code example below.

I was trying to replace the very repetitive if statement below:

p1result = ""    
p2result = ""
if (@p1points > 0 and @p2points==0) 

if (@p1points==1)
p1result = "Fifteen"
end
if (@p1points==2)
p1result = "Thirty"
end
if (@p1points==3)
p1result = "Forty"
end

p2result = "Love"
result = p1result + "-" + p2result
end

I wanted to replace all three of the nested if statements with a call to the get_points method I had created.

def get_points(player_points)
score = {
0 => "Love",
1 => "Fifteen",
2 => "Thirty",
3 => "Forty"
}
score[players_points]
end

Unfortunately, every time I got rid of the if statement and replaced it with one simple call to the method:

if (@p1points > 0 and @p2points==0)
p1result = get_points(@p1points)
p2result = "Love"
result = p1result + "-" + p2result
end

I kept getting the same message:

TypeError: no implicit conversion of nil into String

This was very frustrating, I had used puts on my get_points method and in different parts of my code and the method seemed to be returning the values I wanted.

def get_points(players_points)
score = {
0 => "Love",
1 => "Fifteen",
2 => "Thirty",
3 => "Forty"
}
puts score[players_points]
end

However, as you may know, puts prints a value to the command line but then it returns nil. So, though I saw nil was being returned as the last value of my method, I thought it was just the puts returning nil.

What I should have done from the start was to use puts to see what values were being caught by my if condition and then see what they were returned as from the method.

if (@p1points > 0 and @p2points==0) 
puts @p1points # Putting my puts here would have been handy!
puts @p2points

p1result = get_points(@p1points)
p2result = "Love"
result = p1result + "-" + p2result
end

Once I used puts on each player’s points, I realised that before, the nested if conditions in the if statement were only being called on values 1–3. When I removed the conditions, it was allowing 4 to be passed is as the argument to my get_points method and to enter my hash. However, my hash couldn’t handle 4. Thus, nil was being returned.

What I needed all along was a simple tweak so my if condition didn’t allow 4 to enter my hash and suddenly everything worked as I thought it should and I was able to do the refactoring I wanted to.

This was the final result:

if (@p1points > 0 && @p1points <= 3 && @p2points==0)      
p1result = get_points(@p1points)
p2result = "Love"
result = get_player_score(p1result, p2result)
end

I feel like this is a great example of false assumption. Even though in theory the code was doing what I thought, the values being passed in were not were not what I was expecting. In the future, I’ll try to look at the problem starting at the root of the method instead of diving into the leafier part.