Design a program

First, decide on your ultimate goal. Be optimistic. Maybe you’d like the computer to play the perfect game of chess? or translate every English sentence into French?

Research the past

Whatever you want the computer to do, someone else probably thought of the same idea already and wrote a program for it.

Find out. Ask your friends. Ask folks in nearby schools, computer stores, computer centers, companies, libraries, and bookstores. Look through books and magazines. There are even books that list what programs have been written. Ask the company you bought your computer from.

Even if you don’t find exactly the program you’re looking for, you may find one that’s close enough to be okay, or that will work with just a little fixing or serve as part of your program or at least give you a clue as to where to begin. In a textbooks or magazines, you’ll probably find a discussion of the problem you’re trying to solve and the pros and cons of various solutions to it — some methods are faster than others.

Remember: if you keep your head in the sand and don’t look at what other programmers have done already, your programming effort may turn out to be a mere exercise, useless to the rest of the world.

Simplify

Too often, programmers embark on huge projects and never get them done. Once you have an idea of what’s been done before and how hard your project is, simplify it.

Instead of making the computer play a perfect game of chess, how about settling for a game in which the computer plays unremarkably but at least doesn’t cheat? Instead of translating every English sentence into French, how about translating just English colors? (We wrote that program already.)

In other words, pick a less ambitious, more realistic goal, which if achieved will please you and be a steppingstone to your ultimate goal.

Finding a bug in a program is like finding a needle in a haystack: removing the needle is easier if the haystack is small than if you wait until more hay’s been piled on.

Specify the I/O

Make your new, simple goal more precise. That’s called specification. One way to be specific is to draw a picture, showing what your screen will look like if your program’s running successfully.

In that picture, find the lines typed by the computer. They become your program’s PRINT statements. Find the lines typed by the human: they become the INPUT statements. Now you can start writing your program: write the PRINT and INPUT statements on paper, with a pencil, and leave blank lines between them. You’ll fill in the blanks later.

Suppose you want the computer to find the average of two numbers. Your picture will look like this:

What's the first number? 7

What's the second number? 9

The average is 8

Your program at this stage will be:

CLS

INPUT "What's the first number"; a

INPUT "What's the second number"; b

etc.

PRINT "The average is"; c

All you have left to do is figure out what the "etc." is. Here’s the general method.…

Choose your statements

Suppose you didn’t have a computer. Then how would you get the answer?

Would you have to use a mathematical formula? If so, put the formula into your program, but remember that the equation’s left side must have just one variable. For example, if you’re trying to solve a problem about right triangles, you might have to use the Pythagorean formula a²+b²=c²; but the left side of the equation must have just one variable, so your program must say a=SQR(c^2-b^2), or b=SQR(c^2-a^2), or c=SQR(a^2+b^2), depending on whether you’re trying to compute a, b, or c.

Would you have to use a memorized list, such as an English-French dictionary or the population of each state or the weight of each chemical element? If so, that list becomes your DATA, and you need to READ it. If it would be helpful to have the data numbered — so the first piece of data is called x(1), the next piece of data is called x(2), etc. — use the DIM statement.

Subscripts are particularly useful if one long list of information will be referred to several times in the program.

Does your reasoning repeat? That means your program should have a loop. If you know how many times to repeat, say FOR...NEXT. If you’re not sure how often, say DO...LOOP. If the thing to be repeated isn’t repeated immediately, but just after several other things have happened, make the repeated part be a SUB procedure.

At some point in your reasoning, do you have to make a decision? Do you have to choose among several alternatives? To choose between two alternatives, say IF...THEN. To choose among three or more alternatives, say SELECT CASE. If you want the computer to make the choice arbitrarily, "by chance" instead of for a reason, say IF RND<.5.

Do you have to compare two things? The way to say "compare x with y" is: IF x = y THEN.

Write pseudocode

Some English teachers say that before you write a paper, you should make an outline. Some computer teachers give similar advice about writing programs.

The "outline" can look like a program in which some of the lines are written in plain English instead of computerese. For example, one statement in your outline might be:

a = the average of the twelve values of x

Such a statement, written in English instead of in computerese, is called pseudocode. Later, when you fill in the details, expand that pseudocode into the following:

