For as long as I can remember programming, I have always avoided the break and continue keywords in my loops. Before I explain why I avoid them, I want to explain what they are. Here’s an example:
1 2 3 4 5 6 7 8 |
while (someCondition) { if (someOtherCondition) { doSomeLogic(); continue; //jump to the top of the loop } doSomeOtherLogic(); break; //exit the loop } |
A continue will jump to the top of the loop and reevaluate the condition. A break will exit the loop.
What I don’t like about these keywords is that when you want to refactor this code, the continue s and break s step on your toes. Here’s an animated GIF demonstrating why that is:
What I tried to do here is take the contents inside the loop and put them in their own method. As you can see, the editor I’m using is unable to automatically do that. This adds inertia when you decide that you should refactor this code: Now I have to think harder than I’d have to if I wrote it without the continue s and break s.
It also adds more risk. Because I can’t automate the process, I have to do it by hand. This increases the odds that I’ll introduce a bug along the way. Having my editor automate the process eliminates this risk.
It would be better if the original loop looked like this:
1 2 3 4 5 6 7 8 |
while (someCondition) { if (someOtherCondition) { doSomeLogic(); } else { doSomeOtherLogic(); return; //exit the loop } } |
This way, you can extract the body if you need to:
Notice the return keyword that’s there. That’s the icing on the cake: It limits the logic you can have after the loop if you want it to exit it early. This forces you to keep your method smaller than you would have to if you used a break . Smaller methods are more maintainable because they’re easier to digest. To put it another way, the return makes you have to use discipline but the break lets you be sloppy.
For example, it turns a method that looks like this:
1 2 3 4 5 6 7 8 |
preLoopLogic(); while (someCondition) { loopLogic(); ... //imagine hundreds of lines //oh man, I wish I could exit the loop here and then run the postLoopLogic(), //but a "return" would skip postLoopLogic(). How can I do this without using "break"? } postLoopLogic(); |
Into a method that looks like this:
1 2 3 |
preLoopLogic(); loopAndLogic(); //now it's 1 line postLoopLogic(); |
In summary, avoid continue s and break s in your loops because your code will be easier to refactor later and it encourages smaller methods.