Introduction: Guide to Debugging Code

This guide is made to assist in the difficult process of code debugging, a very important process of development. Debugging is a process more than a specific task, so the steps in this guide are not guaranteed to solve your problem, but they will give strategies that can help you start debugging. There will be example code available to show how the steps can be applied to debugging in practice.

Supplies

This guide presumes that you have some form of program that can compile, but either runs into errors or gives incorrect outputs. This guide will also assume some degree of organization to your program, if your code is not divided into methods and is just one long method, you should partition your code into smaller sections to have an easier time following along. The final thing required for following this guide is some place to write notes during the debugging, such as a tablet or piece of paper.

Step 1: Check Points of Interest

When starting to solve problems in your code, it's a good idea to try to deduce where the problem could be coming from before you start combing through line by line. This is highly dependent on the kind of program you're writing, but examples of where problems could lie are in complicated bits of logic like nested loops where you may have made a small error in writing it. In this example, the program is designed to give optimal moves in a logic game called Mastermind, and one method contains the majority of the algorithm, making it a clear target for calculation problems to come from. I look at the code and notice I placed a semicolon after an if statement, breaking up the logic. Fixing this problem makes my output more accurate, as that if statement was causing the code to completely ignore most of the logic of the algorithm.

Step 2: Add Tester Code

After ruling out obvious points of failure in your code, its time to start experimenting, add code to print out data at the beginning and end of every method. This will allow you to narrow your sights on exactly where the problem is. This Mastermind algorithm is built around a large matrix holding every possible solution, so I built a printer method that can easily print the array of possible answers so checking the values will be easier. I added a call to this method to every method's start and also added a few line to print each methods arguments and outputs, at the start and end of them respectively.

Step 3: Write Out a Test Case

Before analyzing the data your program will be printing out, it's helpful to think of a test case for your program, and write down what output you expect from the given case's input. This gives you more specific directions on what area of code you should be focusing on. It helps to give some descriptive text for what method is being called along with data for clearer analysis of the programs outputs.

Step 4: Compare Output to the Test Case

If it isn't immediately clear which method threw off the data, you might want to walk your test case through the steps the code it taking, and writing down what data you expect to be output at every step, to be clear when the output becomes inaccurate, and thus where to focus your attention. Be sure to address the first place where the data was wrong first, as often an early mistake being fixed can fix the later errors the code is running into. In the Mastermind program, my test case answer was 2556, but the program didn't come to this answer and gave me guess suggestions that didn't match up with my prediction. After adding print statements , it became clear which method was the problem. "convertNums" is a simple method meant to change a number stored as an integer into an array that could be operated on more easily, and the output printed at the end of it didn't match the input it was meant to convert, giving me a place to focus my attention.

Step 5: Find Exact Point of Failure

Once you have a method to focus on fixing, repeat step one, look for any complicated logic you could have made an easy mistake on, see if you can fix it through deduction. If you can't find anything repeat step two through four for the method in question, adding print statements when relevant variables have their values changed. Be careful about gathering too much data, like adding print statements in loops that will iterate hundreds of times, as this will make the output unreadable. When your search is narrowed, further and further, it will become clear which line or small section is written incorrectly. While this will not necessarily give you an immediate solution, to the problem, any mistake you have written will be traced back to this line, whether in the exact syntax, or in the variables it references. In the Mastermind example, I added print statements to convertNums and realized I had made a typographical error in one of the lines of conversion that was feeding my other methods false data. After fixing this problem I got the solution of 2556 I was expecting to receive.

Step 6: Consider a New Approach

If problems persist after you get the first method working correctly, repeat step 5, narrowing your search wherever there are problems. If there are a large amount of separate problems you have to fix in your methods, if you can't seem to figure out what's going wrong on any given problem no matter what you do, and/or if every time you solve a problem, more problems arise; it may be time to start from scratch, your approach to the problem can be do-able but very flawed, and trying a new method may be far easier than trying to fix a suboptimal approach. There's always more than one way to solve a problem, and sometimes the most efficient way to debug is to try a new way entirely.