I've posted a code snippet on another forum asking for help and people pointed out to me that using GoTo
statements is very bad programming practice. I'm wondering: why is it bad?
What alternatives to GoTo
are there to use in VB.NET that would be considered generally more of a better practice?
Consider this snippet below where the user has to input their date of birth. If the month/date/year are invalid or unrealistic, I'd like to loop back and ask the user again. (I'm using if statements to check the integer's size... if there's a better way to do this, I'd appreciate if you could tell me that also :D)
retryday:
Console.WriteLine("Please enter the day you were born : ")
day = Console.ReadLine
If day > 31 Or day < 1 Then
Console.WriteLine("Please enter a valid day")
GoTo retryday
End If
Functions FTW!
Okay, I'm not sure if your code is really VB.Net here, since you've got some wonky type stuff going on (i.e.
Console.Readline
returns aString
, not a number you can do comparisons on)... so we'll just forget about type for the moment.And separately
Or you could have fun with recursion and early-return syntax! ;)
I'm going to differ from everyone else and say that GOTOs themselves are not all the evil. The evil comes from the misuse of GOTO.
In general, there is almost always better solutions than using a GOTO, but there really are times when GOTO is the proper way to do it.
That being said, you are a beginner, so you shouldn't be allowed to judge if GOTO is proper or not (because it hardly ever is) for a few more years.
I would write your code like this (my VB is a bit rusty...):
If you take your GOTO code and look at it, how would someone first approach your code? "Hmm.. retryday? What does this do? When does this happen? Oh, so we goto that label if the day is out of range. Ok, so we want to loop until the date is considered to be valid and in range".
Whereas if you look at mine:
"Oh, we want to keep doing this until it's Valid. It is valid when the date is within range."
Using goto has been considered a bad practice for decades now. Perhaps it was a backlash against the original BASIC (before Visual Basic). In the original BASIC there were no while loops, no local variables (only globals), and (in most BASIC versions) functions could not take parameters or return values. Moreover, functions were not explicitly separated; control can implicitly fell from one function to another if you forgot a RETURN statement. Finally, code indentation was a foreign concept in these early BASICs.
If you used the original BASIC for a some time (like I did), you would come to appreciate how the use of global variables and gotos everywhere makes a large program hard to understand, and without great care, turned it into a tangled mess of "spaghetti". When I learned QBASIC, with its WHILE..WEND loops and SUBs, I never looked back.
I don't think gotos hurt in small quantities, but in the coder culture a strong sense lingers that they are somehow evil. Therefore, I would avoid gotos for no other reason than to avoid offending sensibilities. Occasionally I find that a goto solves a problem cleanly (like breaking out of an outer loop from within an inner loop), but you should consider whether another solution makes the code more readable (e.g. put the outer loop in a separate function and use "exit function", instead of goto, in the inner loop).
I wrote a C++ program with perhaps 100,000 lines of code and I've used goto 30 times. Meanwhile, there are more than 1,000 "normal" loops and around 10,000 "if" statements.
I've got to agree with everyone else here: GOTO itself is not evil, but misusing it will certainly make your life miserable. There are so many other control structures to choose from, and a well-written program can usually handle most every situation without goto. That being said, I am at the near-completion point of a program that's racking up about 15,000 lines, and I used one, and only one, GOTO statement (which I may be replacing we will see). It's the first time I've used GOTO in the last dozen or so programs I've dealt with. But in this instance it got rid of a compiler error (using Me.Close() twice within the same Sub but within different If structures; I could have suppressed it but I simply threw in a label and replaced one Me.Close() with a GoTo CloseLabel). If I start running into more instances that require Me.Close() within this Sub, I'm likely to put Me.Close() in its own sub and simply call that sub from the If structures or other loops that result in a closing of the program... As I said, there's alternatives, but sometimes, and when used very rarely, sparingly, and strategically, GoTo can still be helpful. Just beware of spaghetti code, that's a blinking mess lol
http://xkcd.com/292/ i think this is the standard opinion of Goto.
instead try and use a do while loop. do while loops will always execute once and are great when you need to propmt the user, but make sure they enter the correct information.
The
GOTO
construct produces sphagetti code. This makes tracing through code almost impossible.Procedural / Functional programming is a much better approach.