Pages

Monday, May 7, 2007

Tackling the elusive goto

Obviously this is in response to Zooba’s post Break/Continue vs. Goto. Whilst I don’t consider myself a purist. I do not like the idea of using explicit gotos.

The first thing I want to spell out is that eclipse will happily tell me where the break is going to drop to. True: if I change an if to a while, the location of where that is going to go will change but if you are changing an if to a while, you are probably going to have to fix a lot more that where you drop out to. The delphi IDE I was using at Advatel (can’t remember the name of it though) would also tell me where breaks would jump to when the break word was selected. With a nice little addon, it would also draw coloured lines on the screen.

As for simplifying the code. I actually managed to get it shorter than your goto example.
[java]
do {
for (int i = 0; i < 100 && getMeOutOfHere == false; i++)
{
p += 8; // or some constant
if (p < eof && DoStuff(i, j))
{
j -= 10;
}
else
{
getMeOutOfHere = true;
p = eof; // if the presevation of p to eof IS required
}
}
}
while (getMeOutOfHere == false);

One thing I am having trouble with though is when to subtract 10 from J. In one instance, you state:
[java]
if(DoStuff(i, j) == false)
{
getMeOutOfHere == true;
break;
}

Which obviously breaks if DoStuff is false. In the next example, it breaks if true:
[java]
if(DoStuff(i, j) == true)
{
goto getMeOutOfHere;
}

But seeing as these are examples: we can probably just ignore it.

Final word:
The reason I wanted to use a neat, non-goto method is Zooba’s reason for writing his post: “The point of this whole post is that goto is not evil”. By analogy, neither is a gun. But both can be used in evil ways. At least breaks and continues are limiting to the loop they are in. goto can obviously jump around a lot more. break will always go to the bottom of the loop. continue will go back to the start. Where does a goto go to? Anywhere: hence the name. I’m sure an IDE will let you jump to the location. I’m sure a skilled programmer can use it to their advantage. Unfortunately, not every programmer that makes it out to the world has those skills. Eventually that code then has to be cleaned up and maintained.

-= Comments
1. Zooba | May 6th, 2007 at 3:47 pm
Okay, you got me on the typo. I’ve fixed it. That’s what happens when you copy-paste and then only fix in one occurrence (hence you shouldn’t copy-paste code - put it in a function).

Aside from the fact that your simplified code will not work (read mine again, I’m not doing ‘p += 8′ anywhere, which brings up another typo, all the ‘j’s should have been ‘p’s) I don’t believe it is any shorter. Short-circuiting conditionals which include side-effects also introduces more to think about while you’re reading.

I’ve never noticed Eclipse show a break destination, but I don’t use it often. MS VS definitely doesn’t. Maybe I’ll have to grab the latest Eclipse and have a play.

The fact that break and continue have destinations specified by the language introduces more confusion when using them. My later examples show that it is impossible at a glance to see where they will go. Good use of goto prevents this. Including BASIC-esque comments such as “} // end while(x > 0)” may also help, a comment such as “// The BREAK above comes here” helps slightly more, but when you’re faced with deciphering indentation and braces, a fixed location is considerably more helpful.

2. pimaster | May 6th, 2007 at 5:17 pm
When I seen the while loop that was just incrementing p, and breaking on every 8th line, I thought the best thing to do was a p+=8. Now that p is being used elsewhere, I would have to look over the function again. But I’m not going to.

it is a fair point you raised about the boolean short cutting. If I was really writing the code, I would not have done that.

I feel that I’ve done a good good of cleaning up the code without using gotos. For me to right the thing properly, I would need to know what the task at hand is (Some sort of pseudo code?).
As it currently stands, it looks like the code scrolls backwards through a file. I want to know what happens when p becomes negative.

3. Zooba | May 6th, 2007 at 6:22 pm
The main problem with the ‘p+=8′ is that the loop actually rounds ‘p’ up to the next multiple of 8. Simply adding eight is a different behaviour altogether.

In fact, it is a completely different behaviour. Since p is a pointer to an int (assumed to be a 4-byte integer), every second increment will make it meet the condition of the loop. Adding eight will actually move the pointer by 32 bytes, rather than the 8 intended. This is partially my fault, as I intended the increment to only move it by one byte.

p going backwards by ten is totally arbitrary, I have no idea if it means anything or not, I just made it up. Since p is a pointer it is more likely to go outside of a valid page before it becomes negative, either of which will cause a crash that isn’t caught by this snippet and quite likely isn’t caught by the application anywhere. The example isn’t meant to do anything, I was basically making up a combination of loops and conditions that would help illustrate my point. I feel that my second set of examples is more powerful.

4. Gatesy | May 6th, 2007 at 11:37 pm
The fact that break and continue have destinations specified by the language introduces more confusion when using them. My later examples show that it is impossible at a glance to see where they will go.

Java allows for labeled loops & breaks, so if you were worried about readability you could always label the loops so that it was clear what you were breaking out of…

5. pimaster | May 6th, 2007 at 11:44 pm
Gatesy, that is something I did not know.
For all those that want a read (as I did) Java Documentation on Breaking
But is this much better that a goto? I think only slightly. I allows you to jump to any one of many looping statements, but at least it still limits you to the loops.

6. Gatesy | May 6th, 2007 at 11:56 pm
It might be only of minor usefulness, say for breaking out of two loops without needing an extra flag variable, but it’s still more maintainable than gotos.

On the other hand, if you build an app full of gotos, you might just have job security for life!

7. pimaster | May 7th, 2007 at 2:33 pm
I just wish I could remember where I seen:
If you are required for the task, you can never get promoted.

8. Zooba | May 7th, 2007 at 6:53 pm
I don’t think that’s better at all. I find it horribly counter-intuitive. You label something and go somewhere else? Also, it doesn’t come anywhere near solving the lots of braces problem.

“if you build an app full of gotos, you might just have job security for life!”

This is the reason that goto isn’t taught, or, if you prefer, is ‘banned’: People take things to extremes (”app full of gotos”) and the response is equally extreme (never ever ever ever ever ever ever use gotos).

Goto fits in the same vein as globally scoped variables. Both have their uses, however limited, and there exist cases where one of these is cleaner and more readable than the alternatives (unless the reader has had this part of his/her education skipped). Banning either of them outright forces people to write, and later decipher, unnecessarily convoluted code.

9. pimaster | May 7th, 2007 at 8:33 pm
Please don’t tell me you are going to sit there and state that “globally scoped variables” are sometimes useful?

Constants: yes
Variables: no

10. Andrew Walker | May 8th, 2007 at 10:08 am
I agree that for large team projects globals can cause problems, however I’ll be more than willing to back zooba up on this one.

Global variables if used correctly can simplify design, reduce development time and remove unnecessary performance degrading abstractions.

One good example is how python and lisp code make use of globals for factories and loggers. This removes the necessity for abominations like the singleton pattern.

11. Zooba | May 8th, 2007 at 6:45 pm
Globally scoped variables are sometimes useful.

Of course you always have to weigh the benefits against the potential problems. There are definitely more ways to use them wrongly/dangerously than correctly/safely, but the fact remains that there are some situations that best suit a global variable.

I’m not denying that there are ways of getting around this. All I’m denying is that any way not involving global scope is better. Same deal with goto.

No comments: