SPECIFICATIONS
Of all the requirements that we might place on a program, first and foremost is that it be correct.
In other words, it should give the correct Outputs for each possible input. This is what we mean when
we say that a program "works," and it is often and truly said that "any program that works is better
than any program that doesn't."
An example may serve to drive home this point to those whose minds are tangled in questions of
efficiency and other secondary matters. A programmer was once called to Detroit to aid in the
debugging of a new program-one that was to determine the parts requirements to build a certain
set of automobiles. The input to the program was a deck of cards, each card representing a purchase
order for an automobile, with different punches representing the different options selected by the
customer. The program embodied the specifications relating the various options to the parts that would
be needed. For instance, the choice of upholstery for the rear seat might be determined by such factors
as body colour, body style, options for deluxe or leatherette upholstery, and whether or not the car
was air conditioned. The air-conditioning Option is a good example of the basic complexity of the problem,
for though to an untrained eye the choice of air conditioning might have no connection with, the choice
of rear seat upholstery, it might very well require spaces for extra ducts. In general, then, each
Option might have some effect on the-choice of parts made, so the determination of parts requirements
was an excellent Job for the Computer.
Unfortunately, when this programmer arrived on the scene, the basic approach to the problem had long been
settled-and settled badly. Each Option-as it affected each choice-was reflected as an individually programmed
test and branch in the program. In a way, the program was an enormous tree, with more than 5000 branches,
representing the decisions leading to part selection. Cast in this form-and with 16 programmers working at
the same time-it was impossible to debug, as each and every case had to be tested separately. To test the
program, a particular card would be put in and the Output would be observed. When our programmer arrived,
things were so bad that typical cards were calling for the production of cars with eight tires, no engine,
and three sets of upholstery. In short, a disaster.
As is usual with programming disasters, nobody recognised it as such.
Instead, the whole crew had gone on double shift to get out the bugs, and new programmers, including our
hero, were brought in from all over the country. Naturally, this led to worse confusion than ever, and our
programmer, after a few days, determined that it was hopeless business- and in any case not reason enough
to be away from his family and working night and day. He was roundly condemned for his uncooperative attitude
but was allowed to leave.
While on the plane, he had his first opportunity in a week to reflect calmly. He immediately saw the error
in the approach and perceived that a much better approach would be to divide the work into two phases. The
main operational program would simply loop through a set of specially constructed specifications tables, so
that all decisions would be made with a single test reapplied to different parts of the table. In that way,
the program was at least assured to produce the right number of tires, engines, and so forth. The tables
themselves would be compiled from input written in essentially the form of the engineering specifications.
This would allow the engineering personnel, rather than the programmers, to check the specifications, and
also permit one part of the specification to be changed without changing all parts further down a decision
tree.
By the time he got off the plane, he had coded the two programs. It was a day's work to check them out, and
another two days' work with the local assembly plant engineers to create the specifications in input form.
After a week's testing in the plant, he was about to return to notify Detroit of the news when he got a telegram
saying that the project had been cancelled-since the program was impossible to write.
After a quick call and a plane trip, he was back in Detroit with his version of the program. A demonstration
to the executives convinced them that the project could continue, and then he was asked to make a Presentation
to the rest of the programmers. Naturally, they were a rather cool audience-a phenomenon to which we shall
return in our discussions -but they sat quietly enough through his explanation of the method. Even at the end,
there was a lack of questioning-until the original creator of the old System raised his hand.
"And how long does your program take?" he asked-emphasising the possessive.
"That varies with the input," was the reply, "but on the average, about ten seconds per card."
"Aha," was the triumphant reply. "But my program takes only one second per card."
The members of the audience-who had, after all, all contributed to the one-second version-seemed relieved.
But our hero, who was rather young and naive, was not put down by this remark. Instead, he calmly observed,
"But your program doesn't work. If the program doesn't have to work, I can write one that takes one millisecond
per card-and that's faster than our card reader."
This observation-though it undoubtedly failed to win our hero any friends-contains the fundamental truth
upon which all programming evaluation must be based. If a program doesn't work, measures of efficiency, of
adaptability, or of cost of production have no meaning. Still, we be realistic and acknowledge that probably
no perfect program was ever written. Every really large and significant program has "just one more bug." Thus,
there are degrees of meeting specifications-of "working"- and evaluation of programs must take the type of
imperfection into account.
Any Compiler, for example, is going to have at least "pathological" programs which it will not compile
correctly. What is pathological, however, depends to some extent on your point of view. If it happens in
your program. you hardly classify it as pathological, even though thousands of other users have never
encountered the bug. The producer of the compiler-however, must make some evaluation of the errors on the
basis of the number of users who encounter them and how much cost they incur. This not always done
scientifically. Indeed, it often amounts to an evaluation of who shouts the loudest, or who writes to the
highest executive; But whatever System is chosen, some bugs will remain, and some people will be unhappy
with the same Compiler that satisfies thousands.
In effect, then, there is a difference between a program written for one user and a piece of "Software."
When there are multiple users, there are multiple specifications. When there are multiple specifications,
there are multiple definitions of when the program is working. In our discussions of programming practices,
we are going to have to take into account the difference between programs developed for one user and programs
developed for many. They will be evaluated differently, and they should be produced by different methods.
|