GoTo: is it really evil?

Started by
151 comments, last by Troll 18 years, 1 month ago
Quote:Original post by Will F
Quote:Original post by Servant of the Lord
So I popped up wikipedia and read on it.


Check out the entry for spaghetti code. There's also the seminal essay, Go To Statement Considered Harmful.

Hmm; thanks for posting links.
Quote:(though I must say that the hidden message in the code to Adventure is pretty neat)


You got me curious; what hidden message?

Okay; I have never used the goto function before(besides testing it a few hours ago); nor do I(after reading these posts) intend to. I was simply curious what my book was talking about when refering to the 'evil' of goto statements. If sloppyness is all it is though; a good programmer can code goto statements without making his code unreadable; whilst a bad programmer doesn't need goto to make his code look like crap.
I have decided not to use 'goto' unless extremely neccasary; thanks for all the responses!
            ~S of the L~
Advertisement
Quote:Original post by Servant of the Lord
You got me curious; what hidden message?


You have to look at the larger picture of it. It's on the right hand side.

Here's the web page's explanation of what the orange blocks are
Quote:When a byte of data (as opposed to code) is found in the cartridge, it is shown as an orange row: a solid block for a "1" or a dot for a "0". The row is eight elements long, representing a whole byte. This usually means that the images can be seen in their entirety when a series of bytes are shown as rows.


Anyways, at the time Atari did not allow their developers to be credited for working on a game - so the programmer hid a message in the game: "Created by Warren Robinett"
In modern languages you'll never need the goto statement, because the only real reason to use it is for exception handling in languages having no exception support.
A good example for goto can be found in the old c-written games from id-software.

Dijkstra has written an article about the goto statement and why it's evil, I think the article was written in 1970 or 1980, maybe you can find it in your library of choice.
I think gotos in C/C++ are useful sometimes - I do use doubly nested loops from time to time and I think the goto statement is much clearer than having an extra if statement immediately after one loop something like this:

for (...) {  cond = false;  for (...) {    if (...) {      cond = true;      break;    }  }  if (cond)    break;}


I also use them in a similar circumstance when I need to see how a loop exited since break (and loop condition failure) can only transfer control to one point. I think the need for this is more a flaw in language design than bad programming - I don't really know much about functional programming but from what I hear this kind of thing is solved much more elegantly that way.
Goto's make sense for bailing out. C++ has exceptions for that, but still useful none the less.

cause you can test all your cases have a goto to throw an exception if you don't want to be descript about it. Apple uses then in Carbon for skipping code on error. It makes a lot of sense too, becasue they have clean up code they wanna execute before quitting.
I can't recall my last use of goto.

I've allways just seen what are in my opinion better alternatives. Often it's as simple as refactoring a multi-loop structure into it's own function - the "goto element_has_been_found" becomes a "return reference_or_index_to_found_element" - now the search code is centralized, independant of the code that futzes around with whatever was found. Other times, converting allocation management from manual cleanup to RAII eliminates the need for a goto-cleanup-code statement.

Like much of C++, goto is "evil" because it is (or was) prone to blatent misuse (carrying over old habits from line-numbered BASIC). There are situations where I would not go so far as to label it "evil", but would still likely consider it "a crutch* that allows you to get away with not refactoring your code".

* note: I'm assuming refactoring is a "good idea" from an architectural standpoint in the situation regardless of what method you use to exit a multi-layer loop - most of the time you'd use it in a situation where you'd want to seperate/delegate the responsibilities of different actions into different functions (and are instead doing it in seperate sections of the same function, goto-ing them as appropriate). This isn't necessairly synonymous with a good idea in general - true throwaway prototypes might not be worth the effort of refactoring, old legacy code in dire need of replacing in general, etc. - so there could be a few good places to use goto. That said, it'll still be a crutch that lets things work, rather than something that solves the underlying problem (broken architecture) :-).
Thanks for the replies. It also appears to me that GoTo might be useful as a way of edterminating where your code is messing up if it compiles but doesn't work as intended. You could add a goto while touching up the code and run it to find exactly where the code fails. Pehaps, not though; haven't tried it yet.

So, I gather: Never use goto unless absolutely neccesary; and then think twice before using it. If you do use it, which is frowned upon, make sure you use it in an organized manner and use as few as you can with plenty of commented lines so others reading your code can see at a glance where goto goes to and what it is needed for. Also; Use for breaking out of loop chains so as to not use the 10-15+ lines of code normally used for that purpose. Anything else I should take particular note of? ~S of the L~
Many people trash goto's, yet here is one situation where I believe goto is the most elegant solution. I have seen the alternatives, and they are no better.

   //The following while loop simply creates squares only at locations where squares do   //not already exist.   while (squaresC.size() < numSquaresC) {      size_t numberAllocated = squaresC.size();      pickAnewPoint:   //Second time author has ever used a goto.      int x = (rand() % (SLW-StupidSquareWidth));      int y = (rand() % (SLW-StupidSquareWidth));      for (size_t i=0; i<numberAllocated; ++i)         if (squaresC.touch(x, y)) goto pickAnewPoint;      squaresC.push_back(StupidSquare(x, y));   //Add the square to the vector      }


You will hardly ever run into a situation like that in regular programming, though.
Quote:Original post by Servant of the Lord
Thanks for the replies. It also appears to me that GoTo might be useful as a way of edterminating where your code is messing up if it compiles but doesn't work as intended. You could add a goto while touching up the code and run it to find exactly where the code fails. Pehaps, not though; haven't tried it yet.

So, I gather: Never use goto unless absolutely neccesary; and then think twice before using it. If you do use it, which is frowned upon, make sure you use it in an organized manner and use as few as you can with plenty of commented lines so others reading your code can see at a glance where goto goes to and what it is needed for. Also; Use for breaking out of loop chains so as to not use the 10-15+ lines of code normally used for that purpose. Anything else I should take particular note of? ~S of the L~


Or you could use a debugger?
Quote:Original post by Anonymous Poster
Many people trash goto's, yet here is one situation where I believe goto is the most elegant solution. I have seen the alternatives, and they are no better.
---
You will hardly ever run into a situation like that in regular programming, though.



I'd actually write it more like this... You might not like how it looks, but there are no conditional jumps and it's a pretty simple loop structure I've used similar flag cases before. One example would be any time you want to get input from a user and loop until it's valid input. Using your logic, we should goto while invalid instead of looping while invalid. I disagree with this entirely, no sense replacing valid looping structures with conditional jumps in modern programming languages.
   //The following while loop simply creates squares only at locations where squares do   //not already exist.   while (squaresC.size() < numSquaresC) {      size_t numberAllocated = squaresC.size();      int x;      int y;      bool pointInvalid = 1;      while(pointInvalid){         x = (rand() % (SLW-StupidSquareWidth));         y = (rand() % (SLW-StupidSquareWidth));         pointInvalid = 0;         for (size_t i=0; i<numberAllocated; ++i){            if (squaresC.touch(x, y)){               pointInvalid = 1; break;            }         }      }      squaresC.push_back(StupidSquare(x, y));   //Add the square to the vector      }


[Edited by - M2tM on March 11, 2006 1:29:07 PM]
_______________________"You're using a screwdriver to nail some glue to a ming vase. " -ToohrVyk

This topic is closed to new replies.

Advertisement