Have you ever fixed a bug, then found a related bug, or fixed a bug in a way that caused another bug? When I fix a bug, I ask myself three questions to make sure I’ve thought through what it means. Use these questions to improve productivity and code quality every time you think you’ve found and fixed a bug.

The main idea behind these issues is that every bug is a bad manifestation of the underlying process. You have to deal with the symptoms, but if you just deal with the external symptoms, you’ll have problems that will never end. You should find the process that caused the bug and fix it. When you determine what is happening and why, you may understand that the underlying process that generates the bug is not random, but controllable.

Before asking these three questions, you need to overcome your natural resistance to bugs and analyze them carefully. Look at the code and explain what went wrong, starting with what you can see, working backwards, and asking why until you can find the pattern that produced the bug. Usually, you should do this with a colleague, because explaining what you think will happen forces you to confront assumptions about what these programs do.

“It overflows because the subscript J is out of bounds.”

“Why?”

“J is 10, but the array’s maximum subscript is 9.”

“Why?”

“J is a string length, and the array starts with an index of 0, so the index of the last character of the string length 1 is 0.”

Once you find bugs, look for other unexpected situations. Check the values of the main program variables when the program fails and see if they can be interpreted.

“Why is name null?”

“Why does it always output error messages?”

Keep a record of what you do and what changes you make. You need to know exactly what happened, and doing so means you always have a yardstick and a historical record.

When you have completed these steps, you are ready to ask your first question.

1. Does this mistake happen elsewhere?

Look at where the same pattern is used in your code and systematically change the pattern to find similar bugs.

“Where else have I used length as a subscript?”

“Do all arrays start with the same index?”

“What happens to a string of length 0?”

Try to describe the rules that should be true in this part of the code, but the bugs don’t follow. The process of finding this invariant [1] will help you find other potential bugs.

“The starting offset plus the length minus 1 is the ending subscript, unless the array length is 0”.

For every bug you find, you can solve a batch of bugs, which is very efficient. Trying to describe these bugs in general terms will also improve your understanding of your program and help you avoid introducing more bugs into your program.

2. What other bugs are hidden behind this bug?

Once you figure out how to fix the bug, you need to think about what happens when you fix it. The statement following the failed statement may also have a problem, but the program may not have a bug until it has been executed, or some code may have a problem when it appears in the program for the first time because you fixed a bug. Look at these unexecuted statements to check for bugs in your code.

“Will the next statement work?”

While you’re thinking about your application’s control flow, you can figure out where your application isn’t executing.

“Is there a combination of features I’ve never tested?”

Instrumentation does not take too much time and can be checked in the process of running various parts of the program, but you will be surprised to find that developers have tested a lot of code does not work.

“Can I test out all the error messages?”

Be aware that changes made in one place may cause bugs elsewhere. Some local changes to variables may violate subsequent assumptions when executed.

“If you just subtract 1 from J, when the length is 0, the following statement will operate on the element at position -1 in the array.”

If you’ve already made a lot of changes to your program, think carefully about whether another patch is necessary or if it’s time to consider a redesign and re-implementation.

(Sometimes tuning bugs are like this)

3. What should I do to prevent such bugs?

Ask yourself how you can change your programming methods and avoid bugs by definition. By changing methods or tools, you can often remove bugs from an entire class rather than solving them one by one.

Start with the question “When are bugs introduced?” : At what stage in the application development life cycle can bugs be prevented?

“Design is fine; I’ve introduced bugs in my programming.”

Examine the cause of the bug, consider the process that was running at the time the bug was created, and think about how you can change it to prevent it.

“Separating the offset data type and length will catch the error at compile time.”

“Each text item can be printed with a macro that hides the subscript calculation, and THEN I can find it once.”

Don’t settle for superficial answers. If your explanation for a bug is, “I can’t remember,” how can you improve the process so that you no longer need to remember it? You can change the programming language so that overlooked details can be completely hidden, or else your missing parts will be detected and cause compilation problems. For this problem field, you may use a preprocessor or a smart editor with default values, error checking, smart prompts, and quick documentation. This bug could be a communication problem with the programming team, or a design conflict that needs to be discussed.

Think about ways to find a bug and ask yourself how you could have found it earlier. How could the tests be more rigorous? Can you automate tests? Do you want to add code real-time detection so that you can catch errors in time?

“I should try arrays of length 0 in my test unit.”

“I should do a subscript check to catch nonconforming subscripts in advance.”

There is a need to create systematic approaches and automated tools for compilation, build, and testing that can reduce lengthy debugging and fact-finding.

The application of this technique

Make a habit of asking yourself these three questions every time you find a bug, even if you don’t have to wait until there is a bug to use these three questions.

During the design and review process, you can use these three questions to handle every comment you get. Review comments are the result of an underlying communication process that allows you to make improvements. If you think a reader comment is wrong, for example, you might ask what is making your article not understood and how to better communicate with the reviewer.

Design reviews and code reviews [2] are powerful tools for finding bugs, and you can ask three questions for every flaw in the review process. If thoroughly vetted, the first two questions won’t produce many new bugs, but the third question can help you find ways to avoid bugs that might arise in the future.

Thank you: To my friends and colleagues who taught me these lessons and enriched my life and work. Thanks to Jay O ‘Dell, Rick Berman, and Tom DeMarco for their valuable criticisms and suggestions on an earlier version of this article.

Reference [1] Hoare, C. A. R, Proof of A Program: FIND, Comm. ACM 14, 39-45, Jan 1971. [2] Fagan, M. E., Design and Code Inspections to Reduce Errors in Program Development, IBM Systems Journal 15(3), 1976. [3] Saltzer, J. H., Repaired Security Holes in Multics, MIT CSR-RFC-5, Feb 27 1973.



17 comments

About the author:BJdaxiang

Personal home page
My article
10