• Advertisement
Sign in to follow this  

Is this a bad use of GoTo?

This topic is 2353 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

[source lang="vb"]
Function fsmHeater()
Dim Timer As Integer 'Initialize
State0:
Off (oHeater)
Off (oAlarm)
'---
WaitFor(Temperature() < 84)
State1:
On (oHeater)
Timer = GetmS()
'---
Select Event
Event Temperature() > 85
GoTo State0
Event GetmS() - Timer > 6000
GoTo State2
EndSelect

State2:
Off (oHeater)
On (oAlarm)
'---
WaitFor(Input(iResetButton))
GoTo State0
End Function
[/source]

Is this a good use of GoTo? This code is supposed to mimic a FSM. Personally, I see nothing wrong with it. Given the function is pretty short. But I wonder if this approach should be avoided: because of a better solution, or just because GoTo is the spawn of evil itself.

FSM Link

A snippet from page:

Notice that when an event match happens the line of code following the event condition is executed. In this program that is a GoTo. In many circles GoTo is considered to be bad programming. Not so in coding FSMs; GoTo allows you to move from place to place in the code in a way that echoes how the state diagram transitions from place to place. [/quote]

Share this post


Link to post
Share on other sites
Advertisement
Depends on how WaitFor is implemented. I might be more inclined towards more of an event driven model because it's easier to modify/extend/test, but this is pretty clear and nice (despite my disdain for all things goto).

Share this post


Link to post
Share on other sites
You could also use the equivalent of a switch statement
warning heavy sudo code


void fsmHeater()
{
bool AreWeDone = false;
int State = 0;
while(AreWeDone == true)
{
switch (State)
{
case 0:
{
Off (oHeater)
Off (oAlarm)
'---
WaitFor(Temperature() < 84)
}break;
case 1:
{
On (oHeater)
Timer = GetmS()
'---
Select Event
Event Temperature() > 85
State = 0;
Event GetmS() - Timer > 6000
State = 2;
EndSelect
}break;
case 2:
{
Off (oHeater)
On (oAlarm)
'---
WaitFor(Input(iResetButton))
State = 0;
}break;
}

}
}

Share this post


Link to post
Share on other sites
Personally, I don't like it. I was going to suggest pretty much doing the same thing as yewbie did. If you have a game loop then all you should need to do is set a variable to the state you want and when the next loop comes around the initial switch (select) statement will catch the new state and do what you wanted; therefore the goto statements are not needed.

I just don't like goto statements... sorry

Share this post


Link to post
Share on other sites
off-topic: wow. the editor is really bad. I hope this new forum upgrade fixes this.

on-topic: that's not bad either. doesn't look much different from the GoTo really.

Share this post


Link to post
Share on other sites
In this instance, given the function in question it's fine.

However given that most FSMs are generally written in a 'do something, optionally set next state, return to caller' manner a goto is unlikely to be a good match in the majority of cases when using/writing a FSM.

Share this post


Link to post
Share on other sites
Also, I just read that first page of the link you provided on FSMs and I have to say I completely disagree with the following statement:

Notice that when an event match happens the line of code following the event condition is executed. In this program that is a GoTo. In many circles GoTo is considered to be bad programming. Not so in coding FSMs; GoTo allows you to move from place to place in the code in a way that echoes how the state diagram transitions from place to place.[/quote]

You can accomplish exactly what you need to do in a Finite State Machine without ever using a goto statement! But then again, what do I know... I'm a noob at all this stuff too :)

Share this post


Link to post
Share on other sites

Is this a good use of GoTo? This code is supposed to mimic a FSM. Personally, I see nothing wrong with it. Given the function is pretty short. But I wonder if this approach should be avoided: because of a better solution, or just because GoTo is the spawn of evil itself.


FSMs have been traditionally implemented using a switch statement (see above).

The reason lies elsewhere. A FSM is a graph, which can be represented using a matrix. Since all but the most trivial FSMs contain considerable number of states and might be machine generated, using state and action tables is by far the simplest way to implement them.

It has less with style but more with pragmatic approach.

There is another benefit of using state as external variable. One state advancement can act as generator or yield operator. Or put differently, if you call your state machine via some function "advance()", it will move one state, then return, allowing to take action, rather than just having to modify the internals of FSM during development.

In language parsers there is usually nextToken() function, which is a state machine that will return in the middle of processing. Such workflow is typically not possible using gotos.


For fixed FSMs, such as interpreters or VMs, gotos will often be machine friendliest and fastest way to implement them. They are used by JS VMs, for example. They are simply a natural fit, since a FSM is nothing but jmps and gotos translate to those directly.

Share this post


Link to post
Share on other sites
It's been a looooooooonnnnnnnnggggggg time since I have used a basic derived language, so excuse my ignorance, but does BASIC have a viable switch statement?

Share this post


Link to post
Share on other sites

It's been a looooooooonnnnnnnnggggggg time since I have used a basic derived language, so excuse my ignorance, but does BASIC have a viable switch statement?


Yes and I believe it's a "select statement" in basic

Share this post


Link to post
Share on other sites

Is this a good use of GoTo? This code is supposed to mimic a FSM. Personally, I see nothing wrong with it. Given the function is pretty short. But I wonder if this approach should be avoided: because of a better solution, or just because GoTo is the spawn of evil itself.


As many have noted, goto by itself is not the spawn of evil. There was a recent discussion which included the pdf and the context of the original argument about why gotos should be avoided.

Using goto when other control statements are a better fit is the evil action. Goto is almost never the right answer. There is almost always a better structured answer available. There are very rare situations (generally during error handling) where the unconditional goto jump is the right tool. In almost every other situation goto is the wrong answer since a structured control statement is more clear.


In your specific example you have just three states. The first one drops through, the second redirects to one of two other states, the third resets.

You can see that your example won't scale well. It already struggles for clarity with those three states. Where does each state go, and under what conditions? If you add a state between 0 and 1, what states will the new state transition to? Should the new state fall through to the next state uninterrupted, or possibly route elsewhere? What happens when you want to insert a state in the middle of states 1 and 2?


With three states it is already hard to follow. At double that size it would become a maintenance nightmare. Heaven help you if the monster grew to hundreds of states.


That is why goto is a poor fit.




As others have noted, an FSM is best expressed by a switch statement or other lookup table directly. In vb.net that is a select/case tree.

My preference for a VB example would be along these lines:
[source lang='vb']
Enum FSM_States
State_crash = 0
State_Start
State_Idle
State_Heating
State_Cooling
...
State_End
End Enum


state = State_Start
While state <> State_End AND state <> State_crash
Select Case state
Case State_Start
state = DoStartState()
Case State_Idle
state = DoIdleState()
Case State_Heating
state = DoHeatingState()
...
Case Else
Debug.Assert("Unknown state! Crashing the state machine.")
state = State_crash
End Select
End While
[/source]

This structure very closely follow the details of an FSM. The machine only cares about your current state and the transition that follows on completion. The machine does not care about the internals of any state. Each state must return the transition of the state that follows.

Maintenance and performance wise this structure is excellent for quite a few states. At some point it will eventually be easier to maintain as an array of function pointers, but that would be far beyond a For Beginners post.

Share this post


Link to post
Share on other sites
This is an excellent use of goto. It's a wonderful example of the sort of use of goto that lead to Dijkstra's famous essay. We used to call this spaghetti code (as in, pray to the FSM that you don't have to maintain that code).

After all, if you can't be a good example, you can still function as a warning.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement