BY PATRICK BASS, ANTIC ST PROGRAM EDITOR
THE GREAT GOTO DEBATE
Never use a GOTO
Not every concept in these two articles has already been covered in the first six New Owners Columns. Any unexplained details will be covered in future lessons. But we feel that this debate on seemingly conflicting philosophies of programming contains valuable ideas for all beginning and intermediate programmers. And you'll notice that despite some different opinions, Bass and Hayes agree that the most important thing is for programs to be clean, clear and understandable.-ANTIC ED)
GOTO is a BASIC language command that unconditionally transfers program execution from one line to another -anywhere else in the program. An example would be: 100 GOTO 850. When the computer tries to execute line 100, control is transferred to line 850, if there is one...
After bitter experience, I don't use GOTOs in my own programming. In fact, I believe that if a program has any GOTOs at all, there's a mistake in logic somewhere. I get a lot of "goodnatured" flak at the office about this.
I admit I occasionally GOTO in short BASIC programs which will only exist briefly-but never when I know the code will be read and possibly changed by other programmers. Here's why:
None of us is perfect, so we make mistakes. And other people cannot read our minds. This is an important point, because computer programs are nothing more than the crystallization of the programmer's thought processes saved on disk.
Think about that for a second. It is the programmer who must break each task down into its various parts and then select the appropriate machine instructions which appear to accomplish the job.
One of the beautiful aspects of programming computers is that for any problem, there are at least as many solutions as there are programmers working on it. An answer that seems perfectly clear to you could stop other programmers dead in their tracks. There must be some way to group instructions together so that someone else can follow the original programmer's thoughts without undue confusion.
FROM THE GROUND UP
When a person starts learning to program, the GOTO is a GODSEND. It will take you anywhere in no time flat (even deep into trouble). But the first few programs a person writes are not likely to be too large, probably less than 100 lines of code. Any reasonably well-organized beginner can keep in their head the entire logic flow of a program this size.
Aside from the risk of slipping into messy logic or doing stupid things like GOTOing out of the middle of a subroutine so many times that the memory stack overflows (see last month's New Owners Column), there are no real reasons not to use a GOTO. After all, GOTOs do work, they are available and they do keep the program shorter.
But as budding programmers become more confident in their ability, the size of their programs slowly increase. Until one night while tracking down one of the many "bugs" which always seem to inhabit their programs, they realize they've lost control of the overall logic. This seems to happen at around 250-500 lines of code.
Indeed, this was one of my own biggest stumbling blocks. There I was, locked away inside my little room wondering how in the world someone put together a program 2,000, 5,000, even 10,000 lines long. In my naivete, I thought these professional programmers had some form of Holy Grail they could turn to for keeping the code straight in their minds. I was wrong.
Enlightenment came when I visualized a connection between "building" a house and "building" a program. A house is built of many small nails and boards, each of which by itself contributes little to the overall building. In the same way a program is built up of many small instructions which, taken by themselves, contribute little.
Nobody expects contractors to remember each and every nail and board they build a house with, or to remember the dimensions of the south wall in the third hall on the second floor. But contractors work from written plans and I found out that it is possible for programmers to work from written plans also.
These plans are the basis of Structured Programming, which itself takes advantage of the fact that any program, or rather any sequence of instructions, can be built up in groups of only three different "structures."
These three structures are:
1. A simple sequence of instructions. BASIC, for example, will start program execution at the lowest line number, then proceed to the next higher line number, then the next higher and so forth, unless told to do otherwise.
2. A conditional branch structure where execution of a sequence of instructions depends on a true or false condition. In BASIC this is represented by the IF/THEN structure.
3. A loop structure where a sequence of instructions is repeated as long as some specified condition remains true. In BASIC, this is represented by the FOR/NEXT verb structure.
However, notice that nowhere above did we mention unconditional branches-or more simply, the GOTO. Why? Because we don't need it.
Greater minds than yours or mine have proven that with only the above three structures, any program of any size may be built-with each task in its own block of code. The program itself can be taken as a structure that encompasses a whole collection of structures, each of which is built up of smaller structures and so forth.
This makes the overall sequence of operation easy to follow. Each individual section of the program may be tested and debugged individually as the program develops, and once running they need not be examined again. Indeed, they may be treated as "black boxes," which do a single job and nothing else.
Each related group of structures may be grouped together to form a larger black box that does a somewhat larger job. For example, we can write separate routines to get a filename, open a file, write the file and then close the file. But then we can group these routines together into a single, "Write a file to disk" structure.
A Structured Program is somewhat self-documenting and, when properly written, should almost explain itself completely It should be as easy to read as a short story, with the structures acting as the "outline" of the program.
But remember, I'm not promising you a Rose Garden.
To properly write a program in a structured form, you need to use a somewhat high-level language which allows the formation and use of the three structures. Working in machine language, for example, it is possible to construct the three different structures. But they may not be completely visible to the casual reader. A person needs to GOTO (sorry) a higher language such as BASIC, Pascal, or C before these structures jump out at the reader.
By limiting yourself to only three structures, some programs can be downright awkward to write. They also might execute more slowly and consume more memory than a program which doesn't follow these rules.
Lastly, most programmers do not start out learning to program in a structured environment. The need for structure does not become evident until the programmer acquires enough skill to write fairly long programs. And human beings tend to resist learning new methods.
Overall, programming in a structured environment forces disipline on your program design. It forces the programmer to think in terms of individual sections of code having only a single entrance and a single exit, sections which can be individually checked for logical accuracy.
So use the GOTO if you desire, but be warned that eventually you'll get into trouble. For small programs the difference will be small. But as your programs grow, you may find yourself wasting hours to track down bugs directly related to the actions behind a forgotten unconditional branch. Believe me, it's not worth the programming time you save by using an unconditional GOTO.
And please, if you ever expect other persons to read your programs,
take pity on them, for you know they aren't as smart as you.
BY FRANK HAYES, II COMPUTING ASSISTANT EDITOR
THE GREAT GOTO DEBATE
Part II. Sometimes GOTOS are best
Here are two of my favorite myths about using the GOTO command in BASIC:
1. There's nothing wrong with GOTO. Use it whenever you like!
2. There's nothing right with GOTO. Don't use it-ever!
One crowd believes that a GOTO is a very convenient way of getting from one place in a program to another, and that you can safely use it throughout any BASIC program. Actually, it isn't -and you can't.
Another group-mostly enthusiasts of Pascal and other "highly structured" languages-insists that the GOTO is to be hated and feared, that it destroys programs and damages programmers minds, and that it should never be used under any circumstances anywhere.
Why do people develop such an extreme love or loathing of GOTOs? I suspect it mainly has to do with a fundamental misunderstanding of what a GOTO is, what it means, and how it should be used-and the misunderstanding is tied to some mistaken ideas about programming in general.
BASIC's GOTO statement is a simple branching statement-a way of changing the flow of a program. Every programming language has ways of changing the program flow, and very few programs of any length follow a simple linear path from beginning to end. In fact, the reason we design computer programs is to tell the computer when and how to make decisions based on the available data, and change program flow accordingly.
Every microprocessor has branching capability built into it-and every
programmer regularly uses branching, even in assembly language. The only
difference is that some branching is obvious and some is hidden.
logic, there's no
real reason not to
A good example of hidden branching in BASIC is the FOR/NEXT construction. Actually, in most versions of BASIC it's the only example of a hidden GOTO.
This is how FOR/NEXT works:
10 FOR A=1 TO 10
20 PRINT "HELLO"
30 NEXT A
It is simply a variation of:
10 LET A=l
20 PRINT "HELLO"
30 LET A=A+1
40 IF A<=l0 THEN GOTO 20
How is the first version better than the second? One way is obvious -the version using FOR/NEXT takes fewer statements. But there are two more important factors. The first is that the FOR/NEXT construction always automatically remembers where it should branch to. Suppose you added a line 15 to each of the two short routines above:
15 PRINT A
In the version with FOR/NEXT, the program automatically knows to branch up to line 15 when it repeats the loop. Without FOR/NEXT, you'll also have to change line 40, so that the program will GOTO line 15 instead of 20.
The second critical factor is that the FOR/NEXT loop makes it much clearer what's going on. It's obviously a loop-and it's clear where the loop begins and ends, and what will make it stop looping.
That's the real reason FOR/NEXT is better than GOTO for a loop like this -it makes the program clearer, cleaner, and more straightforward.
Some programming languages have many different kinds of loop structures. BASIC typically has just the FOR/NEXT loop, but it's easy to build other looping structures in BASIC -DO loops and WHILE loops and UNTIL loops- using IF/THEN and GOTO statements. It's easily the most effective use you can make of GOTO, as long as you make clear exactly what you're doing.
FOR/NEXT is clearly better than GOTO for at least some loops. Why not use it for all loops? After all, that would get rid of all GOTOs and also help make a program s structure clear-wouldn't it?
Unfortunately, no. When you try to twist FOR/NEXT around so that it acts as a general purpose loop, it generally creates more problems than it solves.
A typical way of using FOR/NEXT as a general purpose loop is to set the STEP to 0-for example:
10 FOR A=1 TO 2 STEP 0
20 INPUT A$
30 IF A$='X" THEN A=2
40 NEXT A
In this example, because of the STEP 0 option, the FOR/NEXT loop will continue to loop until A$ is X.
What's wrong with this? Well, it will usually work. But it's a classic example of tricky programming-a programmer who's being more clever than needed. The same code could be written like this:
10 REM LOOP UNTIL A$=X
20 INPUT A$
30 IF A$<>'X" THEN GOTO 20
The version with the IF/THEN GOTO is shorter. It runs faster. It doesn't use any unnecessary variables, which waste time and memory space. Most important, what's going on is expressed as simply and clearly as possible.
WILL IT WORK?
As I said, I suspect that GOTO paranoia is tied to mistaken notions about programming. One common mistake by beginning programmers is that if a program works once-or twice, or even dozens of times-then it will always work..
Actually, people in all walks of life tend to think that just because something was once tested sucessfully, it will keep working. The sad truth is that if a system is very complex, it's just about impossible to test it thoroughly just by running it over and over.
No matter how many times you run it through, a really complex system has too many possible complications that could crop up at odd times in unexpected ways. A common example of this is when you crash a program by mistyping a couple of keys and accidentally sending the computer a destructive instruction.
There is a way of making sure a program will work, but it doesn't involve testing in the usual sense. If a program has a clear, easily-understood structure which flows cleanly between well-defined parts, it's easy to make sure it will work and easy to change or improve the program.
But if a program has GOTOs that bounce from the middle of one routine
into the middle of another, proving it will always work can be next
to impossible. That's the "spaghetti programming" which sets almost any
experienced programmer's teeth on edge - and it has given GOTOs a bad reputation.
such extreme love
or loathing of
Spaghetti code is impossible to change safely, because it's impossible to understand. It's the worst possible way for you to use a GOTO-because there's no way to make clear exactly what you're doing.
It's easy to overreact to the unprovability of programs. And that's where another common mistaken idea about programming shows up-the notion that a computer language, or any system of rules, can somehow eliminate any chance of error. That's the basis for "Structured Programming," in which the language, rather than the programmer, is supposed to be responsible for making sure there are no mistakes in the program's structure.
Notice that I put "Structured Programming" in quotes, with capital letters. I'm not just talking about structured programs. All of your programs should be well-structured. If they're not, it means you're programming without a plan, and your programs are lucky if they get anywhere at all. Well-designed, well-structured programs are the only kind you can really trust-and the only kind you sould write.
On the other hand, "Structured Programming" is a philosophy that insists it's more important to use "structures" than to program efficiently. "Structures" are supposed to be so important, because they make a program "self-documenting."
But in the real world, programs need to work efficiently. If a program spends too much time inside "structures," it's badly designed. If it wastes time or space, it's simply not the best program it can be.
More important, in the real world there's no such thing as a "self-documenting" program. A looping structure may help clarify the way a program works, but it's no replacement for making explicit comments (REMarks) in REM statements about how the program works.
The toughest thing about any program is keeping track of what's going on. You can keep track of only so many things in your head at once. When a program gets more complex than that, you'll start to forget details. And if you want to change or improve your program later on, the chance that you'll remember all its nuances weeks or months from now is just about nil.
There's only one practical way to keep track-doing it right in the program itself, with your logical choice of program statements and with REM text statements. Don't trust your memory for anything.
That's the way to make your program structure clear and provable. Design philosophies can help, but they're not much good unless you actually use REMark comments - lots and lots of comments-to document your program.
So, to sum up-don't use more GOTOs than you absolutely must. But avoid tricky programming gimmicks that replace GOTOs with confusion and inefficiency.
Just keep your program as clear, clean and straightforward as you can make it. And as you go, explain with REM statements exactly how it works. And you'll never have to worry about GOTOs again!