19

コードでhttp://code.google.com/p/statelessを使用して、機能をその依存関係から分離したいと考えています。高度な使用例が見つからなかったため、この質問はステートレス フレームワークのベスト プラクティスに関するものです。

次の構成があります (これは単なる例であり、機能状態は 1 つだけです)。

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 のいずれかになります。

  • 利点 - すべて一緒に
  • 短所 - ソリューションは実際にはユニットテストできません

2) ステートマシンと機能を次のように分離します。

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

  • 利点: ステートマシン自体をテストできる
  • 短所:あまり好きではない

3) 他の解決策はありますか?

どんな答えでも嬉しいです

4

2 に答える 2

13

Nicholas Blumhardt はステートレス フレームワークについて良い記事を書きました。

于 2011-05-13T14:41:04.537 に答える
10

ソースコードに含まれている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()
    {
        // ...         
    }
}

この場合、テストは問題になりません。

さらに分離する必要がある場合は、Generateメソッドの代わりにイベント、デリゲート、または戦略パターンを使用できます。

于 2011-05-12T16:05:16.297 に答える