Welcome to the last unit in our debugging course where we review
the material we've seen so far and put it all together.
Now at the end of the course, let's put everything together to see
what we do when we encounter a new bug.
When we see a new bug, the first thing we do is to make sure it gets processed.
So we enter it in the problem database.
We've seen the stages the problem report goes through from unconfirmed
via new to assigned, when it's assigned to an individual developer,
and finally resolved and closed.
Any new problem needs to go into the problem database.
In the long run, checking problems also helps you in coming up with statistics
on how long it takes you to fix a bug, how many bugs there are that still need to be fixed,
as well as where are the bugs are that need to be fixed?
Such that in your program, you know where the locations are
that overtime have the highest bug density, and therefore needs special attention.
For all of this, tracking the problem is the first prerequisite.
The next step is to reproduce the problem because only when you are reproducing a problem,
do you know whether you will actually be able to fix it.
We have seen what the individual inputs are that all influence a program execution.
Most important being static data, user interaction and the interaction with the environment
but also more trouble issues like the debugger which influences the program
or time randomness and other issues that may be hard to control.
In order to reproduce the problem, you must get all of this under your control.
Reproducing your problem can be particularly hard when you're collecting such data from the field
because data and user interaction may contain sensitive data.
This is why we have also seen the techniques of statistical debugging which relate execution features
such as allowing the program being executed on that to failures and success
by collecting such data from the field, you'll be able to find out
which features of the execution correlate with failures
and these features can be features such as executed lines or returned values of functions.
The next step in debugging is to automate and simplify.
The idea being that you write a test gate
at which you can reproduce the bug at any time automatically.
At first, this helpful, of course, for doing regression testing
such that you can always verify whether the problem is there or not.
However, results are helpful to automatically simplify the problem
if you have a big input which causes a failure, then an automatic test
can help you automatically simplifying this input.
The technique of delta debugging takes this big input and with the help of an automatic test
automatically simplifies it to an input in which every single item is relevant for reproducing the failure.
This can be a great aid as it comes to understanding what makes the failure occur and what not.
Once you have simplified the problem, the next step will be to find possible infection origin.
If your program fails, you can see its execution as a succession of state.
The last state is what you see as a failure and you want to figure out where did this failure come from.
The concept of dependencies helps you figuring out
the possible sources of an infection and rule out all the other ones.
When you're tracking back where a failure came from,
you frequently have the choice of looking at multiple possible origins.
But you'd like to do is to focus first on those origins which are most likely.
If you know that some state is already infected that is wrong, you will focus on this one first.
If you know from some earlier state that this caused this later state,
you will also like to focus on this one.
If you know from statistical debugging that some feature is correlated with the failure, go for it.
And if you have reason to believe that some particular state is likely to be buggy anyway,
for instance, because of it's bug history, you also go for it.
And we have seen techniques how to determine all of these in particular assertions
which help a lot for finding out immediately during the execution
whether some part of the state is erroneous or not.
The sixth step is to isolate the infection chain.
What this means is for every likely origin, you go and conduct an experiment
to see whether it actually is the cause of the failure.
For this, you used the scientific method. You set up a hypothesis.
This could be the cause. This could be the cause. This could be the cause.
Make up an appropriate prediction.
Set up an experiment and based on the observation,
you either refine your hypothesis or you reject your hypothesis.
Be sure to make these steps explicit as it helps structure your thinking
and as it helps you interrupting and resuming your debugging activities as needed.
You repeat this going backwards throughout the program until you arrive at a place
where the incoming data is same but the outgoing data is infected.
The statement which generates this infection is the defect. This is the last step of debugging.
To correct the defect, such that it no longer produces an infection
but actually makes the program behave correctly.
Before you fix the defect, you should be sure that the defect actually is the defect.
That is that by changing it appropriately, the problem will be fixed.
You should have a clear understanding about how your correction fixes the defect.
And then, there are also some chores to be made.
You need to verify that the failure no longer occurs.
You need to make sure that your correction did not introduce new problems
and again assertions as we've seen them in this course, helped you a lot with that.
You may also wish to search your code to check whether the same mistake
was made elsewhere and fix these locations as well.
Note how these seven steps of debugging can be easily memorized by looking at their first letters
which formed the word TRAFFIC.
Traffic may not immediately be related to debugging unless
you're debugging traffic programs but the way that infections propagate to the program
and what's happening during a program execution
can be as confusing as more than traffic in a real big city.
With these seven steps, you're done with debugging. Congratulations!
And now, let's move on to the next part.