state-machine

How to handle multiple states with a state machine?


I started to implement a system with a state machine. But I came to a point where I doubt that a state machine is the correct approach.

For example: I have four states:

(idle, powerup, powerdown, work)

and two other states:

(production, test)

powerup and powerdown do behave different in production and test state ...

If I do have more states the combination of states explodes ...

How is this solved with a state machine?


Solution

  • That's a bit difficult to answer since the actual use case is very vague, but here are some possible techniques:

    1. Create separate states for Production+Powerup, Test+Powerup, Production+Powerdown, Test+Powerdown. Depending on the complexity and number of combinations of states this can explode pretty quickly.

    Pros: straightforward.

    Cons: cluttered, does not scale well, if some of the state logic is shared across instances there will be some copy pasta involved (hence, not very maintainable)

    1. Use hierarchical state machines (HFSM), that is, if you can define some sort of hierarchical relationship between the various state groups, the implementation of a specific state would be a state machine on it's own.

    So in your example, you would have a Production/Test state machine, and each one will implement it's own Idle/Powerup/Powerdown/Work state machine internally.

    If you think this over, this is actually a neater implementation of option 1.

    Pros: more readable than option 1

    Cons: assuming substates should share some common logic, there will still be copy pasting involved

    1. Have 2 parallel state machines, one handling Production/Test states and one handling the Idle/Powerup/Powerdown/Work states with some sort of blackboard or shared memory to communicate between machines.

    In your example, your agent or system will a container of the above mentioned state machines and process them in turn. The Production/Test machine would write some status to a shared memory that the other machine will read from and branch it's state logic accordingly.

    Pros: Can share code between different states

    Cons: Can share code between different states... Ok, serioulsy, it's super important to empashize that sharing code is NOT always a good idea (but that's a whole other phylosophical discussion. Just make sure you properly evaluate the amount of shared code vs. the amount of unique code or paths so you don't end up with a huge class that essentially contains 2 completely separate code paths

    1. I know it's a granted, but consider if FSM is the proper method of representing state and execution in your application. Again, not enough context to dive deep into this, and this point on it's own is a phylosophical debate - but keep your mind open to other solutions as well.