Thursday, February 15, 2007

Three Questions About Each Bug You Find

Tom Van Vleck

Do you sometimes fix a bug, and then find another bug related to the first or to the way you fixed it? When I fix a bug, I ask myself three questions to make sure I've thought carefully about its significance. You can use these questions to improve productivity and quality every time you think you've found and fixed a bug.

The key idea behind these questions is that every bug is a symptom of an underlying process. You have to treat the symptoms, but if all you do is treat symptoms, you'll continue to see more symptoms forever. You need to find out what process produced the bug and change the process. The underlying process that caused your bug is probably non-random and can be controlled, once you identify what happened and what caused it to happen.

Before you ask the three questions, you need to overcome your natural resistance to looking carefully at the bug. Look at the code and explain what went wrong. Start with the observable facts and work backwards, asking why repeatedly, until you can describe the pattern that underlies the bug. Often, you should do this with a colleague, because explaining what you think happened will force you to confront your assumptions about what the program is up to.

"It blew up because subscript J was out of range."
"Why?"
"J was 10 but the top array subscript is only 9."
"Why?"
"J is a string length, and the array origin is 0, so the last character in a string of length 1 is index 0."

Look for additional surprises in the situation at the time the bug was found. Check key program variables at the time of failure, to see if you can explain their values.

"Why is the name null?"
"Why was it trying to output an error message anyway?"

Keep notes of what you did and what happened. You need to know what is really going on, and this means keeping measurements and history.

When these steps are out of the way, you are ready to ask the first question.



1. Is this mistake somewhere else also?

Look for other places in the code where the same pattern applies. Vary the pattern systematically to look for similar bugs.

"Where else do I use a length as a subscript?"
"Do all my arrays have the same origin?"
"What would happen for a zero length string?"

Try to describe the local rule which should be true in this section of the code, but which the bug disobeyed; your search for this invariant[1] will help you see other potential bugs.

"The starting offset plus the length, minus 1, is the ending subscript.. unless the length is zero."

It's more productive to fix several bugs for every one you find. Trying to describe the bugs in general terms also raises your level of understanding of what the program is doing and helps you avoid introducing more bugs as you program.

2. What next bug is hidden behind this one?

Once you figure out how to fix the bug, you need to imagine what will happen once you fix it. The statement after the failing one may have a bug in it too, but the program never got that far before: or some other code may be entered for the first time as a result of your fix. Take a look at these untried statements and look for bugs in them.

"Would this next statement work?"

While you're thinking about control flow is a good time to ask if there are other unreached parts of the program.

"Are there combinations of features I've never tested?"

It doesn't take much work to instrument a program so you can check off as you execute its various parts; and it's often surprising how much of a program doesn't work at all after the builder says it's been tested.

"Can I make all the error messages come out in test?"

Beware of making a change in one place which causes a bug somewhere else. A local change to some variable may violate the assumptions made further on in execution.

"If I just subtract one from J, the move statement later will try to move -1 characters when the string length is 0."

If you've made a lot of changes to the program already, consider carefully whether adding another local fix is the right thing to do, or whether it's time to redesign and reimplement.

3. What should I do to prevent bugs like this?

Ask how you can change your ways to make this kind of bug impossible by definition. By changing methods or tools, it's often possible to completely eliminate a whole class of failures instead of shooting the bugs down one by one.

Start by asking when the bug was introduced: when in the development life cycle could the bug have been prevented?

"The design is OK; I introduced this bug in coding."

Examine the reason for the bug in detail. Think about the process that was going on at the moment that the bug was introduced, and ask how it could be changed to prevent the bug.

"Separate data types for offset and length would have caught this error at compilation time."
"Each text item could be output with a macro which hides the subscripting calculation. Then I can figure this out just once."

