A key skill for any software developer is finding and fixing problems. Sooner or later, every developer runs into a bug that's hard to find and fix. These bugs often behave in ways the code you're reviewing seems to rule out.
To fix a problem like this, you first have to reproduce it. Then you isolate it, which means reviewing and testing every line of code in the execution path and noting how the application's state changes. Finding these problems is usually a process of elimination. You examine each line in the execution path and test its assumptions so you can rule it out as the source. Even the most harmless-looking code has to be analyzed and tested. Sooner or later you isolate the problem. As I like to say, once you eliminate every potential cause, the only thing left is the actual problem. When I face a bug like this, I literally eliminate every possible cause, testing even the most harmless-looking code if only to rule it out for certain. In the end, what solves these problems is usually the ability to stay with them and work a detailed, methodical process.
Remember that the problem could be in the application's configuration, which makes configuration the easiest place to start. Make sure the application is configured exactly as expected, and if you're not sure, find out. A configuration fix often means no code change, and so usually no software release. Next, move on to the low-hanging code: code you can rule out quickly with a few tests. By now you may have a gut feeling about the cause. In my experience you should always follow your gut. More often than not it's right, and you can go straight to the problem and cut a long analysis short. Sometimes you'll need to establish some facts before you can confirm your instinct. For example, you may suspect the problem is in a specific method, and that the method's code is correct as long as its variables hold the expected state. To confirm that, you may need to trace all the code in the execution path that acts on that state.
Another step I recommend, and one many developers resist, is talking to another developer, preferably someone with in-depth knowledge of the affected part of the application. I know it sounds obvious, but I've often seen developers agree that bringing someone in would help and then spin on the problem for days without doing it. It's probably a developer's natural impulse at work: we want to solve the puzzle. Still, the best thing for the business is to use the people who may have an easy answer. I've seen developers work on a problem for a week, finally reach out, and have another developer fix it in 10 minutes. Even a developer who doesn't know the code can help. Talking the problem through often leads you to the answer on your own, or the other developer asks questions that lead you down a path you hadn't considered.
Once you've isolated the problem, you can fix it. That's often harder than expected and takes great care. A change that fixes your problem can make a different part of the application fail, and you can end up trading your bug for a more serious one. Test your fix thoroughly, and regression test the application to make sure you haven't broken something else.
Troubleshooting skills are essential to effective software development. A methodical approach will help you isolate and fix even the most difficult problems. Remember to:
- Reproduce the problem
- Isolate the problem
- Validate the configuration
- Rule out every potential cause along the execution path
- Talk it through with another developer
- Thoroughly test every code change you make
First published on termondt.com around 2019. Revised October 2026.