c# - machine - stateless framework
Cómo sacar provecho del marco sin estado. (2)
Me gusta BugTrackerExample que tienen en el código fuente.
Entonces tu máquina probablemente se vería así:
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()
{
// ...
}
}
En este caso las pruebas no deberían ser problema.
Si necesita más separación, puede usar un patrón de evento, delegado o estrategia en lugar del método Generate
.
Me gustaría usar http://code.google.com/p/stateless en mi código para separar la funcionalidad de sus dependencias. No encontré ningún ejemplo avanzado del uso, por lo que esta pregunta es sobre las mejores prácticas de un marco sin estado.
Tengo la siguiente configuración (esto es solo un ejemplo, solo tiene un estado de función):
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
}
donde llamar a la funcionalidad real entonces. Tuve las siguientes ideas pero cada una de ellas tiene ventajas y desventajas:
1) Establezca la funcionalidad y el siguiente disparo en 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);
entonces si solo llamo
stateMachine.Fire(Trigger.Succeed);
termina en State.Finished o State.Error
- ventajas - todos juntos
- desventajas - la solución no puede ser realmente probada
2) tienen máquina separada y funcionalidad separada como:
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();
}
}
- Ventajas: el statemachine puede ser probado
- Inconvenientes: no me gusta.
3) ¿Alguna otra solución?
Me alegraré por cualquier respuesta
Nicholas Blumhardt escribió una buena publicación sobre el marco sin estado.