views:

229

answers:

9

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)?

+5  A: 

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
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.
Col. Shrapnel
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
+7  A: 

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
Also, the exception thrower has no need to know what code, if any, will catch the exception.
Mike DeSimone
+2  A: 

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
+3  A: 

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
A: 

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

spektom
+1  A: 

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
-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
@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
@Jon: 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
@John - seriously? Realism isn't giving up. A wise man chooses his battles carefully.
Jon B
A: 

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
is that supposed to be a fun answer?
knittl
A: 

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.

kemp
Wrong. In PHP goto is limited to the function/file it is within.
Petah
@Petah: a file can be very long.
kemp
@kemp: A file that is extremely long with breaking it down into functions is bad practice anyway.
Petah
Can't argue on that, but it's kind of beyond the point.
kemp
+1  A: 

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