Years ago there was a very popular television program called "Bonanza". It was about a father and his four sons living on a ranch in the Lake Tahoe, Nevada area in the 1860's. It ran on NBC from September 12, 1959 to January 16, 1973; in other words 14 years, and thus it was the second longest-running western (just after "Gunsmoke"). Everyone I knew watched it and knew all about the characters and plots.
But no one asked a very simple question: Why is this show called "Bonanza"?
The family was called Cartwright, they lived on the Ponderosa, the nearest town was Virginia City… there is no "Bonanza" anywhere. When I brought this up a couple of years ago a friend tried to explain that there was probably a gold or silver rush in the area at that time, a real bonanza for the area. But the show was not about mining, the characters were ranchers, not miners, and nobody ever mentioned a gold or silver rush even once.
It makes no sense. The point I am focused on, however, is not just that it makes no sense but that the show played for 14 years and nobody I know of ever questioned its name. Not once. I finally asked it 30 years after it was canceled.
Another example: I've been hearing this song on the radio and in advertising and so forth for a long, long time. I'm not fond of it, but I cannot help but be very familiar with its lyrics. It's the Scorpions' "Rock you like a hurricane."
You know it, it's the one that goes "Here I am/Rock you like a hurricane" over and over. And over.
For years (this song came out in 1984) I heard this without once noting… rock you like a hurricane? Hurricanes blow, they don't rock. That's like saying "I'm as hungry as a lemon", or "my head is spinning like a horse", or "he arrived as quickly as a bar of soap."
It makes no sense. But I heard this probably 100 times (or more, unfortunately) before it even occurred to me that it makes no sense.
I do not think I am unusual in this sense. I think people tend to accept what they hear without much critical thought. Most of the time this is probably not all that important, but it really can be when we accept requirements for a system.
For example, in our Sustainable Test-Driven Development class we conduct an exercise where students develop a device driver for a paint-mixing system, and there are a number of business rules they have to write tests about. We roll these rules out, in an agile fashion, as development stories. They write the tests and then write the code to satisfy them; a very typical test-first approach to TDD.
One requirement that comes along is this: There are currently two kinds of paint in this system, glossy paint and flat paint. But there is a very important rule about mixing, namely that you cannot mix glossy paint and flat paint together. The customer warns that doing so would not work, chemically, that the result would be a gloppy mess of useless goo.
Sounds reasonable. Until you try to write a test for it.
First of all, what does it mean to say "you can't"? Of course I can. Watch! (imagine Scott pouring two cans of paint into a mixer). See? The customer means "you mustn't", rather than "you can't".
And, of course, the real question is… what should the system do if someone tries? This is missing. The requirement should be "if someone tries to mix gloss and flat, do the following." It could be shutting the system down, throwing an exception; you could probably imagine other possible actions. But the point is that this is a customer decision, and therefore is a missing requirement.
But even if we get the answer "what do to if", the requirement is still not clear.
You must not mix gloss and flat. Does that mean precisely what it says? Or does it really mean "the two cans of paint you mix must have the same finish"? Those may be equivalent requirements now, but they will not be when a third finish, say semi-gloss or matte is added to the system. Will the rule still apply to them, or is this a special case only involving gloss and flat?
Not only would this influence how we tested the system, but how also we implemented the rule to pass the test:
if (finish1 != finish2) throw new BadPaintException();
if ((finish1==Finish.Gloss && finish2==Finish.Flat) ||
(finish2==Finish.Gloss && finish1==Finish.Flat))
throw new BadPaintException();
Again, not at all the same thing, but the requirement does not make it clear which is right… and the maintenance path for the code would be quite different if we choose the wrong one.
So I call this "The Bonanza Syndrome". Not that customers give us requirements in this vague and misleading state, but that we accept them as reasonable and complete when they are not. One of the powerful things about techniques like Test-Driven Development (both unit testing and acceptance testing ) and Commonality-Variability Analysis is that they force us to apply critical thinking to requirements, and probe them for their actual meaning.
Which, of course, is one reason we teach them.