Estado-machine: Como mudar de estado sem evento externo (estado transiente)?
-
22-08-2019 - |
Pergunta
O cenário:
Eu tenho uma máquina de estado simples:
caminho feliz:
Uninitialized->Initialized->InProgress->Done
caminho infeliz:
Uninitialized->Initialized->Error
Basta colocar, eu preciso fazer uma transição (seja em InProgress ou em estado de erro) sem um evento externo / gatilho . Ou seja, estado inicializado deve resultar imediatamente em um desses estados.
Perguntas:
- É OK para transição de estado causa de dentro Initialized.Enter () ?
- Eu poderia usar guardas Estado para fazer isso, mas eu prefiro não ter lógica não-trivial na guarda do Estado (e inicialização pode muito bem ser complexo).
- Se não é OK, como posso fazê-lo de forma diferente?
- Devo apenas tomar esta decisão fora de ele FSM todos juntos e ter algum outro componente causa a transição apropriada? Mas então, não seria eu ainda tenho que chamar esse componente externo a partir do Initialized.Enter () ? por isso não resolve nada?
Solução
Em uma máquina de estado, próximo estado é uma função lógica combinatória de entrada e estado atual.
No caso você está descrevendo, a mesma causa (estado Initialized
) parece ser capaz de desencadear dois efeitos diferentes (quer InProgress
ou estaduais Error
). Eu acho que há uma entrada oculta cujo valor faz a diferença. Eu também acho que essa entrada é recebido durante a transição de Uninitialized
para Initialized
.
Portanto, eu teria um modelo diferente:
Uninitialized -> Successfully initialized -> InProgress -> Done
\
`-> Failed Initialization -> Error
combinando Possivelmente Successfully initialized
com InProgress
e Failed initialization
com Error
.
Editar : Desde o seu comentário, eu entendo que a entrada escondida na verdade é o resultado de uma ação (a inicialização do dispositivo). Tomar o seu modelo, presumo que a inicialização ocorre enquanto no estado Initialized
(vamos chamá-lo Initializing
). Desta forma, o resultado do dispositivo é o seu evento externo que irá desencadear transição quer para InProgress
ou para Error
.
Portanto, manter a sua máquina de estado e simplesmente adicionar o resultado de device.Initialize()
à lista de entradas ou de eventos externos.