State pattern and guard
Asked Answered
P

3

13

Update:

State pattern might a wrong way to solve this. Hence, any other pattern is welcome. Basically I'm looking for a way to have guard conditions for each state yet having a clean and maintainable code. How would front-end side routing systems like, emberjs, ui-router and react-router implement guard conditions to avoid entering a specific state if the condition is not met?


I want to implement a finite state machine by using State Pattern but I can't wrap my head around it. In short it's like:

If error -> error state
If A && B && C -> second state
If only A -> first state

At any state, on error, we go to error state. inputs (events) A, B and C might arrive at any order but if they all pass we go to 2nd state. If only input A applies, then we go to 1st state.

The following state diagram is taken from Martin Fowler's Domain Specific Language book.

DSL

In the description he says:

Miss Grant, has a secret compartment in her bedroom that is normally locked and concealed. To open it, she has to close the door, then open the second drawer in her chest and turn her bedside light on in either order. Once these are done, the secret panel is unlocked for her to open.

I emphasize, that turning light and opening 2nd drawer can happen in either order. Same as A, B and C.

Based on @SQLPolice comment and the book, I have drawn this:

enter image description here

But the problem is, I might have (A && B && C && D && D && E). In that case it's gonna be cumbersome to have all of the combination interim states.

Perryperryman answered 1/7, 2015 at 7:49 Comment(5)
you have a start state, I assume ?Wenwenceslaus
What are you drawing this in... UML/Flow...?Fairway
@DavidBarker, neither. I just need something visual to understand how to implement.Perryperryman
OK, but when you have A only, then you want to go to a different state. But what happens if you have A as first event ? How do you know that B or C will follow?Wenwenceslaus
Oh, that's a nice drawing now! - Yes, you are right, it get's very very cumbersome when getting more complex. That's why you use tools to create such state machines - for example lex, flex, etc. (for lexical analysis). They create C code with a lot of labels and goto jumps ...Wenwenceslaus
F
4

You can use some form of lexical analysis for this. I would approach this by limiting the ability to transition from a state unless the constraints placed on the edge between the two states are met. I wrote an FSM in PHP recently for the Laravel framework that has an example such as this where various constraints are all required to be true before a transition can occur. It uses pseudo states or handles within a state to toggle a flag stating that a process has completed. Only when all flags are set to true can the state transition.

Sample lexical state analysis

Using the FSM package I wrote for laravel, an example FSM setup would look something like this.

Each state would (either onEnter) or via a pseudo state set it's constraint flag on the FSM OR State to true.

This would also trigger a checkReady() that would trigger the transition or keep the current state based on the constraint flags.

Adding in new constraints is a case of adding them to an array of constraints within the state or the containing FSM and building a method to allow the constraint to be removed when a task is performed.

When you are looking at multiple states, with each state forming a requirement on the constraints. A sample state would look something like this.

When you are looking at a single state with pseudo states / handlers. The state would look something like this, where it's logic is contained.

Fairway answered 1/7, 2015 at 9:39 Comment(0)
W
3

A quick draft looks like this:

enter image description here

Wenwenceslaus answered 1/7, 2015 at 8:20 Comment(5)
Thanks, but how would I avoid writing if (A && B && C)? The reason is, I already have a lot of if and else with various conditions. The only reason to pick state machine was to avoid doing that.Perryperryman
Ah, I see. What's behind that - is that a homework for school, or what do you want to realize ?Wenwenceslaus
It's not a homework. I'm older than this kinda thing. It's a real problem we have and we are trying to simplify things.Perryperryman
It's a while ago, but I can roughly remember how this was done with lexical analysis. You can dissolve the "A & B & C" by using a sequence of interim states, like this: If you have A, then switch to interim state 1. Now, there, if you have B, then go to Interim State 2, but if not, then go to your Final State 1. In Interim State 1, if you have C, then go to Final State 2. This is one possible way like automated tools would do it.Wenwenceslaus
Make a transition event D where D = (A && B && C)?Roughcast
B
1

A state machine abstraction is comprised of:

  1. States
  2. Events or inputs
  3. Transitions
  4. Actions

A statement like a&&b&&c is effectively an event or input... a label for a transition. So it needs to be mapped to an event if you're going to fit into the state machine abstraction. You need to write code to do that mapping.

If your state machine is generally driven by conditions like these you need to hook events where a b and c change, or check them periodically on timer. Any time they change, your code maps to an event and posts them into whatever code advances the state machine.

Bo answered 28/1, 2016 at 22:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.