Don't be satisfied with glib answers. Suppose your explanation for a bug is, "I just forgot." How can the process be changed so you don't need to remember? The language can be changed so that the detail you omitted is completely hidden, or your omission is detected and causes a compiler diagnostic. You might use a language pre-processor for this problem domain, or a clever editing tool which fills in defaults, checks for errors, or provides hints and rapid documentation. The bug may be a symptom of communication problems in the programming team, or of conflicting design assumptions which need discussion.

Consider the way the bug was found, and ask how it could have been found earlier. How could testing be made more air-tight? Could tests be generated automatically? Could in-line checking code be added that would trap errors all the time?

"I should try a zero length string in my unit tests."
"I could enable subscript checking and catch this sooner."

Systematic methods and automated tools for compilation, build, and test are always worth creating. They pay for themselves quickly, by eliminating long debugging and fact-finding sessions.

Applications of the Technique

Make a habit of asking the three questions every time you find a bug. You don't even have to wait for a bug to use the three questions.

During design and implementation review, each comment you get can be treated with the three questions. Review comments are the result of an underlying communication process which you can improve. If you feel that a reader's comment on a specification is wrong, for example, you might ask what kept your document from being understood, and how you might communicate better with the reviewer.

Design and code inspections[2] are a powerful means of finding many bugs. You can ask the three questions about each defect discovered in the inspection process. The first two questions won't turn up many new bugs if the inspection process is thorough, but the third question can help find ways to prevent future bugs.

Acknowledgments: I am grateful to the many friends and colleagues who taught me these lessons and enriched my life and work. Jay O'Dell, Rick Berman, and Tom DeMarco contributed valuable criticism and advice on previous versions of this paper.

References