sum = 0

FOR i = 1 TO 12

sum = sum + x(i)

133 NEXT

average = sum / 12

Organize yourself

Keep the program’s over-all organization simple. That will make it easier for you to expand the program and find bugs. Here’s some folklore, handed down from generation to generation of programmers, that will simplify your organization.…

Use top-down programming. That means write a one-sentence description of your program; then expand that sentence to several sentences; then expand each of those sentences to several more sentences; and so on, until you can’t expand any more. Then turn each of those new sentences into lines of program. Then your program will be in the same order as the English sentences and therefore organized the same way as an English-speaking mind.

A variation is to use SUB procedures. That means writing the essence of the program as a very short main procedure; instead of filling in the grubby details immediately, replace each piece of grubbiness by a SUB procedure. Your program will be like a good book: your main procedure will move swiftly, and the annoying details will be relegated to the appendices at the back; the appendices are the SUB procedures. Make each procedure brief — no more than 20 lines — so the entire procedure can fit on the screen; if it starts getting longer and grubbier, replace each piece of grubbiness by another SUB procedure.

Avoid GO TO. It’s hard for a human to understand a program that’s a morass of GO TO statements. It’s like trying to read a book where each paragraph says to turn to a different page! When you must say GO TO, try to go forward instead of backwards and not go too far.

Use variables

After you’ve written some lines of your program, you may notice that your reasoning "almost repeats": several lines bear a strong resemblance to each other. You can’t use DO...LOOP or FOR...NEXT unless the lines repeat exactly. To make the repetition complete, use a variable to represent the parts that are different.

For example, suppose your program contains these lines:

PRINT 29.34281 + 9.876237 * SQR(5)

PRINT 29.34281 + 9.876237 * SQR(7)

PRINT 29.34281 + 9.876237 * SQR(9)

PRINT 29.34281 + 9.876237 * SQR(11)

PRINT 29.34281 + 9.876237 * SQR(13)

PRINT 29.34281 + 9.876237 * SQR(15)

PRINT 29.34281 + 9.876237 * SQR(17)

PRINT 29.34281 + 9.876237 * SQR(19)

PRINT 29.34281 + 9.876237 * SQR(21)

Each of those lines says PRINT 29.3428 + 9.87627 * SQR(a number). The number keeps changing, so call it x. All those PRINT lines can be replaced by this loop:

FOR x = 5 TO 21 STEP 2

PRINT 29.34281 + 9.876237 * SQR(x)

NEXT

Here’s a harder example to fix:

PRINT 29.34281 + 9.876237 * SQR(5)

PRINT 29.34281 + 9.876237 * SQR(97.3)

PRINT 29.34281 + 9.876237 * SQR(8.62)

PRINT 29.34281 + 9.876237 * SQR(.4)

PRINT 29.34281 + 9.876237 * SQR(200)

PRINT 29.34281 + 9.876237 * SQR(12)

PRINT 29.34281 + 9.876237 * SQR(591)

PRINT 29.34281 + 9.876237 * SQR(.2)

PRINT 29.24281 + 9.876237 * SQR(100076)

Again, let’s use x. All those PRINT lines can be combined like this:

DATA 5,97.3,8.62,.4,200,12,591,.2,100076

FOR i = 1 TO 9

READ x

PRINT 29.34281 + 9.876237 * SQR(x)

NEXT

This one’s even tougher:

PRINT 29.34281 + 9.876237 * SQR(a)

PRINT 29.34281 + 9.876237 * SQR(b)

PRINT 29.34281 + 9.876237 * SQR(c)

PRINT 29.34281 + 9.876237 * SQR(d)

PRINT 29.34281 + 9.876237 * SQR(e)

PRINT 29.34281 + 9.876237 * SQR(f)

PRINT 29.34281 + 9.876237 * SQR(g)

PRINT 29.34281 + 9.876237 * SQR(h)

PRINT 29.34281 + 9.876237 * SQR(i)

Let’s assume a, b, c, d, e, f, g, h, and i have been computed earlier in the program. The trick to shortening those lines is to change the names of the variables. Throughout the program, say x(1) instead of a, say x(2) instead of b, say x(3) instead of c, etc. Say DIM x(9) at the beginning of your program. Then replace all those PRINT lines by this loop:

