As a developer sooner or later you will encounter bugs, be it small ones or production breaking bugs. Now it is your task to find and fix the bug as soon as possible. In this article I will list the techniques I learned over the course of many years debugging web applications in the hope that it will help you be better and more efficient in bug hunting.
1. Make the problem your own.
The process start with the actual bug report in a bug tracker. When reading the report, be careful for incomplete information or assumptions made by the reporter. It is easy to forget crucial steps in writing down the bug, so if possible, try to reproduce the bug with the reporter. Sometimes the bug report might contain possible causes to the bug. This happens more often if the reporter has a technical background. Be careful about trusting these assumptions made in the bug report since they are not always based on actual knowledge of the system, and it might create tunnel vision in finding the root cause.
2. Reproduce the bug
The first step in solving the bug is to reproduce it in your development environment. This way you have more options available to find the bug, for example, using a debugger. If possible, write a test that hits the bug. This way you have a lot of freedom in debugging, since you don’t need to manually reproduce the situation again, and you expand your test suite at the same time. Keep in mind that your development environment might not fully represent your production environment.
3. Collect information
When starting the bug hunt process, the bug could be anywhere. There are a few things that can help you reduce the problem space.
Logging is incredibly useful in tracking down the cause of the bug. It can contain an exception, and the path leading to it. If the log contains an exception, be sure to start with the first exception in the log, since the first exception might have triggered other exceptions. Keep in mind that the first exception may have occurred a while ago, or even at application startup. Therefore try to get hold of as much of the log file as possible, not just an exception snippet. Once you found the first exception, look for the last caused by.
These days debuggers are quite powerful. It is worth your time to learn how to use them. Getting handy with them and using features like conditional breakpoints or break on exception will prove invaluable.
3.3. Work from bottom to top
Instead of starting to debug at the application entrance point and hope you encounter the the problem, it is often more effective to start where the bug occurred and work your way up. You will be able to see the exact state and the path that got you there using the debugger.
3.4. Exclude possible causes
Sherlock Holmes once said “When you have eliminated the impossible, whatever remains, however improbable, must be the truth.”. The same principle applies to debugging. When you start the bug hunt, the problem space can be quite big. In order to find the bug we need to reduce it. So we need to exclude possible causes. Is it a back-end problem or a front-end problem?, which components are involved? these kind of questions can help you pinpointing the location of the bug. Be aware that when you made the decision to exclude a component, you generally don’t look back. Keep looking at the facts, and reevaluate the decision when needed.
If the bug only appears in the latest version of the software, it might be a clue to finding out where the bug resides by comparing versions. Keep in mind that code is not the only thing that changes between versions. It might also be a database change, environment variables, or external services or dependencies.
5. Identify the problem
Now we found the problem area, we need to find out what is going wrong.
5.1. Learn the code
First review the code. Really try to learn what the code does, think about what input could cause errors in the code. Write a few unit tests to understand the code. Knowing what the code should do helps locating and finding the best solution for the bug.
5.2. Trust your knowledge and skill
In retrospect, most bugs you solved in your career were probably quite obvious and simple. This is true for most bugs. So be careful when you start thinking about magical causes when you are having a hard time finding the bug. Once there is consensus in a team about a possible cause that is not solvable by the team ("it’s probably faulty hardware"), the team will stop looking for a solution. Trust your own skill, if the thought up cause seems too magical, it probably is, keep on looking until you are sure.
5.3. Test your hypothesis
This is probably the most important tip in this article. I noticed most bug hunting time is wasted trying to solve non-existing bugs. Once you formed a hypothesis about the possible cause of the bug, try to think of a way to prove it as well. It is okay to make a temporary hack just to check if you were right. Don’t start solving your hypothesis before you are sure that you are right.
6. Solve the problem in the right place
When you finally tracked down the location of the bug it is now time to solve it. Keep in mind that the location where the bug occurred does not have to be the best place to fix the bug. Spend time finding the root cause of the bug instead, and fix it there instead of adding an extra if condition.