Hi,
I know there are many popular and useful Design Patters.
Are there something like them for debugging scenarios? Maybe not patterns but methodologies which are categorized and that can be used repeatedly for similar cases.
Any idea?
thanks.
Hi,
I know there are many popular and useful Design Patters.
Are there something like them for debugging scenarios? Maybe not patterns but methodologies which are categorized and that can be used repeatedly for similar cases.
Any idea?
thanks.
When I am just shooting in the dark debugging I take the binary search approach. I comment out half of my code or half of a method, something along those lines, then I focus on the on the uncommented half. If the problem still exists, I comment out another half. And so on.
There are a few more formal patterns to eliminate specific bugs:
However, I think most of your debugging decisions and workflow are going to be already designed by the environment you use.
My approach is to use the scientific method:
If you have a piece of code that used to work, and now exhibits a bug, and a full version history, a binary search through your history can be very useful. You pick a point midway between the working and non-working commit, and you compile that and test. If that commit exhibits the bug, you know it started here or earlier, so you go back midway between here and the known good commit and test again; otherwise, you know the bug started later, so you you go forward midway between here and the known bad commit, and test there. You keep following this process until you find out which commit introduced the bug, and then you look at what changed, and there's a good chance the problem will be obvious.
git bisect is a spectacular tool for just this purpose. But you could theoretically do the same with a bunch of tarballs, if that's all you have.
Of course, this won't work if the bug has been in and out of the tree multiple times. And it probably won't be very helpful if your commits aren't very fine grained.
I like to think that Unit Testing is a debugging pattern. If you can reproduce the problem, you can write a unit test to make it a lot easier to debug.
Once you have the "top-level" unit test that you use to debug the problem, you can always create more failing unit tests at lower and lower levels in your code to help you focus in on the bug while adding unit tests that will be useful long-term in your project.
I'll add one more debugging pattern that seems fairly obvious, but hasn't been said yet:
Reduce the bug to the smallest case possible, and then use that as your unit test for any proposed fix.
Fault isolation is one. Does the problem occur on all the OSes, or is it related to one OS only ?
Proceed by dichotomy to determine the location and the cause of the problem.
The way I debug is the way I solve problems. I use the cartesian method.
There's is 4 rules :
Or, say differently :
You only have to adapt theses rules in the context of programming.
If I had to resume, I'd say take the problem/bug to it's simple expression. Do it iteratively.
Just a few I've come across:
I've got more on my web site under Software Development -> Debugging if you're interested.
I agree with the others about Unit Testing as a "Pattern" for preventing bugs. additionally I would like to quote the following steps from Debugging: The 9 Indispensable Rules for Finding Even the Most Elusive Software and Hardware Problems:
And last, on the more practical side, Dimitry Vostokov has gathered some very nice debugging patterns in his book and website.
Here are a few that work for me:
This is not really a debugging technique, but I think we have to mention a debugging precondition which, if not met, will greatly complicate your work.
You can't really start meaningful debugging until the bug is reproducible, with a step by step recipe. If you get a bad bug report, you may wind up having to discern that recipe yourself, but if you are supporting someone, you should let them know that you figuring out the recipe will take longer than them doing it for you and may even be impossible. A useful bug report has to answer the three questions of what I call the bug report formula: 1) what did you do? 2) what did you expect to happen? 3) what happened instead?
Of course, some bugs are Heisenbugs, apparently transient. You should still try to get something resembling a statement like "If I do the following, it looks like about 10% of the time this undesirable result happens."
Once you have the recipe, the next step is often boiling down to a minimal test case, as others have mentioned.
Others (Xynth, Broam, Moshe) have mentioned the need to get a minimal test case, hopefully one which can be inserted into your unit test suite. I agree. Once you can make the bug happen, start paring away extra factors, or even code (as Bob suggested), testing at each step to see if the bug went away. If it's in cron, run it manually. If it's run from the GUI, try it from a command-line or a simple test suite.
If you are having trouble, the opposite approach is often useful: create a tiny, minimal program that does a couple of things the buggy routine does. Test it and see if you have the bug. Then, step by step, try to write a working program that does what the buggy routine is supposed to do. At some point, you may see the bug exhibited, in which case you now have your test case. Or, you may get all the way to a successful routine. In this case, start transforming that routine, line by line, into an exact replica of your code, testing along the way to see when the bug appears.
Specializing this to OpenGL fragment shader debugging, which is very opaque. Dumbing stuff down is good and necessary, but checking the output is trickier than regular application programming, so you need some tricks:
Thanks for all ideas. They were really helpful. As far as I understand there is not a certain list of patterns like the Design Patterns when it comes to fixing bugs. Maybe after some point everybody has his own way.
One of the approaches I use is, if the process looks complicated, to sit and try to see if I can do some re-factoring the code. This gives me a chance to refresh my mind on the code's behavior, to have better understanding and to make it maybe even more maintainable. Extract method is my favorite to have readable logical units.
One of my favorite thing is, if a value of a property is changed in an unexpected way, I put a break-point on the setter of that property. I do not know if it is possible to do it with implicit property decelerations (bool myProperty {get; set;}).
Maybe it would be better to start with having a BUG catalog showing all the types of bugs categorized with descriptions.
thanks, burak ozdogan