a companion discussion area for blog.codinghorror.com

I'd Consider That Harmful, Too


#21

GOTO is not a performance improvement. If it is the only way to improve the performance of your program then something went wrong around the design phase.


#22

A few years ago I found a paper titled “Gotos Considered Harmful and Other Programmers’ Taboos”, from a Workshop of the “Psychology of Programming Interest Group”. You can find it at http://www.ppig.org/papers/12th-marshall.pdf.

Avoiding a goto when it is the correct option - by using Jim Conyngham’s do/while/break technique - is a very bad idea. It seriously harms readability because the programmer EXPECTS that the loop will be taken at least once with some set of inputs. Targeted local gotos, as present in all modern languages in preference to line-numbered global gotos, are clear enough to understand. I would generally restrict gotos to FORWARD jumps only, a backward jump is a loop and should be coded as one.

The overloaded use of ‘break’ in C-based languages - to indicate the end of a case in a switch statement, and to break out of a loop - may require you to use a goto if you need to break out of a loop when you’re in a switch statement in a loop. One solution is of course to put the switch statement into a separate function.

You’ll use goto rarely - maybe a few times a year, in most cases. If you’re using it in C++ to jump to common cleanup routines, your time might be better invested in making automatic cleanup, via stack local objects’ destructors, work properly. In C#, you should be looking at IDisposable and using blocks. But goto is a handy tool to have, if used judiciously and sparingly.


#23

it’s only a minor hazard compared to the COMEFROM statement,
but I’m glad to have both of those largely behind us

COMEFROM is alive and well, and very widely used. The only change made was that the marketing guys rebranded it as ‘exception handling’.


#24

In the Jurassic era when I helped students debug their programs, one guy had a program where all the variables were girls’ names. He also deliberately introduced a slight inefficiency into his program, with the statement: goto bed;

One of my father’s colleagues, with a lower level of creativity, had this in a program: goto hell;

As for me and creativity, well, I got 0.


#25

I hate goto’s for the simple reason that people who shouldn’t be programming in the first place see them and think they’re a perfect hammer. Then they start seeing everything else as nails.

I’ve debugged plenty of production code with goto’s all over the place, and then the original programmers sit there wondering why it doesn’t work right.


#26

I don’t really agree with the idea of returning early from functions. As Jeff says it is just a tightly scoped GOTO and I think it can adversely affect readability.

In fact our in-house coding standard explicitly recommends against it.
Multiple return point in the same function makes it harder to understand and goes against the “don’t make me think” principle".

Generally the only reason I would use early return is for basic pre-condition sanity checking at the start of a function.

e.g.

char* some_function( char* somestring, int somenumber )
{
// Sanity checks
if ( somestring == NULL ) return NULL;
if ( somenumber = 0 || somenumber LIMIT ) return NULL;

// Do real work..

}

And even there I would consider exceptions instead, if they were available.

Similarly I think breaking out of loops is overused.
Why not just add a boolean exit condition to the loop?
It makes the intent clearer and means there are less paths to consider.

e.g. if I write

for ( int i = 0; i LIMIT !found_thing; i++ )

then you know just by reading that line that I am traversing through i until I hit a limit or find the thing I am looking for. Using break would mean the exit condition was less clear.


#27

I’ve seen goto in case statements in C# to get round the “can’t fall through” compiler error when you have something in a case.

This becomes another religious issue in the end. Sure, more people are on the same side of the fence over the whole GOTO thing (me included), but where d’you draw the line? People will argue ceaselessly that VB isn’t a proper programming language, others will say that you shouldn’t have single-line if statements like this:

if (!ValidateInput()) return;

In these examples it’s less clear who’s right or wrong. In this particular example my opinion differs from that of a colleague of mine, where he doesn’t like it but I think there are two situations where it’s okay (the one above, and when you’re disposing objects in finally blocks). Neither of us is right or wrong, we just have preferences. In the case of GOTO, much as I dislike seeing it, the only reason we think it’s “wrong” is because enough people think it is.


#28

Neil: yes, C# has a sub-type of goto with restricted scope, “goto case”, which is particularly for declaring fall-throughs in switch statements.

Although this uses the dreaded cursed word, it is not a “real goto” and it is considerably less evil than the implicit fall-through used in C/C++


#29

For the people who think GOTO is so incredibly horrible that it shouldn’t even be in a language, I would suggest that you read something from some dude named “Donald Knuth” who had something to say on the subject.

http://pplab.snu.ac.kr/courses/adv_pl05/papers/p261-knuth.pdf


#30

I use it from time to time, I’m just that crazy … but I always have a safety variable to make sure I don’t lock up :wink:


#31

Your essay (and Earth) - mostly harmless.


#32

The “go to” discussion: old news
The “Considered harmful” discussion: boring


#33

The most common use I have for a goto is in image processing where I am usually using two loops and I need a double break. It really can make code more readable.

for (y = 0; y h; y++)
for (x = 0; x w; x++)
if (image[x][y] == 0)
goto found;
found:

Compared to this

for (y = 0; y h; y++)
{
for (x = 0; x w; x++)
if (image[x][y] == 0)
break;
if (x w)
break;
}

or this

for (y = 0; (y h) (image[x][y] != 0); y++)
for (x = 0; (x w) (image[x][y] != 0); x++)
{}

In the first case there is only one place where I check if I’m done, in the other two there are two places, thus they have added complexity.


#34

mccoyn: But couldn’t you just write that as:

for (y = 0; y h !found; y++)
for (x = 0; x w !found; x++)
found = (image[x][y] == 0);


#35

(By the way Jeff, it would be really handy to have some kind of PRE or CODE tag available to us when posting code snippets!)


#36

Graham:

You are still writing two tests, just caching the result (and fixing my bug).


#37

In the 80s I saw an article in a mainframer magazine that started off saying all logic can be expressed by sequence, alternation and iteration. From this he concluded that COBOL “perform” was “harmful” and showed how to simulate the three major structures with GOTO. For example, don’t use perform while, use GOTO the top of the loop. With no subroutines, his outermost structures were the length of the program. (I was reminded of this the other day when I opened a Java class with one 5,000 line method.)

I’ve never seriously missed GOTO in Java.


#38

It seems like there is a new modern trend in essays. Which I would call “is dead” :slight_smile: Remember, “Computer science is dead?” “Microsoft is dead?” Who’s next? :slight_smile:


#39

I did not think you had many FORTRAN or BASIC programmers reading your blog . . .


#40

You can still make a case for GOSUB for that matter in languages with only two levels of procedure scope.

Some procedure that needs to use the same sequence of code operating on a hefty collection of local data items more than once. It isn’t worth the overhead of making an out-of-scope procedure and passing a raft of parameters to it.