11

Many people accused me recently for just mentioning a single word - "goto".
It makes me wonder, why it is considered such a nasty word.
I am aware of several previous discussions on the topic, but it doesn't convince me - some of the answers just says "it's bad" not even trying to explain and some bring reasons, irrelevant for scripting languages like PHP, IMO.

Anyway, I am going to ask a very particular question:
Let's compare goto and throw statements.
Both, in my opinion, do the same thing: avoiding execution of some portion of code based on some condition.
If so - do throw have same disadvantages as goto? (if any)?
If not - whit is the difference then.

Anyone experienced enough, who can tell the fundamental, conceptual difference between code structures of the two following code snippets?
Regarding these very code snippets, not "in theory" or "in general" or "here is a nice XKCD comic!".
Why the first one considered to be brilliant and latter one considered to be deadliest of sins?

#$a=1;
#$b=2;

/* SNIPPET #1 */

try {
    if (!isset($a)) {
      throw new Exception('$a is not set');
    }
    if (!isset($b)) {
      throw new Exception('$b is not set');
    }
    echo '$a + $b = '.($a + $b)."<br>\n";
} catch (Exception $e) {
    echo 'Caught exception: ', $e->getMessage(), "<br>\n";
}

/* SNIPPET #2 */

if (!isset($a)) { 
  $message = '$a is not set';
  goto end;
}
if (!isset($b)) {
  $message = '$b is not set';
  goto end;
}
echo '$a + $b = '.($a + $b)."<br>\n";

end:
if (!empty($message)) {
  echo 'Caught exception: ', $message, "<br>\n";
}

Note that I am aware of the fact that throw is more powerful and flexible in making spaghetti. It does not make the principal difference for me. It is matter of use, not concept.

EDIT
I've been told by many people that first example should be newer used.
Reason: Exceptions should be used to handle errors only, not to implement business logic.
It looks sensible.

Therefore, the only way left to stop useless code execution is goto (not to mention some substitutes, such as while, return etc, which are the same matter but harder to implement)?

Community
  • 1
  • 1
Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
  • 12
    goto has absolutely nothing to do with exceptions... "but exceptions can be implemented by goto!", so can if statements, so can while loops, so can coroutines, so can calls – L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ Jul 25 '10 at 14:08
  • In c#, the actual IL emitted is very different. Therefore fundamentally, to answer your question, I believe you would need to understand what the PHP interpreter is doing when it encounters your script to begin to answer this question. All other responses are coding jihad. This is pedantic, but in your goto example, your echo statement is misleading to another dev as there is no exception at that scope (thus no stacktrace, etc). – Jason Slocomb Jul 26 '10 at 17:35
  • 1
    Related reading: http://www.joelonsoftware.com/items/2003/10/13.html – Pekka Aug 03 '10 at 13:27
  • Partly related reading (a few parapgraphs on exceptions) http://www.joelonsoftware.com/articles/Wrong.html – Pekka Aug 03 '10 at 13:29
  • @Hejazzman I don't see what you're responding to, but this looks like it's from 8.5 years ago :) I can say that many things have changed plenty in that time, and I'm sure other things haven't. – defines Mar 01 '19 at 03:06
  • @defines Some post/comment might be from 8.5 years ago, but people read it today, and in 5 and 10 years, as long as Stack Overflow is up and serves this answer. So post date doesn't matter, posts are perennial, and the comment discussion is asynchronous over eternity... – Hejazzman Mar 02 '19 at 17:58
  • @Hejazzman Cool beans! – defines Mar 02 '19 at 21:10

11 Answers11

13

Throw/catch are much more flexible than goto: you can catch from the functions which call the code throwing the exception. Additionally, the required destructors are called automagically.

ssegvic
  • 3,123
  • 1
  • 20
  • 21
7

I think you need to ask the question the other way around: why would you use goto when exceptions are perfectly suited to the situation? That's what exceptions are for.

You may as well ask "why use while, for and functions when I can just as easily use goto?"

Dean Harding
  • 71,468
  • 13
  • 145
  • 180
  • Good point. From the practical point of view it's perfect answer. But i am still interesting in conceptual difference, if any. Especially why there is so polar opinions of thee two. – Your Common Sense Jul 25 '10 at 14:01
  • 1
    Much of the hate for "goto" comes from earlier languages like BASIC, where it is used in conjunction with a line number (instead of a label). This was considered very bad practice since your line numbers will inevitably change as you make changes to the file. – Daniel Jul 25 '10 at 14:10
5

goto hard codes the execution path into the code. Exceptions on the other hand allow the execution path to be determined at runtime.

For example, let's assume you have a database class that throws an exception on error. With exceptions, you could capture that error, and do something else before rendering the error page (Like clean up allocated resources, or "rollback" prior changes if you use a non-transactional db type. If you used a goto, you wouldn't have the chance to do that, since the goto would have rendered the error page.

Remember, keep your code reusable and flexible. goto is the antithesis of both...

ircmaxell
  • 163,128
  • 34
  • 264
  • 314
