Sunday, October 1, 2017

Ready, Fire, Aim!

Debugging Isn't Guesswork

I had a recent encounter with a team member that reignited a continuing source of aggravation for me when dealing with less assiduous developers. We were pair-programming, attempting to debug some VBA code that the other person had written. I was at the keyboard with my counterpart looking over my shoulder, offering advice.
"You know what it might be, it might be <insert random code location here>."
"Oh wait, I know what it is. It's <insert random code location here>."
"Hmmm. Take a look at <insert random code location here>."
Let's set aside the fact that it was incredibly frustrating to jump from spot to spot in code that I'm unfamiliar with, while simultaneously trying to understand the overall logic, but none of the suggestions panned out. Which led me to growl (at a less than acceptable volume),
"Let's stop guessing and do the damned analysis." (I'm not always known for my tact.)
To me, that's what debugging is - analysis. But I see far too many developers, including some of the most experienced, that view debugging as total guesswork. It's the coding equivalent of throwing dung against a wall to see what sticks. And here's the real danger with that approach. Sometimes, your random guess appears to have corrected the problem, but actually hasn't. Because you didn't analyze and determine the exact cause, you may have just masked the original defect with another defect.
Please stop debugging via guesswork. Please.

Aim, Then Fire

My recommendation is to Identify-Locate-Kill:
  1. Identify and focus on what you're trying to achieve. This sounds straightforward, but we often lose sight of the goal. While searching for an off-by-one defect, have you found several other unrelated issues and then gotten sidetracked correcting them? Stay focused on the original intent. Make note of the other issues and come back to them later. Sometimes, an informed guess by someone that knows the code can lead you to the general area, where you can begin your analysis, but don't just blindly assume that this is definitively the location of the defect.
  2. Use analysis to locate the precise location of the defect. This is the crucial step. Don't skip past performing a step-by-step trace of the code to watch the values of variables and check the order of code execution. Modern debugging tools make this far simpler than when I first started coding, way back in the mists of time. However, sometimes the act of attempting to observe an issue makes the issue difficult to duplicate. In these situations don't forget the power of simple logging statements in code - sometimes it's the only way to locate a gnarly defect.
  3. Kill the bug with a well considered correction. This can take several forms. Sometimes it's a deletion of code, rather than an addition. Sometimes it a re-ordering of a few lines. And in other situations, you need a complete code refactor. Discuss the approach with other developers that you trust, preferably ones that know the codebase, to ensure that your correction doesn't have repercussions. Test your modifications by hand to ensure minimum viable correct operation.
Not indicated here is the need for overall application testing to ensure no regressions have been introduced. However, I don't consider that part of debugging - unit tests should be a regular, repeating step in your development cycle.

I Can Get Some...Satisfaction

A lot of developers groan at the thought of debugging, especially correcting someone else's code. While I also prefer the pleasure of greenfield development, debugging is unavoidable. And when I know I've located and positively corrected a code defect, I experience a profound sense of satisfaction. Part of that is because debugging is hard. It can be considerably more difficult than coding a new application or feature, especially if you're trying to decipher some other developer's thought process - or lack thereof.
So please, analyze, don't guess.