Shared publicly  - 
 
I've actually heard quite a bit of GOTO bashing recently (specifically re: PHP). And I'll admit it shouldn't be the first choice of programming tools. But the majority of arguments are pithy lines about it being a last resort or ugly - but not why it is a bad move functionally, programmatically, or even in terms of maintainability (ok, this last one does come up).

There is a good conversation from a while back on StackOverflow (http://stackoverflow.com/questions/1900017/is-goto-in-php-evil), and I think the best answer, which was not chosen said it well with:

"Bad structuring of code is evil, regardless the control structure you use.

I personally prefer a goto that makes clear the flow of the program to "control variables" and nested "if" that will indirectly just cause the same branch in the code."

Basically, don't abuse it and don't write bad code. The same could be said for nested ifs, breaks in whiles, or recursive structures. They all have their places, but misuse can lead to unreadable, unmaintainable code.

But maybe I'm just stirring a hornets nest for no good reason.
1
Mark French's profile photoAdam Covati's profile photo
4 comments
 
The issue is not that GOTO (or any other language construct) is evil in and of itself. The issue is what it implies:

GOTO is often found in cases of code that really ought to be refactored, but were too complicated to make that easy, and a GOTO was a quick solution. This generally implies some combination of laziness and/or overly complicated code, neither of which are laudable traits.

The statement is also problematic in that it makes code harder to work with (read, test, maintain, debug):

GOTO usually makes code harder to write automated tests against, because it almost always breaks modularity in code. Rather than being able to write tests against self-contained methods, one is left writing them against a larger, more loosely-connected set of code, as GOTO allows program flow to jump in ways that are harder to control or anticipate. This makes the tests more complex, harder to write, harder to maintain, and ultimately less useful (because the tests end up being forced to consider larger areas of code, making more of them break when refactoring occurs later, and making it harder to track down the immediate cause of a test failure when things break/regress).

While the GOTO-label implementation in PHP is vastly less prone to breakage than the GOTO-line implementation in BASIC and some other languages, it has its own pitfalls. In particular, the limitations placed on GOTO in order to make it safer in PHP (no jumping into loops, jumps not available between functions or otherwise out of the current context/scope, etc) place significant restrictions on how it can be used, which raise their own issues for refactoring code that uses them.

The GOTO statement in PHP does not provide any forensic trail in the event of errors. If a failure (ie, an exception) occurs during the execution of a method, a stack trace is readily available to trace back through the code and discover how program flow arrived at the point of the error. Likewise, jumps to segments of code using GOTO provide none of the mechanisms for specific error-handling that function/method calls provide (There is no try { GOTO myLabel; } catch(FailBurgerException $e) { // do something to recover } ).

I have seen many people suggest GOTO as a good way to get out of loops (while you cannot jump into them, jumping out of loops is allowed with GOTO in PHP). While this is true, the BREAK statement already provides the same mechanism, and a multi-level break can get you out of a loop just as well as GOTO, and with fewer opportunities for shenanigans.

The mere fact that code contains a GOTO does not make it bad code, but it is usually a pretty strong indicator. While it is technical to write good code that uses GOTO, it is very easy to write bad code, and finding GOTO in code is usually a great big red flag.
 
Thank you for the detailed response +Mark French , your conversation (I somewhat overheard) earlier today was one of three that have come up over the passed couple days on the topic.

I agree with much of what you are saying. However, there is still the main use case that I believe GOTO was added for in PHP, which is the cleanest way to exit nested IFs (Where break doesn't help - right?). Now, perhaps you shouldn't be that deep into nested IFs. So this may be an indicator that refactoring could be in order.

I have an immediate knee-jerk reaction to dislike GOTOs because it has a bad rep, and mainly due to my years of painful BASIC that taught me how bad it could be. I just wanted to have some better reasons under my belt for why it was deserved.

I still feel that the biggest reason is "Because it's too easy to abuse" and "it can get messy" and I guess that's good enough to lay off of it. But it's a dangerous road to go down - cause lord knows there are some other commands that wield mighty power or can create messes - and I'm not willing to give all of them up! :)
 
Actuallly, +Adam Covati, you can use BREAK to exit from nested IF statements just like you can use it to exit nested loops. In fact, you can use it to exit from IF and FOR/WHILE loops nested inside of one another. (http://php.net/manual/en/control-structures.break.php)

However, that's another one of those things that usually indicates an opportunity to refactor. Cyclomatic complexity rises quickly as you start nesting IF statements, and it skyrockets when you start nesting loops. If you find yourself inclined to use BREAK more than maybe two levels deep, it's usually time to break whatever you're working on out into its own, much simpler method.
 
Agreed. Many of these instances seem like likely refactoring situations. 
Add a comment...