Как использовать преимущества системы без гражданства
Я хотел бы использовать 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) какое-то другое решение?
Я буду рад за любой ответ
Ответы
Ответ 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
Николас Блумхардт написал хороший пост о структуре без гражданства.