Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Split state machine in several classes using Stateless library

In a C# solution I'm working at, the core of application logic is implemented as a state-machine by means of (very good) Stateless library. There are other parts of business logic modeled in a number of other classes, for the different areas and features the app shows, but this is the one driving the main changes in underlying app states.

Although every state transition is quite simple in itself (notifying events, setting eventArgs, listening to other events, ...) and I'm using substates when applicable, to me it's starting to look like somehow too big. I understand this is not an exact measure, but if you look and think about substates, you may well end up finding that they could be distinct state machines on their own.

Is there an evident way that I'm missing to build separate sub-statemachine (so to say) with Stateless, mapping every state machine to a distinct class (and file)?

The first blocking issues that come to my mind are (especially the second):

  1. the one-big-piece state machine triggers events on all state changes: after the split, each single state machine would fire each own triggers. So there would better be a façade collecting all events and re-triggering them for the clients, so to hide the many state machines (after all they are an implementation detail for clients).

  2. Stateless substates take care of bubbling triggers up the state/substate chain, as well as downwards. So e.g. for a given state A having substates, one can define a trigger (in one place, A's Configure) that will make the state machine leave A, no matter in which substate of A we will be. How does this work with separate sub-state machines?

like image 984
superjos Avatar asked Oct 31 '22 08:10

superjos


1 Answers

Defining good substates, as you mentioned, is really helpful in being able to abstract pieces of a big state machine. It can also be helpful if you put the definition of a superstate and its substates plus all guards and entry/exit/transition actions in a class of itself.

Agreed about your suggestion for point 1. The client needs to see it as 1 state machine.

About point 2, I suggest to define some interface between your sub state machine and super state machine via internal triggers.

Let's call your super state machine A and your sub state machine B. A would fire an event such as StartB that would move B from some sort of Idle state to an InProgress state, i.e. running the sub state machine. Meanwhile A goes to some sort of WaitingForB state. When B is done with its subprocess, it would fire an event like BComplete on A. A will then continue with the rest of its process.

You could have A and B share the same set of possible triggers, but B could also define its own (smaller) set of triggers or on a level that fits with the subprocess it abstracts. I think it makes most sense to abstract a substate machine B out of your one-big-piece state machine A if B does not need to respond to the same complete set of triggers as A.

like image 114
stevenv Avatar answered Nov 15 '22 04:11

stevenv