In the code skeleton below I'd like to eliminate the gotos/labels while maintainig a reasonably equivalent clarity in the "flow chart" of the code. How could I do that?The _correct_ way to do that is to rethink the structure of the program to find one that doesn't require producing spaghetti code.
And contrary to what others seem to think your code has sufficient clarity, for me at least.
So you get the cigar.
marcov,
although you didn't use specifically a state variable, the combine use of "break" and "continue" acts as a kind of flip-flop flag or state variable.
All the other proposed solutions also use a form or another of implicit or explicit state variable. And contrary to what others seem to think your code has sufficient clarity, for me at least.
So you get the cigar.
440bx,The point is that it is much more powerful to do that way _and_, with just a little additional code, how the whole thing flows depending on those conditions can be made a lot easier to understand. I'm not going to say that the code below is "good" because, it still leaves something to be desired but, I do believe it is a very significant improvement over your original code:
1. What's the point of using two state variables rather than just one, as Warfley has done?
2. What spaghetti code? The structure of the procedure is straigtforward, as Warfley has already summarized. Or in other words, setting aside the the initial condition and the exit code, it's simply:Spaghetti code is any code that causes the programmer's attention to be jumping around in a piece of code. "goto"s are not the only way to make execution jump around. The answer to your question is: the code you posted is spaghetti code and the one I posted is dangerously close to spaghetti code (it's lasagna code, strands of cheese spaghetti between layers of pasta.)
As stated above, what makes it spaghetti code is that the programmer's attention has to jump all over the place to figure out how that code flows. That's bad/niente/no good/trump.
The fact that the triage has to deal with many values of the parameter VK doesn't constitute "spaghetti" code, nor does the number of conditions used. As explained in my previous post many of those conditions are in fact the return value of a function.
Why not just write procedures Reload, DispLoop and Lexit? You may define function/procedure within function/procedure.
while true do begin
...
Lexit;
...
Reload
end;
I'm fairly relaxed about goto, there are cases where it's quite simply the right tool for the job. Just don't over-use it.I'm also relaxed about goto, but I didn't use it in the last several years, I never saw the necessity.
procedure Skeleton;
isReload: Boolean;
begin
{ Code #1 }
if Condition1 then
begin
{ Code #2 }
end
else
begin
{ Code #3 }
isReload := True;
while True do
begin
// Reload:
if isReload then
begin
{ Code #4 }
isReload := False;
end;
// DispLoop:
repeat
{ Code #5 }
until not Condition2;
if Condition3 then
begin
case VK of
0: break;
1:
begin
if Condition4 then
continue;
{ Code #6 }
isReload := True;
end;
2:
begin
{ Code #7 }
isReload := True;
end;
3:
begin
{ Code #8 }
if Condition5 then
begin
{ Code #9 }
continue;
end;
{ Code #10 }
isReload := True;
end;
4:
begin
{ Code #11 }
if Condition6 then
continue;
if Condition7 then
begin
{ Code #12 }
isReload := True;
end;
end;
5:
begin
{ Code #13 }
end;
end; {Case}
end; {If Condition3}
end;
end;
//Lexit: ;
{ Code #14 }
end;
Well, it is not my opinion it is general attitude in programming. Using LABELS and GOTO is considered bad practice in higher languages. These are stuff kids today first learn in school or university.
As a senior programmer (almost retired) which is practically grown on ASM, I do support such attitude that it should be avoided by any cost in higer language, while in ASM that is "natural".
One parallel. Toyota had an accident some 5 years ago or so with unpredictable car acceleration which was consequance of extensive use of recursion in the software (leading stack overflow, IIRC), which is even strictly forbiden by MISRA standards.
Thus, some rules need to be followed as there is great chances that badly designed and implemented software cost even lives. Fine is we programming for fun, but in industry that is very serious matter.
Concerning myself, i really prefer to read in nested loops "If Not bAllRight Then goto NextThis;" rather than "If Not bAllRight Then Continue;".
It's understandable, and to their credit, that the MISRA standards are against a stack overflow.
I do support such attitude that it should be avoided by any cost in higer languageThis statement (i.e. avoid goto by any cost) implies that you are happy to replace:
One parallel. Toyota had an accident some 5 years ago or so with unpredictable car acceleration which was consequance of extensive use of recursion in the software (leading stack overflow, IIRC), which is even strictly forbiden by MISRA standards.Yes, but most people don't write safty crucial software for the automobile industry. If a car crashes because of a software bug it results in a lot of damage, including human damage. This must be avoided even at very low risks. If the size calculator for an online shop crashes and the customer has to reload the page, it is annoying but if it doesn't happen to often no one bats an eye.
[...]
Thus, some rules need to be followed as there is great chances that badly designed and implemented software cost even lives. Fine is we programming for fun, but in industry that is very serious matter.
This statement (i.e. avoid goto by any cost) implies that you are happy to replace:
...
with this
...
They're also taught that C++ and Javascript are a good idea. And they used to be taught that APL was a good idea, with absolutely no consideration of the runtime resources required. And Lisp, Prolog and Smalltalk with no security in their runtime storage. I can play this game for hours... :-)
I'd argue that a pragmatic approach is to be preferred.
That is truth. But anyway, using LABEL and GOTO with procedural languages?!