All About Debugging: An Introduction
What, why, and how to debug
In computer science, debugging is the process when the developer or programmer attempts to find a source of error, isolate it, and then fix it or create a way to work around it. The word “debug” first appeared in the 1940s when Grace Hopper was working on the Mark II computer and observed that it wasn’t functioning correctly. The reason was that a moth got stuck in the relay of the computer, causing it to malfunction. So back then, a “bug” was quite a literal term!
Finding and fixing bugs is an essential step in the software development cycle. Usually, the process of finding a bug or a scenario where the program doesn’t function properly is part of the testing phase of developing software.
Although the testing step comes after the design step (which includes design, outlining, and implementing the code) in the cycle, in practice, testing goes in parallel with writing the code. Usually, big software projects are divided into several sections. Each has its team of developers and its standalone functionality. These sections are then combined to form the overall software product. That’s why each part must undergo its own testing process to make sure it functions properly before it is added to the main project.
“Good programmers know that they spend as much time debugging as writing so they try to learn from their mistakes.” — Brian W. Kernighan, Rob Pike
Debugging is definitely the most dreadful task for developers. After all, we like to build things rather than fix bugs! Nevertheless, no one can deny the importance of debugging. Programs or applications that work perfectly from the first try are the exceptions and not the rule.
Debugging can help developers pinpoint various types of errors, including syntax errors, semantic errors, and logic errors. Although compilers can help significantly in finding some syntax errors, some of them — like runtime errors — can depend on the environment and the dependencies, which means that they will not occur in every single run of the application.
Oftentimes, testing and debugging software takes a longer time than writing the software itself. Being able to find and fix bugs is a valuable skill for any developer because it means that you’re a creative thinker and a problem-solver. However, this process can be made more efficient if the company or the team has a set go-to debugging strategy. Not to mention the financial loss that can be avoided if a severe bug is found in a product before it is deployed.
How to Debug
There are different debugging approaches that perform different functionalities. Some approaches reproduce the error conditions that caused the failure, while others examine the program state at every step of the application and locate the bugs that caused the errors. Those techniques can help programmers trace the execution of the code step by step and halt it wherever an error occurs.
We can categorize debugging techniques into two main categories:
- Techniques that analyze the program performance by inspecting the main memory after the program crashed (post-mortem debugging).
- Techniques that analyze the program step by step by running it under a debugger (“dynamic debugging” or “tracing debugging”).
Most applications today contain thousands of lines of code, which can make the debugging process complicated. Some strategies can be followed to make debugging easier, such as unit tests, code reviews, and pair programming.
Sometimes, the location in the code where the error occurred can be clearly identified. However, that’s not always the case. Most times, the location of the bug is unclear. Here’s where unit testing can be helpful. It allows the programmer to run a specific part of the code with a particular input. Doing so can ease the process of locating the bug.
An agile software development technique where two programmers work together on the same codebase, usually in the same physical location. The two programmers will have different roles. The driver writes code, while the observer or navigator reviews each line of code written by the driver. The two programmers switch roles frequently to increase the efficiency of this approach.
A software quality assurance approach where two or more programmers systematically check each other’s code for errors and uncertainties.
Debugging tools, or debuggers, are special tools that are built for the sole use of analyzing programs and finding errors. Some debuggers analyze a test case and run it to determine which lines of the code didn’t execute correctly or at all. In contrast, others provide simulations of the code’s behavior, allowing the programmer to model how the program will behave on a given software (operating system) based on specific dependencies.
Testing vs. Debugging
Testing and debugging are two terms that are usually used together, which may lead to the misunderstanding that they mean the same thing.
In fact, they are quite different from each other. They do share some functionality, but they differ in designs, execution, and benefits. Both testing and debugging are essential stages of software development and come with a variety of results. That’s why it’s necessary to properly understand the differences between them to optimize our software development process.
Testing is usually done by the developer (or a tester) to search out any problems and weird behaviors within the software. The tester executes manual and/or automatic test cases on the software and collects information about the results. These results are sent to the developers so they can fix the cause of the problem. Once they are done, they send the software back to the tester.
The developers debug the software after getting the test report about the errors from the tester. Developers then debug their work by searching it to find the cause of the error using an appropriate debugging technique. Once they locate the bug, they go ahead and modify the code and check whether the error is fixed.
So testing is for finding errors, while debugging is for finding the cause of a specific error (or the bug causing the error).
Debugging is a tough task and may take a significant and unpredictable amount of time. Therefore, the goal is to try to simplify it as much as possible. Techniques that can help achieve that include good design, good style, stipulation tests, assertions, adding checks within the code, having well-designed interfaces, and limiting the use of global data.
This article is the first of a four-part series digging deep into everything debugging-related. Upcoming articles will be:
- All About Debugging: The Techniques. I will discuss in detail the different debugging techniques used in debugging tools.
- All About Debugging: Special Systems. I will discuss debugging special systems, such as large-scale debugging, parallel system debugging, and more.
- All About Debugging: Advanced Approaches. I will discuss unanswered questions about debuggers, visual debuggers, and the latest debugging research.
- Brian W. Kernighan/Rob Pike: The Practice of Programming. Addison-Wesley, 1999.
- Ko, A., & Myers, B. (2008, May). Debugging reinvented. In 2008 ACM/IEEE 30th International Conference on Software Engineering.
- Hailpern, B., & Santhanam, P. (2002). Software debugging, testing, and verification. IBM Systems Journal.