GOTO no longer Considered Harmful

Started by Darren Dirt, November 18, 2015, 01:52:38 PM

Previous topic - Next topic

Darren Dirt

http://developers.slashdot.org/story/15/02/12/1744207/empirical-study-on-how-c-devs-use-goto-in-practice-says-not-harmful

Should not be shocking, because, you know, developers are not just stupid lazy idiots, but actually might use code constructs in ways that make logical rational sense and/or make future maintenance clear and easy! ( mostly "jumping forward, not backwards" and almost entirely for "error handling and cleanup" -- see pdf of results of study )

Quote from: https://peerj.com/preprints/826v1/

It seems to me that Dijkstra's fears have had two salutary effects on the use of goto statements:

1. The development of various other control structure abstractions that are safer and often easier to understand than gotos would be. This allowed a great reduction in their use since the days of FORTRAN and BASIC.

2. The cultural effect of actively discouraging goto statements, which has served to prevent the worst abuses and perhaps relegated gotos to only the few applications that were found in this analysis. This is, of course, aided by the control constructs added to remove/reduce the need to use gotos in code in the first place.


bingo.

_____________________

Strive for progress. Not perfection.
_____________________

Darren Dirt

And also, for balance, I offer a couple of  /. comments:

Quote
1968 was the year Djikstra wrote his article. At that time, arguably the dominant languages (FORTRAN IV and maybe BASIC) did not have structured control-flow constructs such as if-then-else, do-while and begin-end blocks...

Without structured control-flow constructs, one is pretty much forced to write goto statements everywhere. I think Djikstra's cautioning against the use of gotos was also a call to abandon them in favor of the structured approaches that the new languages supported. And he was right: if you're using gotos to replace structured control-flow, then you're abusing gotos.


Quote
Goto is being used safely (relatively) now, but would have the programming practices that cause that to be true become so prevalent without his warning that it had potential for problems?



In other words, USE the better way if it keeps it simple and clean and easy to maintain.

But also keep an open mind to the benefit of properly using "That Dangerous Nasty GOTO" if the alternative is lotsa nested BS that's a nightmare to understand -- XKCD's satire drives that point home

/END OF LINE
_____________________

Strive for progress. Not perfection.
_____________________

Mr. Analog

I've seen the opposite, where a developer thought that using exceptions was a great new control flow mechanism because they could escape any operation (sort of like GOTO)

// try
// do thing
// logical assertion: throw exception X
// catch exception X
// do other thing throw exception Y
// calling object has to expect exception Y to process different logic
// repeat pattern with different custom exceptions / logical conditions


So instead of returning a complex type on this method they had NO returns and about 15 different thrown exceptions that all meant different things to the calling code they made

This completely destroys OOP concepts (and needlessly fills your log output up with a bunch of trash) not to mention confusing as hell to debug if you aren't thinking the same way that person was (or maybe you ARE that person and 3-6 months have transpired)

Side Note:
I don't know why some people like to abend processes, I think they think there's some magic that happens that makes things more efficient but in most languages that are abstracted from the bare metal its not only unnecessary and confusing but potentially dangerous because who knows whats happening in the VM/Framework...

...maybe they just like to see the world burn, who knows
By Grabthar's Hammer

Darren Dirt

Agreed, exception handling can become ugly.

But have a look at the conclusions in the PDF linked inside the OP -- imo it was encouraging to see that the vast majority of the examples of what was found on GitHub (like 80-95% of the occurrences) were of this variety...



-------

function foo
{
   init_or_create_something()

   if(!test_something) goto end_cleanup
   if(!test_something_else) goto end_cleanup
   if(!test_one_last_thing) goto end_cleanup

   dependent_processing_here()

end_cleanup:
   always_cleanup_or_destroy_something()
   exit function

}

-------




...instead of something like...



-------

function foo
{
   init_or_create_something()

   if(test_something)
   {
      if(test_something_else)
      {
         if(test_one_last_thing)
         {
            dependent_processing_here()
         }
      }
   }

end_cleanup:
   always_cleanup_or_destroy_something()
   exit function

}

-------



...which of course could get complex and ugly very quickly.


So looks like nowadays usage of any kind of "goto" is mostly being done to improve readability or maintainability, not to replace the more "modern" code constructs for looping etc. that was so concerning 40+ years ago.

_____________________

Strive for progress. Not perfection.
_____________________

Tom

The main reason people don't abuse goto much in C these days is because it is looked down upon very vigorously. There are very few /valid/ use cases that people won't slam you for immediately. It literally feels dirty to use for many C programmers.

Have to say though, there is one place i was super happy to use it. Wrote a Virtual Machine of my own design that had been using a loop and a switch, and i learned about something called "Direct Dispatch" or "Computed GOTOs". You build a table of labels (gcc extensions ftw), that mark each individual action, and at the end of each labled block you increment the instruction pointer, and jump to the next label :D it was SO much faster than a loop+switch. like 10x faster.

One other not-so-dirty use is error handling. kind of a pseudo exception setup. You have one or more "error" labels at the end of the function, after the success return, and in various points of failure in the function, you just "goto" some error handling code that multiple points in the function can share.
<Zapata Prime> I smell Stanley... And he smells good!!!

Mr. Analog

To me a Using statement with an implemented dispose or even a try / catch / finally block is easy enough

Also I'm not sure about other IDEs but most I've worked with allow you to collapse matching open / close structures (like brackets) so if I don't want to look at 'em I collapse the parts I don't need to see (after all most code I write gets compiled into MSIL or obfuscated JavaScript)

Not to mention that usually something like this:

}
}
}
}
}
}
}
}
}
}


...means it's refactorin' time.
By Grabthar's Hammer

Tom

Quote from: Mr. Analog on November 18, 2015, 03:13:26 PM
To me a Using statement with an implemented dispose or even a try / catch / finally block is easy enough
Its usually a mater of language features. C has none of those things!
<Zapata Prime> I smell Stanley... And he smells good!!!

Darren Dirt

Quote from: Tom on November 18, 2015, 03:12:56 PM
One other not-so-dirty use is error handling. kind of a pseudo exception setup. You have one or more "error" labels at the end of the function, after the success return, and in various points of failure in the function, you just "goto" some error handling code that multiple points in the function can share.

Ding! See my more recent post ITT.
_____________________

Strive for progress. Not perfection.
_____________________