Here is some timeless advice on debugging software from Sir Arthur Conan Doyle’s fictional detective Sherlock Holmes.
“There is nothing as deceptive as an obvious fact”
“It has long been an axiom of mine that the little things are infinitely the most important”
“It is a capital mistake to theorize before one has data.”
“When you have eliminated the impossible, whatever remains, however improbable, must be the truth.”
In full disclosure, I am not the clever person who noticed this wisdom applies to software development. I got these quotes from Robert Bermani, with whom I was privileged to work while at Continuum Innovation. His email credited it to someone named Peter Simpson. I do not know if the email chain goes further back.
I received it in 2012 and I re-read it about once a year along with other thoughts on programming. They are useful thoughts to remember when debugging code.
Another piece of good advice can be found in the following famous quote.
"It ain’t what you don’t know that gets you into trouble. It’s what you know for sure that just ain’t so."
This wisdom is often credited to Mark Twain, but I have seen internet commentary to suggest it is older. I really don’t know, but I suspect it was first declared in anguish by a programmer.
So I have some specific suggestions gleaned from the above advice and some hard-earned experience when such advice was forgotten.
- Be careful of passed parameters. Always add code to public functions to verify passed parameters. (You should not trust function calls from other modules.) If parameters in static functions are not checked, note that in comments.
— “It’s what you know for sure that just ain’t so.”
- Variable names can be deceptive and can lead to misunderstandings. Make sure your variable names are descriptive and properly suggestive. It is usually worthwhile to spend a few minutes reviewing names before a module is released. Always modify variable names when the use has changed. Never re-use a variable for a second purpose and never re-use a variable name in a module for a similar but different purpose.
— “There is nothing as deceptive as an obvious fact.”
- When debugging loops, most programmers check the first pass through the loop, but the last pass is often assumed to work. The “little things” like final values for array indexing and modified pointers also need to be checked for correctness.
- Also when you are debugging loops, check the loop exit variables; thinking you know how many times the loop has repeated is not the same as knowing.
- Always add code to check the return values from library functions. Try to avoid the embarrassment of ignoring that small detail of the library function returning an error code.
Lastly, always remember that in the virtual universe in which software executes almost nothing is impossible. I’ve spent way too many extended hours searching for software faults in the wrong place because somebody (or me) waved it away while confidently stating “Oh, that can’t possibly happen!”