Debugging is a process to find and fix a defect or bug in the code. We all know that Brian W. Kernighan was right when he wrote: “Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.”
In the forthcoming “Debugging Step by Step …” articles we consider traditional and state of the art debuggers, introduce some new methods make debugging easier and describe and efficient process of bug hunting.
In this first article we shortly outlined the main methods of traditional debugging, and explain their advantages and disadvantages.
Logging is the first traditional method to find bugs by inserting log statements into the code. Originally, it consists of different print statement to display the value of variables we are interested in. Nowadays there are logging frameworks which make this task much easier. The log information can be prioritized and the logging level can be changed.
The advantage of this method is that the necessary information remains available after the program has been terminated. It’s very easy to use and there is almost no learning curve. Logging is also important in production environment, where traditional debugging is not possible. The application should run on a level logging only serious and fatal errors, but if necessary it can be changed to log other information.
However, there are some drawbacks as well. The code becomes larger and thus less transparent. If one information is missing than you should insert a new log statement and execute the code again. Sometimes you should dig into a large log file to find your specific need. For me the biggest problem is that the log result and the code are completely separated, and it’s difficult to connect them. Some authors report serious damage by applying it. For example, inserting log statements into an application with more threads may cause a classic out-of-order deadlock scenario, however this happens very rarely.
71% of the developers are using debuggers, which can be stand alone or built in an IDE. Though you can execute the code step by step, the sad truth is that the number of execution steps even for a short run is several thousands, and therefore not tractable. Therefore, the most important added value of debuggers is the breakpoints by which you can stop execution in a sophisticated way. You should make hypothesis and stop running at some points to see what happened there. After some iterations the fault may be detected.
The advantage is that erroneous values are detected at the point of their assignment, so you don’t need to connect them to the code. You can also display any value you think is needed to verify. With sophisticate break point settings you can stop running at any execution point. All the data are up to date, and there are no huge log files aggregating new data again and again. Last but not least, debuggers nowadays are very fast.
However, the main problem is that traditional debugging is cyclical. This means that selecting a series of breakpoints and arriving at the last one it occurs that the defect is in an earlier execution step. The main problem of traditional debuggers is that you cannot go backward. Thus you should rerun the code with the same input and setting a new breakpoint closer to the defect. This iteration end when you finally find the defect. The problem is that this process requires each run to behave the same way. For real time or multi-threaded programs this is not the case. Nevertheless, even for multi -threaded programs there should be several inner states where the values have to be deterministic, and we can use debuggers. Another problem is that traditional debuggers can be very rarely used at production environment.
For more information on this topic read http://zeroturnaround.com/rebellabs/the-state-of-logging-in-java-2013/and http://www.vogella.com/tutorials/EclipseDebugging/article.html
Summarizing, both traditional methods have numerous advantages and disadvantages, but without them developers’ life would be more difficult. In the next article we consider state of the art debugging that eliminates most of the drawbacks of traditional ones. Don’t miss it!