Debugging -- Using Hypotheses to Track Down the Culprit

Steven Zeil

Last modified: Jul 22, 2016
Contents:

1 Rules of Debugging

In this lesson we focus on tracking down the culprit.


An actual message received from a student

Professor Zeil,

Upon running my code, I found several errors that I have been unsuccessful in solving. The most glaring error is that when I try to use the “Tile” option under the view menu, I get an error concerning a division by zero. Looking back at where the error references the code, it seems to be happening at the point where there is division by the bounding box height and width. This leads me to believe that my bounding box function for the Composite is flawed. This is not unlikely considering my inexperience with Java, but by my estimation it should have worked. I used the union function to combine the bounding boxes of different shapes, so there should be no reason that the bounding box returned by the Composite would be zero. Unless there are no shapes in the list to begin with, but that should not be the case either. When I use the “Draw Composite” option under the view menu, shapes are drawn, so there should be shapes in the Composite private member field (I am using a vector to store the shapes). Additionally, when I select the “Move Composite” or “Reflect Composite” options, nothing is displayed, but there is no error message given either. Any assistance you can provide would be greatly appreciated.

This email was sent in regards to an assignment involving manipulating pictures composed of many component shapes.

A key idea in such applications is that of a bounding box, the smallest rectangle that can enclose a set of shapes. Computing the bounding box was one of the first steps required for many of the picture manipulations.


What’s Wrong with That?


Wasted Effort

 

Some of the thought going into those guesses may have been wasted effort:

This leads me to believe that my bounding box function for the Composite is flawed…the bounding box returned by the Composite would be zero.

That’s an awful lot of effort going into something that might not even be remotely true.


Continuing in that vein

I used the union function to combine the bounding boxes of different shapes, so there should be no reason that the bounding box returned by the Composite would be zero. Unless there are no shapes in the list to begin with, but that should not be the case either.

This leads us to the key rule of this lesson …

2 Don’t Guess, Hypothesize

The problem with the above-quoted student is that he was making guesses instead of hypotheses.


Guessing

Looking back at where the error references the code, it seems to be happening at the point where there is division by the bounding box height and width.


More Guessing

This leads me to believe that my bounding box function for the Composite is flawed.


Still More Guessing

 

by my estimation it should have worked. I used the union function to combine the bounding boxes of different shapes, so there should be no reason that the bounding box returned by the Composite would be zero.

Unless there are no shapes in the list to begin with, but that should not be the case either.


Won’t the Guesswork Ever Stop?

When I use the “Draw Composite” option under the view menu, shapes are drawn, so there should be shapes in the Composite private member field


Can you phrase that in the form of a question?

Additionally, when I select the “Move Composite” or “Reflect Composite” options, nothing is displayed, but there is no error message given either.

2.1 Hypothesizing

The frustrating thing about all that guesswork is that it would have been easy to check and see which of those guesses were actually true:

Looking back at where the error references the code, it seems to be happening at the point where there is division by the bounding box height and width.


Guess + Test = Hypothesis

This leads me to believe that my bounding box function for the Composite is flawed.


Why Engage in Idle Speculation?

by my estimation it should have worked. I used the union function to combine the bounding boxes of different shapes, so there should be no reason that the bounding box returned by the Composite would be zero.


Hypothesize

Unless there no shapes in the list to begin with, but that should not be the case either.


Hypothesize, Hypothesize

When I use the “Draw Composite” option under the view menu, shapes are drawn, so there should be shapes in the Composite private member field


Hypothesize, Hypothesize, Hypothesize

Additionally, when I select the “Move Composite” or “Reflect Composite” options, nothing is displayed, but there is no error message given either.

2.2 Debugging as a Series of Science Experiments

 

As you trace backwards along the path from failure to possible faults,

3 Narrowing the Search


Divide and Conquer

If you can find a location along a probable backwards infection path that

then test the hypothesis that the failure occurs before that location.

You can save a lot of time and effort by repeatedly cutting your search space in half.

Essentially, this is the “binary search” approach to debugging.


What if a Problem Has Multiple Possible Causes?

 

If you find that there are multiple potential causes for the observed failure, you may have to test hypotheses for each in turn.

4 If you didn’t fix it, it ain’t fixed!

 

(Quoted from Debugging by David Agans)

If an error goes away, and you don’t understand why, don’t trust that it is really gone.


Grounds for Suspicion

 

If an error goes away, and you don’t understand why, don’t trust that it is really gone.