FOR i = 1 TO 9

PRINT 29.34281 + 9.876237 * SQR(x(i))

NEXT

Make it efficient

Your program should be efficient. That means it should use as little of the computer’s time and memory as possible.

To use less of the computer’s memory, make your DIMensions as small as possible. Try writing the program without any arrays at all; if that turns out to be terribly inconvenient, use the smallest and fewest arrays possible.

To use less of the computer’s time, avoid having the computer do the same thing more than once.

These lines force the computer to compute SQR(8.2 * n + 7) three times:

PRINT SQR(8.3 * n + 7) + 2

PRINT SQR(8.3 * n + 7) / 9.1

PRINT 5 - SQR(8.3 * n + 7)

You should change them to:

k = SQR(8.3 * n + 7)

PRINT k + 2

PRINT k / 9.1

PRINT 5 - k

These lines force the computer to compute x ^ 9 + 2 a hundred times:

FOR i = 1 TO 100

PRINT (x ^ 9 + 2) / i

NEXT

You should change them to:

k = x ^ 9 + 2

FOR i = 1 TO 100

PRINT k / i

NEXT

These lines force the computer to count to 100 twice:

sum = 0

FOR i = 1 TO 100

sum = sum + x(i)

NEXT

PRINT "The sum of the x's is"; sum

product = 1

FOR i = 1 TO 100

product = product * x(i)

NEXT

PRINT "The product of the x's is"; product

You should combine the two FOR...NEXT loops into a single FOR...NEXT loop, so the computer counts to 100 just once. Here’s how:

sum = 0

product = 1

FOR i = 1 TO 100

sum = sum + x(i)

product = product * x(i)

NEXT

PRINT "The sum of the x's is"; sum

PRINT "The product of the x's is"; product

Here are more tricks to make your program run faster.…

Instead of exponents, use multiplication.

slow: y = x ^ 2

faster: y = x * x

If your program doesn’t involve decimals or big numbers, put this statement at the top of your program:

DEFINT A-Z

If your program involves just a few decimals or big numbers, begin your program by saying DEFINT A-Z; then put the symbol "&" after every variable that stands for a long integer, and put the symbol "!" after every variable that stands for a single-precision real number.

Test it

When you’ve written a program, test it: run it and see whether it works.

If the computer does not gripe, your tendency will be to say "Whoopee!" Don’t cheer too loudly. The answers the computer is printing might be wrong. Even if its answers look reasonable, don’t assume they’re right: the computer’s errors can be subtle. Check some of its answers by computing them with a pencil.

Even if the answers the computer prints are correct, don’t cheer. Maybe you were just lucky. Type different input, and see whether your program still works. Probably you can input something that will make your program go crazy or print a wrong answer. Your mission: to find input that will reveal the existence of a bug.

Try six kinds of input.…

Try simple input

Type in simple integers, like 2 and 10, so the computation is simple, and you can check the computer’s answers easily.

Try input that increases

See how the computer’s answer changes when the input changes from 2 to 1000.

Does the change in the computer’s answer look reasonable? Does the computer’s answer go up when it should go up, and down when it should go down?… and by a reasonable amount?

Try input testing each IF

For a program that says —

IF x < 7 THEN GOTO 10

input an x less than 7 (to see whether line 10 works), then an x greater than 7 (to see whether the line underneath the IF line works), then an x equal to 7 (to see whether you really want "<" instead of "<="), then an x very close to 7, to check round-off error.

For a program that says —

IF x ^ 2 + y < z THEN GOTO 10

input an x, y, and z that make x ^ 2 + y less than z. Then try inputs that make x ^ 2 + y very close to z.

Try extreme input

What happens if you input:

a huge number, like 45392000000 or 1E35?

a tiny number, like .00000003954 or 1E-35?

a trivial number, like 0 or 1?

a typical number, like 45.13?

a negative number, like -52?

Find out.

If the input is supposed to be a string, what happens if you input aaaaa or zzzzz? What happens if you capitalize the input? If there are supposed to be two inputs, what happens if you input the same thing for each?

