Last week I published a blog offering some debugging tips for beginners. This week I want to expand on that topic, and provide something of value to at least an intermediate developer.
Of course, the matter now gets exponentially trickier because the more skilled a developer, the more language- or case-specific the advice must get before it can be useful.
Thus, rather than committing to 20 articles dedicated to 20 programming languages, I’ll focus on sharing some very general tips which also seem rather counter-intuitive. Depending on your level, I hope that at least one of these will be new to you.
#1 – Look for coincidences
When and where is your bug manifesting itself? Is it appearing exactly every 49 minutes, and if so, what other parts of your program run on a similar cycle? Or is it happening only when working on specific devices, and in that case, what is it that differentiates these devices?
When looking for coincidences, you should really think outside the box. If you can’t find the bug no matter how hard you look in your code, then odds are, the bug may not be in your code at all. One of our instructors once told me of a boss who complained that blue-screen errors would appear when he worked on his account, but only when he was inside his office. It turned out that when adjusting things in that space he had placed the computer’s processor next to the heater, so it would overheat within the half-hour of being used.
No matter how odd the coincidence may appear, look into it. If your program malfunctions every time your mother calls you, it’s probably time to find out what’s up with mum.
#2 – Check the hardware
This is related but not reducible to the above point, as trouble with your hardware can result in glitches in your system which can easily be mistaken for bugs. Unfortunately, there won’t be always be a telling “coincidence” to reveal these for you.
The way to test for hardware malfunctions is not entirely dissimilar to the way to test software, except of course it’s done physically. Run the program on a different computer, on a different hard drive, on a different power outlet, one at a time. Test everything this way down to the computer’s cables. Sometimes the bug vanishes when one of these components is replaced. Other times it doesn’t, in which case, at the very least you’ll know for certain the problem is in the software.
#3 – Ignore the error message
By and large, as I argued in my previous article, error messages are a blessing that will point you towards a solution. For some of the more complex bugs, however, they may be misleading – and there may well be more than one such messages resulting from the same bug. While I would not recommend this as a starting point, in some cases it may be advisable to set the error messages aside and approach your code from a different perspective.
This holds true even when there isn’t an error message but only an error. Some of the most obvious clues offered by your bug may be dead ends. Experiment with pushing them out of your focus, and thinking of ways to approach your problem that does not involve them.
#4 – Do not go the extra mile
You may be determined to get the bug ‘out of the way’, and so you’ll stay in the office as long as you have to until that’s done.
That is a surefire way to not solve the problem.
The longer you overwork, the more stressed and tired you get, and the more your productivity falls, along with your ability to find and understand bugs. You are also exposing yourself to burnout.
Instead, take a break. Or at least work on something different for a while. Get a good night’s sleep. Refreshing your mind will always be much more productive than overheating it, and this doesn’t just apply to debugging.
#5 – Scrap your achievements
Or at least consider scrapping them. One of the debugging methods that is most guaranteed to give results – if undeniably the most painful – is to simply erase the code and start again.
This leads to another important discussion which we don’t really have the space to appropriately delve into here, namely version control. It goes without saying that you should be saving updated versions of your files on GitHub all the time, so if something goes wrong, you can delete only the parts you developed subsequently to the appearance of the error. This helps with the ‘economy’ of debugging, but don’t lose sight of the general principle – that your efforts to preserve work already done may involve more actual work than just redoing it from scratch.
Of course, it is extremely hard to make an assessment of when an attempt to resolve a bug will take longer than rewriting the entire method that was causing it (or at least, it’s hard to do so in time). But when that does happen, it’s often because the developer never stopped to think “I’ve spent 3 hours trying to get rid of a bug in a piece of code that took me 1 hour to write – maybe I should just start again?”
Coding is about using your head, not about banging it against the wall. If the worse comes to the worst, then it’s time to make a difficult decision and, if necessary, kill your darlings.