Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to get advantage of stateless framework

I would like to use http://code.google.com/p/stateless in my code to separate the functionality from its dependencies. I didn't find any advanced examples of the usage, so this question is about stateless framework best practices.

I have following configuration (this is just example, has only one function state):

var stateMachine = new StateMachine(State.Stopped);

stateMachine.Configure(State.Stopped)
    .Permit(Trigger.Failed, State.Error)
    .Permit(Trigger.Succeed, State.GenerateMachineData);

stateMachine.Configure(State.GenerateMachineData)
    .Permit(Trigger.Failed, State.Error)
    .Permit(Trigger.Succeed, State.Finished);

public enum State
{
    Stopped,
    GenerateMachineData,
    Finished,
    Error
}

public enum Trigger
{
    Succeed,
    Failed
}

where to call the actual functionality then. I had following ideas but each of them has advantages and disadvantages:

1) Set the functionality as well as next fire in OnEntry():

stateMachine.Configure(State.GenerateMachineData)
.OnEntry(() => { 
    try {
       Generate(); 
       stateMachine.Fire(Trigger.Succeed);
    } catch {
       stateMachine.Fire(Trigger.Error);
    } 
})
.Permit(Trigger.Failed, State.Error)
.Permit(Trigger.Succeed, State.Finished);

so then if I just call

stateMachine.Fire(Trigger.Succeed);

it ends up either in State.Finished or State.Error

  • advantages - all together
  • disadvatages - the solution cant be really unittested

2) have statemachine and functionality separated like:

void DoTheStuff() {
    switch (stateMachine.State)
    {
         State.Stopped:
              stateMachine.Fire(State.Succeed);
              break;
         State.GenerateMachineData:
              Generate();
              stateMachine.Fire(State.Succeed);
              break;
         default:
              throw new Exception();
    }
}

void Main() { while (stateMachine.State != State.Succeed && stateMachine.State != State.Error) { DoTheStuff(); } }

  • advantages: the statemachine can be tested itself
  • disadvantages: I quite don't like it

3) some other solution?

I will be glad for any answer

like image 297
Tomas Panik Avatar asked Mar 10 '11 00:03

Tomas Panik


2 Answers

Nicholas Blumhardt wrote good post about stateless framework.

like image 101
xelibrion Avatar answered Sep 30 '22 22:09

xelibrion


I like BugTrackerExample which they have in source code.

So your machine would probably look like this:

class Generator
{
    private readonly StateMachine state;

    public Generator()
    {
        state = new StateMachine(State.Stopped);

        // your definition of states ...

        state.Configure(State.GenerateMachineData)
        .OnEntry(() => { Generate(); })
        .Permit(Trigger.Failed, State.Error)
        .Permit(Trigger.Succeed, State.Finished);

        // ...
    }

    public void Succeed()
    {
        state.Fire(Trigger.Succeed);
    }

    public void Fail()
    {
        state.Fire(Trigger.Fail);
    }

    public void Generate()
    {
        // ...         
    }
}

In this case tests shouldn't be problem.

If you need further separation you can use event, delegate or strategy pattern instead of Generate method.

like image 37
Jakub Šturc Avatar answered Sep 30 '22 21:09

Jakub Šturc