Try input making a line act strange

If your program contains division, try input that will make the divisor be zero or a tiny decimal close to zero. If your program contains the square root of a quantity, try input that will make the quantity be negative. If your program says "FOR i = x TO y", try input that will make y be less than x, then equal to x. If your program mentions x(i), try input that will make i be zero or negative or greater than the DIM.

Try input that causes round-off error: for a program that says "x - y" or says "IF x = y", try input that will make x almost equal y.

Try garbage

Computers often print wrong answers. A computer can print a wrong answer because its circuitry is broken or because a program has a bug. But the main reason why computers print wrong answers is incorrect input. Incorrect input is called garbage and has several causes.…

The user’s finger slips Instead of 400, he inputs 4000. Instead of 27, he inputs 72. Trying to type .753, he leaves out the decimal point.

The user got wrong information He tries to input the temperature, but his thermometer is leaking. He tries to input the results of a questionnaire, but everybody who filled out his questionnaires lied.

The instructions aren’t clear The program asks "How far did the ball fall?" but the user doesn’t know whether to type the distance in feet or in meters.

Is time to be given in seconds or minutes? Are angles to be measured in degrees or radians?

If the program asks "What is your name?" should the user type "Joe Smith" or "Smith,Joe" or just "Joe"?

Can the user input "y" instead of "yes"?

Maybe the user isn’t clear about whether to insert commas, quotation marks, and periods. If several items are to be typed, should they be typed on the same line or on separate lines? If your program asks "How many brothers and sisters do you have?" and the user has 2 brothers & 3 sisters, should he type "5" or "2,3" or "2 brothers and 3 sisters"?

For a quiz that asks "Who was the first U.S. President?" what if the user answers "George Washington" or simply "Washington" or "washington" or "G. Washington" or "General George Washington" or "President Washington" or "Martha’s husband?" Make the instructions clearer:

Who was the first U.S. President (give just his last name)?

The user tries to joke or sabotage Instead of inputting his name, he types an obscene comment. When asked how many brothers and sisters he has, he says 275.

Responsibility As a programmer, it’s your duty to include clear directions for using your program, and you must make the program reject ridiculous input.

For example, if your program is supposed to print weekly paychecks, it should refuse to print checks for more than $10000. Your program should contain these lines:

10 INPUT "How much money did the employee earn"; e

IF e > 10000 THEN

PRINT e; "is quite a big paycheck! I don't believe you."

PRINT "Please retype your request."

GO TO 10

END IF

That IF line is called an error trap (or error-handling routine). Your program should contain several, to prevent printing checks that are too small (2¢?) or negative or otherwise ridiculous ($200.73145?)

To see how your program reacts to input that’s either garbage or unusual, ask a friend to run your program. That person might input something you never thought of.

Document it

Write an explanation that helps other people understand your program.

An explanation is called documentation. When you write an explanation, you’re documenting the program.

You can write the documentation on a separate sheet of paper, or you can make the computer print the documentation when the user runs or lists the program.

A popular device is to begin the program by making the computer ask the user:

Do you need instructions?

You need two kinds of documentation: how to use the program, and how the program was written.

How to use the program

Your explanation of how to use the program should include:

the program’s name

how to get the program from the disk

the program’s purpose

a list of other programs that must be combined with this program, to make a workable combination

the correct way to type the input and data (show an example)

the correct way to interpret the output

the program’s limitations (input it can’t handle, a list of error messages that might be printed, round-off error)

a list of bugs you haven’t fixed yet

How the program was written

An explanation of how you wrote the program will help other programmers borrow your ideas, and help them expand your program to meet new situations. It should include:

your name

the date you finished it

the computer you wrote it for

the language you wrote it in (probably BASIC)

the name of the method you used ("solves quadratic equations by using the quadratic formula")

the name of the book or magazine where you found the method

the name of any program you borrowed ideas from

an informal explanation of how program works ("It loops until x>y, then computes the weather forecast.")

the purpose of each SUB procedure

the meaning of each variable

the significance of reaching a line (for a program saying "IF x < 60 THEN GOTO 1000", say "Reaching line 1000 means the student flunked.")