5

In your example there is effectively no difference as you are checking the error condition and either raising the exception or calling goto if the condition fails. Your example could be recoded to remove the need for either construct.

Where exceptions are useful is where you are calling methods that may have an error state but can't handle it themselves as the following pseudo code illustrates:

try
{
    $c = add($a, $b);
    echo '$a + $b = '.($c)."<br>\n";
}
catch (Exception $e)
{
    echo 'Caught exception: ', $e->getMessage(), "<br>\n";
}

The add method does the error checking:

if (!isset($a))
{
    throw new Exception('$a is not set');
}
if (!isset($b))
{
    throw new Exception('$b is not set');
}

then returns the result of the addition.

This means that your main code flow shows the expected path through the program.

ChrisF
  • 134,786
  • 31
  • 255
  • 325
3

goto is usfull for doing things like this:

foreach ($items as $item) {
    if ($item->is_match()) goto match;
}

$item = new Item();

match:
render('find_item.php', $item);

as apposed to this:

$matching_item = null;
foreach ($items as $item) {
    if ($item->is_match()) {
        $matching_item = $item;
        break;
    }
}
if ($matching_item === null) {
    $item = new Item();
}

render('find_item.php', $item);
Petah
  • 45,477
  • 28
  • 157
  • 213
3

Since no one has yet provided an answer to this question that the OP found acceptable, I’ll throw my hat in the ring.

…the fundamental, conceptual difference between code structures of the two following code snippets?

There is no conceptual difference at all between the two code snippets you provided. In both instances a condition is tested, and if met, a message is thrown to another part of the program for handling.

Why the first one considered to be brilliant and latter one considered to be deadliest of sins?

Thank you Col. Shrapnel for opening the door to the following rant.

<rant>

Every programming construct holds the potential for abuse. The dogmatic persecution of goto reminds me of the similar bashing of PHP. PHP leads to bad programming practices. Compared to: Goto leads to spaghetti code.

Simply put: goto is “evil” because Edsger Dijkstra said so and Niklaus Wirth gave it his seal of approval. ;-p

</rant>

For your reading enjoyment: http://en.wikipedia.org/wiki/Goto

Probably the most famous criticism of GOTO is a 1968 letter by Edsger Dijkstra called Go To Statement Considered Harmful. In that letter Dijkstra argued that unrestricted GOTO statements should be abolished from higher-level languages because they complicated the task of analyzing and verifying the correctness of programs (particularly those involving loops). An alternative viewpoint is presented in Donald Knuth's Structured Programming with go to Statements which analyzes many common programming tasks and finds that in some of them GOTO is the optimal language construct to use.

It goes on to say,

Some programmers, such as Linux Kernel designer and coder Linus Torvalds or software engineer and book author Steve McConnell also object to Dijkstra's point of view, stating that GOTOs can be a useful language feature, improving program speed, size and code clearness, but only when used in a sensible way by a comparably sensible programmer.

That said, I personally haven’t found a practical use for GOTO since Commodore BASIC, but that’s neither here nor there. :-)

Herbert
  • 5,698
  • 2
  • 26
  • 34
  • 1
    As i remember the story going, Dijkstra merely voiced (strong, and quite valid at the time) concerns about the potential for abuse (his paper was originally titled "A Case Against the `go to` Statement"). Wirth took the idea and ran with it, taking it to dogmatic levels. – cHao May 25 '13 at 19:25
2

goto may have a little performance boost comparing to throw, since it doesn't create any exception stack.

Michael Spector
  • 36,723
  • 6
  • 60
  • 88
2

In practical terms, the difference between your two code segments is that you'll have to spend more time explaining yourself to other programmers with the "goto" code.

For better or for worse, most programmers believe you should never use a goto. Perhaps you can prove that this is unfounded, and that your goto code is the best way to implement that function. Even so, you'll have to fight with coworkers or anyone else with whom you collaborate to get them to accept it.

If you are working by yourself and no one will see your code - use whatever you like. But if you're working on a team, sometimes the path of least resistance is most prudent.

Jon B
  • 51,025
  • 31
  • 133
  • 161
  • 1
    -1 If you dismiss perfectly valid code (no matter if there is a `goto` in there or not), because of ignorant resistance of your coworkers, then I can call that a lot of names, but none of them is *prudent*. – John Smithers Jul 28 '10 at 10:59
  • 1
    @John - then while you're fighting with your coworkers to prove to them that you're right, I'll have moved on and will be getting work done. That's the point. That's prudent. – Jon B Jul 28 '10 at 11:13
  • Moving on finding a better place to work would be prudent. It sounds like you just gave up and let the fools rule the company. That's not prudent. The wiser man gives in and stupidity rules the world. Congrats! – John Smithers Jul 28 '10 at 11:40
  • 1
    @John - seriously? Realism isn't giving up. A wise man chooses his battles carefully. – Jon B Jul 28 '10 at 13:52
2

