Подтвердить что ты не робот

Как использовать преимущества системы без гражданства

Я хотел бы использовать http://code.google.com/p/stateless в своем коде, чтобы отделить функциональность от своих зависимостей. Я не нашел каких-либо расширенных примеров использования, поэтому этот вопрос касается лучших практик в системе без учета состояния.

У меня есть следующая конфигурация (это просто пример, имеет только одно состояние функции):

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
}

где можно вызвать фактическую функциональность. У меня были следующие идеи, но у каждого из них есть свои преимущества и недостатки:

1) Задайте функциональность, а также следующий огонь в 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);

поэтому, если я просто позвоню

stateMachine.Fire(Trigger.Succeed);

он заканчивается либо в State.Finished, либо в State.Error

  • преимущества - все вместе
  • недостатки - решение не может быть действительно unittested

2) имеют statemachine и функциональность, разделенные как:


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(); } }

  • Преимущества
  • : statemachine может быть протестирован сам.
  • Недостатки: мне это совсем не нравится

3) какое-то другое решение?

Я буду рад за любой ответ

4b9b3361

Ответ 1

Мне нравится BugTrackerExample, который у них есть в исходном коде.

Итак, ваша машина, вероятно, будет выглядеть так:

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()
    {
        // ...         
    }
}

В этом случае тесты не должны быть проблемой.

Если вам нужно дополнительное разделение, вы можете использовать шаблон event, delegate или strategy вместо метода Generate.

Ответ 2

Николас Блумхардт написал хороший пост о структуре без гражданства.