A little History … (lest we forget)
Gotos have had a long and sordid history in computer science. In the early days, before languages had a rich set of control structures, goto’s were it. It turned out that overusing GOTOs made the control flow of programs hard to follow and thus programs difficult to maintain. Dijkstra’s 1968 paper Go To Statement Considered Harmful is considered a classic for recognizing this fact. GOTO enriched programs are sometimes called Spaghetti Code
A movement was spawned to eschew the GOTO with as much zealotry as todays modern Object Oriented fanatic uses to eschew “procedural code.” This movement was called Structured Programming. The central premise being that any given block of code should have one entry point and one exit point. Presto … control flow is now easy to understand.
And so the structured programmers waged war on low level control structures in favor of high level control structures. And you know what? They won. Languages were constructed without GOTO statements. Computer science degrees became harder to get for those with an affinity to goto. Higher level control structures flourished.
As some of the zealotry faded, it turned out that sometimes multiple exit points can be useful for clarifying code. Continue, return, and break and later throw all provide ways to provide multiple exit points to a block of code.
Multiple entry points remain blissfully rare except for the occasional confusing fall-through case in a switch statement.
Early in my career, I had the (mis)fortune to be a maintenance programmer on some older programs written in the unstructured style with gotos. This is where I learned debugging, code smells and refactoring. Not having a source code control system, the programmer before me was loathe to actually remove unused code from a program, so he would simply GOTO around it. After years of this, a program might be 50% dead code. Goto “patches” were used instead of subroutines. A goto would jump to a distant location, perform some operations, and then jump back. FOR loops were simulated with gotos. Living with wholesale GOTO abuse, like some sort of war atrocity is not easily forgotten.
GOTOs in PHP
What surprised me most about the GOTO patch for PHP is the positive reception that it has received. There seem to be three arguemnts in favor of it:
- it is useful for error handling.
- it is useful for writing parsers
- it can be faster than other control structures
Regarding error handling, I think that using GOTO for error handling is like simulating for loops with GOTO. Why use the low level concept, when the higher level concept works better? try..catch and try..finally are designed for error handling. Use them.
Would people try to simulate gotos with exceptions? Perhaps. While that might be bad, gotos might be worse. The big difference is that exceptions can only provide multiple points of exit from a block of code. Gotos can provide multiple points of entry. Goto is far easier to abuse than exceptions.
Another difference between gotos and exceptions is that gotos in PHP are limited to a single scope, while exceptions can cross scope. This is important when a low level function may know that an error has occurred, but not what to do about it.
Using gotos for error handling increases the active area of variables involved in the error from the point of error occurrence to the point of error handling. This is bad and not just for compiler register allocation algorithms.
I think that people who want to use goto for error handling probably don’t understand how to use exceptions properly yet. (Thinking in C?)
Gotos are handy for parsing? Yes, but they are usually used in generated code built by lex or yacc. This is code not meant to be maintained by humans. If you are hand constructing a parser, you probably aren’t going to use tight state transition loops as generated by these programs. It is possible to write a reasonably fast parser in PHP without goto.
Goto is faster? This is related to parsing. The cost of parsing in PHP is allocating memory for substrings, anyway. This will probably dwarf any gains in control flow. If you sacrifice maintainability for speed at the micro level, you obfuscate opportunities for real performance gains, which almost always occur at the macro level. Don’t sacrifice speed for maintainability.
Having a goto statement makes control flow analysis more difficult for any current or future optimizing compilers. What is confusing for people turns out to be confusing for computers as well.
Java provides a little used labeled statement which can be the target of a break or continue statement. This allows escaping deep nesting (a bad code smell on its own) without introducing the problems of multiple points of entry. This might be a better alternative.
Not once in four years of programming in PHP have I thought to myself “I wish PHP had a goto statement.”
Perhaps worst of all, I think having goto will cause serious programmers to take PHP less seriously as a language.