A systematic approach to Debugging
During the last 6 years of web developing experience, I’ve dealt with a variety of issues. At some point, I realised that my approach to debugging evolved which helped me deal with bugs in a more efficient way. I would like to share this with you, and I will be more than happy if you implement any of these in your daily debugging routine.
Gather information
- The very first thing you should define is what is the expected behavior versus what is the actual behavior. The expected behavior is for example when you fill out a form and hit a button, you should get a green success message and specific data will be consequently stored in the database. Actual behavior is when you get a red message and when data is not stored in the database.
- Search for error messages on google or a StackOverflow, because it will help you find a solution or idea about what you can check in your codebase. If you can’t find any results on Google then search your own codebase and you’ll see exactly where that exception was thrown, which class and which line in that class it affected. You can go right in there and figure out what’s going on.
- Stack trace shows you the exact path of execution that your code took.
It will show you which error was thrown down from which function which class. Then you can visualize in your head what path did the execution take through the code and why was this exception thrown.
- Date & time can be very helpful. In some cases, you can conclude the reason for bug just judging by the time of error occurrence.
- Log entries are something you should always have in mind. You can find crucial information about your bug there.
Replicate the issue
You really want to be a 100% sure that the steps you’ve identified to replicate the issue, will, in fact, make that issue occur again. Let’s assume that you aren’t able to put together an exact description and steps of how to replicate the issue.
Let’s say you put together three steps which replicate the issue in only 50% of the cases, meaning, you will be able to have a bug-free code only half of the time (by some inexplicable magic). Then when you go to resolve the issue and retest later, you will not be able to determine whether things are working because you fixed them or because it was that other half of the time, when things just magically work.
You won’t really know unless you’re able to replicate the issue with 100% certainty!
Identify the culprit
You want to be really methodical on how you go look for that culprit. You want to assure that you’re not making any faulty assumptions. You should not be assuming that part of a codebase is working fine or that system that’s been working fine for years has no problems. Don’t make any assumptions. Challenge everything and when you find a bug try to understand it . Understand the fundamental nature of that bug. Why is it behaving in this way? Why is it affecting these systems and not some other ones? Why is the bug doing what it’s doing?
Fix it & retest
When you’ve identified the culprit you can go ahead and fix that issue. Once you fix the issue – retest. Go through those replication steps again and see if you’re able to replicate the issue. And you do try and put a solution in place.
Do not import any temporary workarounds because they can
- add technical debt
- they could introduce other issues
- quite often they never get replaced with a solid permanent solution
Mitigate future occurrences
If you’re doing test-driven development (TDD) add an automated test. If not, that’s fine too. You can add automated tests after and that’s totally ok.
But mitigating future occurrences goes beyond just adding automated tests.
It also means preventing other people or helping other people prevent those same kinds of issues occurring again.
Wrapping Up
By using this five-step process you will probably see some great long-term results.
You will get a lot of experience with the different tools that you will use and with the different code bases you will work on.
You will learn how different frameworks work, not because you’ll write the code itself, not because you’ll contribute to it but because you’ll debug it. So you’ll have a good idea about what’s going on there.
You’ll also be able to build up a mental library so that when you see an issue that intuition just immediately clicks and says yep that’s that kind of issue, that’s a networking issue, that’s a race condition, that’s permissions issue.
Your mind will immediately jump to your previous experience and you would not have to waste any time looking at other false scenarios.
And perhaps most important aspect is that having a solid process like this will boost your confidence.