I was trying to fix a bug a few days ago and my initial fix involved nested loops. The code pulled some random values out of a list and added them to another list (creating wrong answers for a multiple choice question). I of course forgot to check for duplicate values, introducing a bug. The humbling thing about software development is that I still routinely make mistakes like this after ten years of getting paid to write software.
Anyway, I went to fix the bug, and so I just put another loop inside the loop that added the answers to the list which made sure that the value I picked wasn’t already assigned to an answer I had added. If the value was already used, I just did this:
continue;
Guess whose fix didn’t work? This statement was applied to the inner loop that checked for duplicates rather than the outer loop that added answers to the list and the duplicate answer kept getting added as before. The next logical step was to use a label, so I could label the outer loop with something helpful like outer
and then change the statement above to:
continue outer;
This would work, but I don’t think it would add much in the way of clarity. Instead I added a method called hasAnswerWithValue()
to my Question
class and replaced the inner loop with:
if (question.hasAnswerWithValue(newAnswer)) { continue; }
I may even use the new method somewhere else at some point. In some cases, there’s no way to avoid the use of nested loops, but I’ve come to think that you should always do so whenever it’s practical.
In fact, I’m coming to think that “minimize the number of loops and conditional statements” is a good principle for programmers. That’s another post though, because that’s not what I did in this case. I just hid the loop in a method instead of nesting it.
July 31, 2006 at 4:38 pm
Hmm. I’m only reading Ruby books now, but doesn’t “has_value?()” already exist to check to see if a value already is in a hash?
July 31, 2006 at 11:02 pm
Finally you have a reason to envy PHP: in PHP, break and continue statements can accept an optional parameter to designate the number of nested loops to break or continue out of.
July 31, 2006 at 11:44 pm
Java has the same feature, that’s what labels are for.
July 31, 2006 at 11:45 pm
Yeah. The code in this case is Java code. You’d need a new method in this case because what I’m really checking is one property of an “answer” object, not the “answer” object itself.