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:
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?
State is a behavioral design pattern that allows an object to change the behavior when its internal state changes. The pattern extracts state-related behaviors into separate state classes and forces the original object to delegate the work to an instance of these classes, instead of acting on its own.
A state machine is a mathematical abstraction used to design algorithms. A state machine reads a set of inputs and changes to a different state based on those inputs. A state is a description of the status of a system waiting to execute a transition.
A finite state machine is a mathematical abstraction used to design algorithms. In simpler terms, a state machine will read a series of inputs. When it reads an input, it will switch to a different state. Each state specifies which state to switch to, for a given input.
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With