The thing that's "wrong" is that goto it can implement many kinds of control mechanisms, not just throw, and therefore has little inherent structure. Because of this, there are several reasons why a script programmer would be interested in using goto alternatives:

First, we are starting to see scripts moving from purely interpreted to byte-code compiled. Good examples of this can be found anywhere, such as Python, Perl 6, Scala (Lift), Clojure (Compojure). Even PHP has byte-code compilers. Since goto has little structure, compilation of control mechanisms can't happen, which is a considerable performance loss because modern compilers are generally very good at this. For throw, compilers can start assuming that an exception being thrown is not common, and therefore it will optimize the "normal" control path often at the cost of a less optimal "abnormal" control path.

Even if you don't have a full blown compiler, interpreters can assist a programmer considerably more when the programmer uses control mechanisms that have more structure. For example, for loop blocks are lexically scoped by the compiler/interpreter, and so a programmer can use this scoping to modularize chunks of code. Otherwise, with goto you are forced to pollute the variable namespace.

Furthermore, if your language allows you to declare methods that throw exceptions, the compiler/interpreter can inform you that you haven't handled all the possible exceptions that the methods you are calling may experience (similar to throws Java, if you have experience there). With goto, the compiler has no idea what you're trying to do, so it won't help you out during compilation and testing.

Goto also requires the programmer to recover from the error. Imagine if you had some code like this one (snatched and edited from your snippets):

if (!isset($a)) { 
  $message = '$a is not set';
  goto errorA;
}
if (!isset($b)) {
  $message = '$b is not set';
  goto errorB;
}
if (!moonInRightPhase) {
   goto errorP
}
echo '$a + $b = '.($a + $b)."<br>\n";

errorA:
// Do something non-trivial and unique to handle $a not being set.
goto afterError

errorP:
// Do something non-trivial and unique to handle moon phase
// This error requires drastic failure of code path:
goto failure

errorB:
// Do something non-trivial and unique to handle $b not being set.
goto afterError

afterError:
// Program continues

return SUCCESS

failure:
return FAILURE

The problem here is that the programmer is required to do the right thing. If he forgets to goto afterError, he will run through the next exception path. With throw the mechanisms are a bit less error prone.

Finally, my personal experience makes me dislike the goto statement simply because it is not easy to read. When I'm trying to understand a piece of code with four or five labels named some-error, fail, retry, and they're not located close to the offending/excepting code, it can be a nightmare to untangle. And if it's not easy to read, then even the programmer trying to review what he or she did a year ago may lead to mistakes.

As a post-script to this answer, I don't believe "wrong" is the right way to describe goto. That might have come from sensationalizing the famous Dijkstra paper. "Powerful" may be a better term, because it implies that it can do pretty much everything, but even the simplest mistakes make "wrong" turn into "horribly wrong". We shouldn't ban tools because they're really dangerous; we should better educate people about their danger, and let them decide.

Jeremy Powell
  • 3,426
  • 2
  • 21
  • 29
  • Put another way: `goto` is the Swiss army knife of flow control. It (along with `if`) can reimplement every control structure in the language (and usually does, at the machine-language level; processors rarely (eg:) do `foreach` loops natively). But that power comes with a cost: `goto` is too generic to express intent. Just like a Swiss army knife typically sucks as a screwdriver, can opener, or often even a knife, `goto` is inferior to more specific, more expressive structures -- and should only be used if an existing one doesn't meet your needs without some trickery. – cHao Jul 28 '12 at 06:38
0

I don't hate GOTO as much as many do, but I think its main problem is that it's not restricted to a specific "scope". With every other control structure, you know where it starts and where it ends. A GOTO label, on the other hand, may be placed in a lot more unpredictable places. You can of course search the label, but it breaks the readability.

Of course all is up to how it's used.

Matteo Riva
  • 24,728
  • 12
  • 72
  • 104
-3

Don't use either. Use a "while(1)" around the bulk of your code and "break" statements where you want to jump to the end.

while(1)
{
    if (!isset($a)) { 
      $message = '$a is not set';
      break;
    }
    if (!isset($b)) {
      $message = '$b is not set';
      break;
    }

    echo '$a + $b = '.($a + $b)."<br>\n";
    break;
}

if (!empty($message)) {
  echo 'Caught exception: ', $message, "<br>\n";
}
Robert Deml
  • 12,390
  • 20
  • 65
  • 92
  • is that supposed to be a fun answer? – knittl Sep 07 '10 at 20:54
  • In what way is this a better solution than using goto? – Emil Vikström Nov 07 '10 at 13:27
  • 1
    @EmilVikström: It's not. It's "`goto` without the `goto`", and is even worse because the code is now lying about intent. When one feels the need to use a control structure to emulate `goto` -- in a language that *has* it, no less -- they've missed the entire point of the arguments against `goto` in the first place. – cHao May 25 '13 at 19:33
  • a better alternative to "while" is a do {/* your breakable code here*/} while(0). It is executed only once and has exactly the same advantage of an easy "break" from the code flow – tipograf ieromonah Feb 18 '17 at 16:27