Basic State Machine setup using Stateless

12,227

The machine is in only one state at a time; the state it is in at any given time is called the current state. It can change from one state to another when initiated by a triggering event or condition, this is called a transition. from Finite-state machine on Wiki

I believe, the trigger is this triggering event.

Update:

Of course trigger name sometimes can be equal to some of state names.

New (initial state)
New -> Filled (trigger "Filled")
New -> Cancelled (trigger "Cancelled")
Filled -> Shipping (trigger "ToBeShipped")
Filled -> Cancelled (trigger "Cancelled")
Shipping -> Complete (trigger "Completed").

Update:

stateless is really nice framework! I've tried to implemented the functionality.

States:

public enum State
{
    New,
    Filled,
    Shipping,
    Cancelled,
    Completed
}

Triggers:

public enum Trigger
{
    Filled,
    Cancelled,
    ToBeShipped,
    Completed
}

Order class:

public class Order
{
    private readonly StateMachine<State, Trigger> _stateMachine;

    public Order()
    {
        _stateMachine = CreateStateMachine();
    }

    public bool TryUpdateOrderStatus(Trigger trigger)
    {
        if (!_stateMachine.CanFire(trigger))
            return false;

        _stateMachine.Fire(trigger);
        return true;
    }

    public State Status
    {
        get
        {
            return _stateMachine.State;
        }
    }

    private StateMachine<State, Trigger> CreateStateMachine()
    {
        StateMachine<State, Trigger> stateMachine = new StateMachine<State, Trigger>(State.New);
        stateMachine.Configure(State.New)
            .Permit(Trigger.Filled, State.Filled)
            .Permit(Trigger.Cancelled, State.Cancelled);

        stateMachine.Configure(State.Filled)
            .Permit(Trigger.ToBeShipped, State.Shipping)
            .Permit(Trigger.Cancelled, State.Cancelled);

        stateMachine.Configure(State.Shipping)
            .Permit(Trigger.Completed, State.Completed);

        stateMachine.OnUnhandledTrigger((state, trigger) =>
            {
                Console.WriteLine("Unhandled: '{0}' state, '{1}' trigger!");
            });
        return stateMachine;
    }
}

Tester for Order class:

Order order = new Order();
bool result = order.TryUpdateOrderStatus(Trigger.Completed);
Console.WriteLine("Attemp to complete order: {0}", result);
Console.WriteLine("Order status: {0}", order.Status);

result = order.TryUpdateOrderStatus(Trigger.ToBeShipped);
Console.WriteLine("Attemp to ship order: {0}", result);
Console.WriteLine("Order status: {0}", order.Status);

result = order.TryUpdateOrderStatus(Trigger.Cancelled);
Console.WriteLine("Attemp to cancel order: {0}", result);
Console.WriteLine("Order status: {0}", order.Status);
Share:
12,227
Ali Mst
Author by

Ali Mst

I am an IT Software Architect from Salt Lake City, Utah.

Updated on June 05, 2022

Comments

  • Ali Mst
    Ali Mst about 2 years

    I have some fairly simple state needs (for now). I think I would like to model these using the Stateless api. (But I don't really know much about state machines, so I could be wrong.)

    But I am getting caught up in the terminology (Specifically State and Trigger)

    Here is an example: I have an order class. It is setup with several states. They are: New, Filled, Shipping, Completed, Cancelled.

    A few simple state rules I would like is that these state transitions are allowed:

    • New (is the default)
    • New -> Filled
    • New -> Cancelled
    • Filled -> Shipping
    • Filled -> Cancelled
    • Filled -> Shipping
    • Shipping -> Complete

    So where I am getting tripped up here is what is my "Trigger"?

    Just in case a more specific example is needed, say I want a method like this:

    public bool UpdateOrderStatus(int OrderId, OrderStatusEnum NewOrderStatus)
    

    that will return true if the status updated successfully. How can setup and use Stateless to make this happen?

  • mbeckish
    mbeckish over 12 years
    @Vaccano - You vane't listed your triggers for us yet. For example, what action causes the New -> Filled transition? What action causes the New -> Cancelled transitions? I believe those would be your triggers. It looks like you don't tell the state machine which state transition to perform. You just define the triggers that cause state transitions, then fire triggers as they occur, and the state machine will do the state transitions.
  • Ali Mst
    Ali Mst over 12 years
    @mbeckish - Thanks for your comment. It would appear that a state machine is not for me. I will have a WCF service call that fires this state transition. (ie ShipOrders(List<int> orderIds)) I don't see how that can be made into an object.
  • Ali Mst
    Ali Mst over 12 years
    @Serge - Thanks for your answer! I had another issue pull me away from this for a day or so. When I am able to get back to it I will look at the code (and accept if it works). Thanks again!
  • swannee
    swannee over 11 years
    @Serge - Great answer, not sure why it hasn't been accepted, but helped me immensely...thanks!
  • Sergey Vyacheslavovich Brunov
    Sergey Vyacheslavovich Brunov over 11 years
    @swannee, glad it was useful.