Act — a library for (hierarchical) state machines

Bertil Muth - Jun 9 '22 - - Dev Community

I created a library for defining executable state machines in your code. This includes the possibility to define hierarchical state machines with sub states. State machines simplify understanding how your code works when you have complex business rules.

As an oversimplified example for learning purposes, look at the following state machine for a shopping cart.

It represents its two fundamental states of being either empty, or non-empty.

The AddItem trigger causes a change to the non-empty cart state.

The RemoveItem trigger causes a change to the empty cart state, if the cart only contains 1 item.

Image of a statemachine of a shopping cart, with two states

And here's how the state machine is presented in code:

State<Cart, Trigger> emptyCartState = state("Empty Cart", cart -> cart != null && cart.items().size() == 0);
State<Cart, Trigger> nonEmptyCartState = state("Non-Empty Cart", cart -> cart != null && cart.items().size() > 0);

Statemachine<Cart, Trigger> statemachine = Statemachine.builder()
    .states(emptyCartState,nonEmptyCartState)
    .transitions(
        transition(anyState(), nonEmptyCartState, 
            when(AddItem.class, consumeWith(Cart::addItem))),

        transition(nonEmptyCartState, nonEmptyCartState, 
            whenInCase(RemoveItem.class, i -> i.state().items().size() > 1, supplyWith(Cart::removeItem))),

        transition(nonEmptyCartState, emptyCartState, 
            whenInCase(RemoveItem.class, i -> i.state().items().size() == 1, supplyWith(Cart::removeItem)))
    )
    .flows(
        entryFlow(when(CreateCart.class, init(Cart::createCart)))
    )
    .build();
Enter fullscreen mode Exit fullscreen mode

Please visit the project on GitHub for details. I'm looking forward to your feedback.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .