« New project for google | Main | Cheap entertainment »

Ah, those gotos..

Nothing riles up programmers more than a good "goto" discussion as evidenced by today's daily WTF [0]. I sometimes use labels in Java to simplify code.. every now and then that produces the following discussion;

someone: "Hey, that's a goto! You can't use a goto!"
me: "why not"
someone: "they're evil!"
me: "why?" [1]
someone: "Everyone knows that?"
me: "Okay, I must be stupid, why is this bad?"
someone: *mumble* *mumble* *run away*

Perhaps that wasn't verbatim, but it gets the idea across. Often, programmers will scream about something they don't completely understand [2]. I think the best argument against such knee-jerk reactions I've ever seen went something like this..

me: "would you use a return statement in a middle of the method?"
someone: "oh sure! I do that all the time, makes flow easier!" [3]
me: "How about something like this:"
public void someMethod() 
{
   if(something != something_else) 
   {
      goto end;
   } 
   else 
   {
      do_something_else;
   }
   end:
}
someone: "err.."

Of course the above was not Java, but the example is meant to illustrate the fact that maybe a "goto" isn't such a horrible, evil thing when applied correctly.


[0] .. and reading it daily really makes you appreciate your co-workers quite a bit more!
[1] Don't forget, we're talking Java here, there is no unconditional branching in Java
[2] Many will say that about me and often they will be right!
[3] Amusingly enough, that's something I don't like at all and avoid doing.. but try not to preach about, it's often style over substance.

Comments

Gack. I don't think it was "applied correctly" in that example. I never use goto's - never needed them. If there was no other way, then I'd resort to them. I just don't like them - they're like BASIC line numbers (goto 10) and make your code harder to follow.

public void someMethod()
{
if(something > something_else)
{
do_something_else;
}
}

In some languages gotos are bad anyways since they mess with memory and variable settings sometimes. I can't remember which languages, but i do remember covering that in class.

I don't like curly braces on lines by themselves either, unless they're the final one.

By a strange coincidence...

http://beust.com/weblog/archives/000308.html

*woosh* there goes the example over everyone's heads!

I wasn't advocating using a goto instead of a return (ew), I was trying to show that multiple returns from the same method are nothing more than a form of a goto.

Goto commands can be used intelligently. The problem is they can be too easily abused by Jr. Programmers. I like to keep the Goto Genii in the bottle and not use Goto commands.

On the VB side of things, Goto commands were needed for error handling pre-.NET. Thank God for Structured Error Handling!

I've used goto on occassion. When exiting multiple loops, it can make your code far more readable than multiple if(...) break; statements. The if(...) break; syntax also adds multiple tests for the same condition, which, IMO, is a far worse programming practice.

The multiple 'goto end' == 'return' analogy only works for methods returning void.

And as someone posted above, Cedric's post is also very relevant to this (the single return vs multiple returns, with values being returned).

I must admit I've used gotos in the past, as a way to break out of some complex loops. To me they are necessary evil to be used as a last resort and defenitely a sign of code smell.

Why? Because it goes against the natural flow of the Java program, and helps creating spagetti code. It's all about what you read on the screen, not about what the computer will ultimately execute (in the end of the day, all the cpu sees are instructions and gotos anyway).

It's definitely a style thing. If you have an awful complicated loopy thing you can:

1. Return in the middle
2. Use a goto
3. Try to break it into a bunch of methods
4. Use breaks, continues etc.

I lean towards 3 and then 1, but I don't think any method is superior. They all have their drawbacks:

1. Multiple points of return make debugging harder
2. Gotos can make working backwards harder.
3. Too many methods means you can't possibly see them all on one screen and keep them in place.
4. Breaks and continues are easy to miss, plus you then have to add checks to see if the whatever you were searching, adding etc is done.

Anyway, bad code can be written using any method. I think the backlash from GOTO is that everyone is slightly embarrased by their first ever program:

10 PRINT STEVE IS COOL
20 GOTO 10

One should also include the "break" statement in this discussion. What is a break but a goto statement where the destination is implicit rather than explicit?

In some sense, goto is natural because that command exists more at the machine level, but the very reason we have higher level programming languages is that machine level programming is incomprehensible to most humans. By forcing folks to obey certain style dogmas, like avoiding goto, our programmers become constrained to writing more comprehesible code.

Of couse, dogma can get you into trouble sometimes, which I believe is Kasia's point. However, just because the dogma is wrong 5% of the time, doesn't mean that we should throw it away. We need something to keep the idiots honest the other 95% of the time; and THAT is the real issue. (There are a lot of idiots out there, and yes, some of the are programmers).

Exactly, and Java's labeled break, which K admitted she uses, is essentially a restricted form of explicit goto, and really represents the chief remaining use of goto in languages like C and C++ that don't have such breaks. (Another use being cleanup on exceptional method return, but in C++ that is far better done with Stroustrup's resource-acquisition-is-initialization idiom or a catch-rethrow.)

Java can survive without a goto only because it provides other features that provide the same thing in key cases.

Your goto is not exactly the same as a return, as it's possible to call other statements following the goto. In a return, you know that the method ends there. Excluding wierd things like finally blocks.

So... if you don't like returns, what's your opinion on exceptions like this?

public void someMethod()
{
if(something != something_else)
{
throw new IllegalStateException("foo");
}
else
{
do_something_else;
}
}