[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.

Software Engineering Comix #1

ACM SIGSOFT Software Engineering Notes, vol 14 no 5 July 1989, pages 62-63.


Read more...


Link to trackback page

Wednesday, February 14, 2007

Software Engineering Proverbs

collected by Tom Van Vleck

cartoon, building tower from top down

Drawn by Angus Macdonald




A clever person solves a problem.
A wise person avoids it.

-- Einstein


André Bensoussan once explained to me the difference between a programmer and a designer:

"If you make a general statement, a programmer says, 'Yes, but...'
while a designer says, 'Yes, and...'"


No matter what the problem is,
it's always a people problem.

Jerry Weinberg


Wexelblat's Scheduling Algorithm:

Choose two:

  • Good
  • Fast
  • Cheap

Craziness is doing the same thing and expecting a different result.

Tom DeMarco, rephrasing Einstein, who said

Insanity: doing the same thing over and over again and expecting different results.


"There's no time to stop for gas, we're already late"

-- Karin Donker


Deming's 14 points

  1. Create constancy of purpose.
  2. Adopt the new philosophy.
  3. Cease dependence on mass inspection to achieve quality.
  4. Minimize total cost, not initial price of supplies.
  5. Improve constantly the system of production and service.
  6. Institute training on the job.
  7. Institute leadership.
  8. Drive out fear.
  9. Break down barriers between departments.
  10. Eliminate slogans, exhortations, and numerical targets.
  11. Eliminate work standards (quotas) and management by objective.
  12. Remove barriers that rob workers, engineers, and managers of their right to pride of workmanship.
  13. Institute a vigorous program of education and self-improvement.
  14. Put everyone in the company to work to accomplish the transformation.

We know about as much about software quality problems as they knew about the Black Plague in the 1600s. We've seen the victims' agonies and helped burn the corpses. We don't know what causes it; we don't really know if there is only one disease. We just suffer -- and keep pouring our sewage into our water supply.

-- Tom Van Vleck


The Troops Know

  • The schedule doesn't have enough time for maintenance in it.
  • A lot of bugs get past the tests.
  • Most old code can't be maintained.

To go faster, slow down. Everybody who knows about orbital mechanics understands that.

-- Scott Cherf


Everybody Knows:

  • Discipline is the best tool.
  • Design first, then code.
  • Don't patch bugs out, rewrite them out.
  • Don't test bugs out, design them out.

Everybody Knows:

  • If you don't understand it, you can't program it.
  • If you didn't measure it, you didn't do it.

Everybody Knows:

If something is worth doing once, it's worth building a tool to do it.


Your problem is another's solution;
Your solution will be his problem.


Everybody Knows:

  • If you've found 3 bugs in a program, best estimate is that there are 3 more.
  • 60% of product cost comes after initial shipment.

The significant problems we face cannot be solved by the same level of thinking that created them.

-- Albert Einstein


On the radio the other night, Jimmy Connors said the best advice he ever got was from Bobby Riggs:

  • do it
  • do it right
  • do it right now

It is not enough to do your best: you must know what to do, and THEN do your best.

-- W. Edwards Deming


A leader is best when people barely know that he exists.
Less good when they obey and acclaim him.
Worse when they fear and despise him.
Fail to honor people, and they fail to honor you.
But of a good leader, when his work is done, his aim fulfilled,
they will say, "We did this ourselves."

-- Lao-Tzu


You must be the change
You wish to see in the world

-- Gandhi


Experiment escorts us last,
His pungent company
Will not allow an axiom
An opportunity.

-- Emily Dickinson


when the cart stops
do you whip the cart
or whip the ox?


Q: How many QA testers does it take to change a lightbulb?
A: QA testers don't change anything. They just report that it's dark.

Kerry Zallar


Q: How many software engineers does it take to change a lightbulb?
A: Just one. But the house falls down.

Andrew Siwko


One test is worth a thousand opinions.


"If you didn't write it down, it didn't happen."

This saying is popular among scientists (doing experiments), but I believe it applies to software testing, particularly for real-time systems.

--Larry Zana


We reject kings, presidents, and voting.
We believe in rough consensus and running code.

--Dave Clark (1992)


I am a design chauvinist. I believe that good design is magical and not to be lightly tinkered with. The difference between a great design and a lousy one is in the meshing of the thousand details that either fit or don't, and the spirit of the passionate intellect that has tied them together, or tried. That's why programming---or buying software---on the basis of "lists of features" is a doomed and misguided effort. The features can be thrown together, as in a garbage can, or carefully laid together and interwoven in elegant unification, as in APL, or the Forth language, or the game of chess.

-- Ted Nelson


Software is Too Important to be Left to Programmers, by Meilir Page-Jones.


"If you think good architecture is expensive, try bad architecture."

-- Brian Foote and Joseph Yoder


Abraham Lincoln reportedly said that, given eight hours to chop down a tree, he'd spend six sharpening his axe.

-- TidBITS 654, quoted by Derek K. Miller, via Art Evans


... while we all know that unmastered complexity is at the root of the misery, we do not know what degree of simplicity can be obtained, nor to what extent the intrinsic complexity of the whole design has to show up in the interfaces. We simply do not know yet the limits of disentanglement. We do not know yet whether intrinsic intricacy can be distinguished from accidental intricacy.

-- E. W. Dijkstra, Communications of the ACM, Mar 2001, Vol. 44, No. 3


You can only find truth with logic if you have already found truth without it.

-- Gilbert Keith Chesterton (1874-1936) " The Man who was Orthodox", via Paul Black


Here is a great page about some kinds of management actually observed, and some insights on quality processes, by Joseph Koshy, via Robert Watson


16 Jan 2007


Read more...


Link to trackback page

Wrox.com: Save on WROX books!

With WROX, you get real-world programming know-how from real-world programmers. Now you can save 20% on WROX books. Just go to wrox.com and sign up for the FREE WROX newsletter. You’ll get great WROX content in the newsletter—and 20% off books on purchased through wrox.com.

After you signed up, you could see this msg:

Thank you for your subscription. Now you are eligible to receive 20% off of your next Wrox purchase. Enter promo code CODE into your wrox.com shopping cart."

Enjoy your books!

Read more...


Link to trackback page

Thursday, February 1, 2007

First Here!

hoho, another blog!!!

Read more...