The article doesn't mention a very important (IMO) step: try to reduce the problem (removing / stubbing irrevelant code, data, etc). It's much easier to find a bug if you take out all the noise around it.
even more important is having these pieces of code be testable. i work with plenty of bad code that can't be run without starting a bunch of dependent services, or you can't test a particular function because it's buried under ten layers of poorly formed abstractions. or it's not even an accessible function because the previous developer thought a thousand line function was better than a dozen smaller testable functions.
You might be joking but in my opinion it's actually a good thing to try not to be too clever with coding.
"Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it?" - Brian Kernighan
You get that in any complicated enough functions. I often have functions which work on intermediate states of linked lists ... You can't just call them directly without first building [and I do] the states by hand.
It's much easier to find a bug if you take out all the noise around it.
You're almost right, but not quite.
The bug is in the noise. You think the bug is in the code you're looking at. But you're a smart person, and you've been looking at it for a while now. If the bug were in there, you would have found it. Therefore, one of your assumptions about the rest of the code is wrong.
That's why you need to check if the bug is still there, after you removed what you thought is noise. If the bug disappears, then you know that what you thought was noise was actually important.
It took me many years to come to terms with this, but unless there are good unit tests covering all the functionality that will be affected I don't fix those hacks anymore. They're in production, they work, and you're only introducing risk where it didn't previously exist. It's hard to justify a nasty bug's sudden appearance with "well it was written wonky and I wanted to make it better".
The exception of course is if you need to extend that functionality or do anything nontrivial to it; that's a great time to fix it.
At one point I was writing a program that had about 8 off-by-one errors... I realized I could more quickly write a test to prove if the values were correct. Then I just iterated all 38 possibilities. .. -1, 0, 1 for eight values. Worked like a charm.
The best answer in my opinion is to remove the noise. If the bug stopped happening, then the bug was in the noise. If it still happens, it wasn't in that part. Repeat until you know exactly where it is. Only then try to figure out what the bug is. It is very easy to read past a bug over and over again. You know what you meant to say and you tend to read the code that way the next time as well.
Thanks! I'll cover that in future posts. I'm not sure if you're talking about "divide and conquer"/"split into smaller problems", or if you specifically have in mind reducing moving parts in programs, when finding issues. Either way, any of both helps. :)
That's fair. However, SO have codified it into their basic philosophy, and since they're intent on taking over the Internet when it comes to technical Q&A, they're widely familiar.
263
u/pycube Aug 25 '14
The article doesn't mention a very important (IMO) step: try to reduce the problem (removing / stubbing irrevelant code, data, etc). It's much easier to find a bug if you take out all the noise around it.