Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Hierarchical State Machine? #8

Closed
Bouke opened this issue Oct 2, 2014 · 9 comments
Closed

Support for Hierarchical State Machine? #8

Bouke opened this issue Oct 2, 2014 · 9 comments

Comments

@Bouke
Copy link

Bouke commented Oct 2, 2014

Hi @inamiy, I really like your take on state machines in Swift. I'm now running into an issue in which support for a Hierarchical State Machine would benefit the architectural design. For example, I have three states: A, B and C. A and B are two variants; and it is possible to go from either A or B to C. However, from C it is only possible to go to A. So I would need a handler (A, B) => C and C => A. However SwiftState doesn't allow me to create a handler (A, B) => C, so either I duplicate the handler (no good), or disregard the current state and add nil => C (but that also allows C => C, and a future D => C). As the states grow complexer, this would result in headaches; as adding yet another state would require re-evaluating all the current handlers.

@inamiy
Copy link
Member

inamiy commented Oct 3, 2014

Hi @Bouke, thanks for your feedback.

Your situation can be solved using condition in addRoute(state:condition:).
To do that, try

machine.addRoute(nil => .StateC, condition: { transition in
    // from anywhere to .StateC at first, but restrict fromState to only A or B, using condition
    return transition.fromState == .StateA || transition.fromState == .StateB
}

For more information, please see blacklisting technique in: StateMachineTests.swift#L116-L129

@inamiy
Copy link
Member

inamiy commented Oct 3, 2014

Oops, I forgot the handler part. Please use this instead: addRoute(state:condition:handler).

You can also do like this:

machine.addHandler(nil => .StateC) { context in
    if context.fromState != .StateA || context.fromState != .StateB { return }

    // do whatever handling you want for A => C or B => C only
    ...
}

@Bouke
Copy link
Author

Bouke commented Oct 4, 2014

Well that's also what I meant by using the nil state. However, add another 20 states and it becomes very hard to maintain or even grasp the states of the machine by looking at the routes. For example, take the following picture of a HFSM:

HFSM
source

This state machine allows to go from (Dive | Crouch) => Roll => Crouch. This is a very clear state transition.

Another solution would be to use SFSM (nested FSM), this could be modelled as 4 different state machines:

SFSM
source

Or the following picture, where an UML state machine is shown. In my example case both A and B would be within s1, and the transition from s1 to s2 would equal the nil => C case in the example.

UML
source

inamiy added a commit that referenced this issue Oct 4, 2014
inamiy added a commit that referenced this issue Oct 4, 2014
Improve #8 by adding another `=>` helper to create StateRoute (conditional transition) using array.
@inamiy
Copy link
Member

inamiy commented Oct 4, 2014

Thank you for detailed information!
Your post gave me a good insight 😉

To achieve your (Dive | Crouch) => Roll transition (HFSM),
I added a simple helper in #9 (db73c10) as:

machine.addRoute([.Dive, .Crouch] => .Roll)

Now complex routing becomes more declarative and understandable :)

For nested FSM, please let me take some more time to dig into.

@Bouke
Copy link
Author

Bouke commented Oct 11, 2014

Thanks for the changes, that already cleaned up some code. 👍

Being able to also specify handlers that way, would also be great. However these changes somewhat eases the burden on complex state machines; it would still be able to address so-to-speak categories. Like in the example above only define s1 -> s2 transition, without worrying about the sub-states of s1 and s2.

@inamiy
Copy link
Member

inamiy commented Oct 13, 2014

I added a HierarchicalStateMachine feature in #10.
Please take a look and tell me your thoughts :)

@inamiy
Copy link
Member

inamiy commented Oct 18, 2014

I will merge #10 anyway and close this issue.
If you've got any opinions, feel free to reopen.

@inamiy inamiy closed this as completed Oct 18, 2014
@Bouke
Copy link
Author

Bouke commented Oct 18, 2014

Sorry, i haven't been able to look at this thoroughly. Good to hear that you'll be merging your solution. However, would it be somehow possible to also create a HSM with static typed states, with enums?

@inamiy
Copy link
Member

inamiy commented Dec 10, 2015

In ver 4.0.0, I refactored many codes and now states with enums are supported for hierarchical state machine.
Please see Ver 4.0.0 Release Notes and new HierarchicalMachineTests.swift for more info.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants