Tuesday, September 1, 2009

Java's goto

There is an old programmer joke that goes something like this: One programmer in anger says to the second programmer, "Go to Hell!" The second programmer replies in obvious repulsion, "Ugh, you used goto!" The point of this nerdy humor is that to many programmers, use of "goto" is just about the worst offense one can commit.

There are several reasons that the goto is held in such low esteem among software developers. Edsger W. Dijkstra's paper A Case Against the GO TO Statement is a relatively early treatise on the evils of GOTO abuse. In that article, Dijkstra states, "[I became] convinced that the go to statement should be abolished from all 'higher level' programming languages." Dijkstra's Go To Statement Considered Harmful letter not only lambasted the goto statement, but also started a popular computer science trend of using the phrase "considered harmful" (though those two words were apparently used outside of programming before that).

Many programmers since Dijkstra have been bitten by some of the maintainability problems associated with use of goto statements in certain languages. Other programmers have heard these stories or have had the "Thou shalt not use goto" pounded into them so much that they don't need to experience its drawbacks firsthand to believe that they should not use GOTO.

Although the goto statement appears to have a generally bad reputation, it is not without its supporters. Frank Rubin wrote a response to Dijkstra's Go To Statement Considered Harmful (March 1968) called GOTO Considered Harmful' Considered Harmful (March 1987). In that letter, Rubin wrote about Dijkstra's letter having an effect on programmers so dramatic that "the notion that the GOT0 is harmful is accepted almost universally, without question or doubt." Of this observation, Rubin wrote, "This has caused incalculable harm to the field of programming, which has lost an efficacious tool. It is like butchers banning knives because workers sometimes cut themselves." Note that Dijkstra responded to Rubin's letter with On a Somewhat Disappointing Correspondence. The Cunningham & Cunningham Wiki page Go To says this about the goto statement: "The apprentice uses it without thinking. The journeyman avoids it without thinking. The master uses it thoughtfully."

There are numerous other resources that cover the pros and cons of using the goto statement. I don't intend to rehash that debate here other than the brief presentation of the early history of the controversy already covered. I have heard some Java developers stating that Java does not have a goto statement and that is what I want to discuss in the remainder of this blog post.

Java does reserve "goto" as a reserved keyword. However, it is an unused keyword. What this means is that although the keyword does not actually do anything productive, it is also a word that cannot be used in code for names of variables or other constructs. For example, the following code will not compile:


package dustin.examples;

/**
* Class demonstrating Java's goto-like functionality.
*/
public class JavaGotoFunctionality
{
/**
* Main executable function.
*
* @param arguments Command-line arguments: none expected.
*/
public static void main(final String[] arguments)
{
final String goto = "Go to bed!";
}
}


If I try to compile that code, I see an error like that shown in the next screen snapshot.



The error message "<identifier> expected" with a pointer at the space before "goto" gives an experienced Java developer enough of a clue to quickly realize that there is something wrong about using "goto." However, it may not be as obvious to someone new to Java.

I generally do not use the goto construct, but I also recognize that there are situations in which its use makes for code that is more readable and uses less crazy work-arounds than not using it. In Java, this has also been realized and support is provided for some of the most common situations in which a goto statement would be most useful and would likely actually be preferable to alternatives. The most obvious examples of this are the labeled break and labeled continue statements. These are discussed and demonstrated in the Java Tutorials section Branching Statements.

The ability to label a particular statement and then have the break or continue apply to that statement rather than its most immediate statement (as an unlabeled break or continue does) is especially useful in cases where nested loops would otherwise require more code and more complex code to accomplish the same thing. I have found that I can often redesign my data structures and code to avoid such situations, but this is not always practical.

Another good resource related to use of goto-like functionality in Java is the 13 June 2000 JDC Tech Tip Goto Statements and Java Programming. As this tip points out, the labels can actually be used to any block and are not limited to break and continue. However, it is my experience that necessity of this approach outside of break and continue is far less common.

One important observation about labels is that code execution does not literally return to that label when the break somelabel is executed. Instead, execution flow goes to the statement immediately following the labeled statement. For example, if I had an outer for loop called "dustin:", then a break to that would actually go to the first executable statement following the end of that labeled for loop. In other words, it acts more like a "goto the statement following the labeled statement" command.

I don't provide any examples of using these labeled break or labeled continue statements here because there are plenty of good examples easily located online. Specifically, the two resources that I have already mentioned (Java Tutorials Branching Statements and Goto Statements and Java Programming Tech Tip) include simple illustrative examples.

The more I work in the software development industry, the more convinced I become that there are few absolutes in software development and that extremist positions will almost always be wrong at one point or another. I generally shy away from use of goto or goto-like code, but there are times when it is the best code for the job. Although Java does not have direct goto support, it provides goto-like support that meets most of my relatively infrequent needs for such support.

3 comments:

Scott Vachalek said...

I believe break and continue, with or without labels, are considered "goto" for the purposes of Dijkstra's paper, which was written at an abstract level and not aimed at any particular keyword of any particular language. They are not "conditional clauses", "alternative clauses", or "repetition clauses" and were definitely frowned on in the heyday of structured programming.

Although they sometimes make code easier to write, it's rare that they make it easier to read which is generally a more important goal. They also prevent most automated "extract method" refactorings as well which is an extra annoyance when you are trying to unwind spaghetti code.

Chris said...

Hi,

I am interested in advertising on your site. I think its awesome!

Please get back to me when you have a chance.

crose@enticelabs.com

Thanks

@DustinMarx said...

Scott,

Thanks for the comment. It is certainly true that many people today consider break and continue to be "goto" statements because of the abruptness of their nature. As far as making code easier to read, that must be opinion because I have seen many cases where the work-arounds to avoid these constructs are hard to get one's head around because of the various flags and other "state" things that must be maintained. In fact, this is the main point of my post: software development has very few, if any, absolutes.

Thanks again for taking the time to comment.