14A. Avoiding the Swamp: Diagnosing and Fixing Errors


The process of debugging

Do your best, through careful planning and checking, to ensure that your code uses a correct algorithm and implements that algorithm correctly. An ounce of prevention is worth a pound of cure.

But despite your best efforts, you will make mistakes. Everybody does. A major issue in software development is how to find mistakes and find the right way to fix them. There are a few logical stages in doing that.

  1. Testing. Before you can fix a mistake, you have to realize that it is present. That calls for extensive testing. It is not enough to try one or two inputs. If there is a mistake, you want to know about it.

    Among others, try inputs that are, in some sense, extreme. For example, if the input is a positive integer, try the smallest positive integer, 1. It is a good idea to try 2 and 3 as well. If there is a largest allowed input, try that. Mistakes in software often show up for inputs that are at the beginning or end of an allowed range.

    Experts use an idea called regression testing. Instead of doing tests by hand, they write a script that performs tests automatically. When a test is found to work, it is not removed from the script. Each time the script is run, it runs all of the tests that have ever been done. That way, if your fix of one error breaks something else, you find out about it.

  2. Localization. Usually, a mistake is in a small part of your software. Before you can find out what is wrong, you need to find out roughly where the mistake is. The next page looks at a way to make localization easy in most cases.

  3. Diagnosis. Once you have discovered where an error is, it is time to determine just what is wrong. Hand simulation or tracing can help in that.

  4. Fixing. If the error is the result of incorrectly coding a correct algorithm then, most of the time, once you see what the error is, the way to fix it is obvious.

    If the error is the result of an incorrect algorithm, it is back to planning. Do not try to patch the algorithm for a specific input. That just wastes your time. You will patch and patch and never reach something that works. Check the algorithm again, and be willing to abandon one algorithm in preference for another.

Many beginners look at that list of tasks and see it as daunting. It is not. With experience, each step can be done quickly.

The worst approach that you can take is to avoid all of that and instead try a random change. If you are ever tempted to start trying changes without good reasons for believing that those changes are sensible, then put your software down and come back to it later.