Skip to content

Instantly share code, notes, and snippets.

@evandrododo
Last active December 10, 2021 01:36
Show Gist options
  • Save evandrododo/2c7e1a1d172a5c03d67c84f09c13fcba to your computer and use it in GitHub Desktop.
Save evandrododo/2c7e1a1d172a5c03d67c84f09c13fcba to your computer and use it in GitHub Desktop.
Testes para aplicar máquina de estados com laravel

Utilizando Máquina de estados com Laravel

Fiz alguns testes para aplicarmos máquina de estados no Laravel, e acho que seria legal compartilhar esse conhecimento para quem achar que pode ser útil :)

Conceito de máquina de estados

Wikipédia define melhor do que eu poderia resumir:

Uma máquina de estados finita (FSM - do inglês Finite State Machine) ou autômato finito é um modelo matemático usado para representar programas de computadores ou circuitos lógicos. O conceito é concebido como uma máquina abstrata que deve estar em um de um número finito de estados. A máquina está em apenas um estado por vez, este estado é chamado de estado atual. Um estado armazena informações sobre o passado, isto é, ele reflete as mudanças desde a entrada num estado, no início do sistema, até o momento presente. Uma transição indica uma mudança de estado e é descrita por uma condição que precisa ser realizada para que a transição ocorra. Uma ação é a descrição de uma atividade que deve ser realizada num determinado momento.

Definindo uma máquina de estados

Para testes defini uma máquina de estados representado 4 diferentes estágios do desenvolvedor:

  1. Acordando
  2. Comendo
  3. Fritando
  4. Dormindo

Só esses 4 estados são possíveis, e para trocar entre eles é preciso definir os 'caminhos'. Defini as seguintes transições para trocar entre os estados:

  • Comer (vai pro estado Comendo)
  • Tomar café (vai pro estado Fritando)
  • Dormir (vai pro estado Dormindo)
  • Acordar (vai pro estado Acordando)

Como uma imagem vale mais que mil palavras, taí um gif pra explicar as transições: estados de um desenvolvedor

Testando plugin

Para aplicar o conceito de máquina de estados no PHP um pacote bastante recomendado foi o do winzou, e para minha sorte, já existe um service provider pro laravel disponível no Github.

Instalei o plugin no laravel, defini a máquina de estados e fiz os seguintes testes:

// Pegando um usuario do banco                                                         
$u = App\Usuario::find(1); 
// Definindo um estado inicial
$u->estado = 'dormindo'; 
// Iniciando a maquina de estados para o usuario                             
$fsm = StateMachine::get($u, 'fsm'); 

// Perguntando o estado atual
$fsm->getState();                                                                                                 
=> "dormindo"                                                                                                        

// Verificar quais os possíveis estado futuros
$fsm->getPossibleTransitions();                                                                                  
=> [                                                                                                                 
     1 => "levantar",                                                                                                
   ]                                                                                                                 

// Aplicando uma transição
$fsm->apply("levantar");                                                                                         
=> true                                                                                                              

$fsm->getState();                                                                                                
=> "acordando"                                                                                                       

$fsm->getPossibleTransitions();                                                                                  
=> [                                                                                                                 
     0 => "comer",                                                                                                   
     2 => "tomar_cafe",                                                                                              
   ]                                                                                                                 

// Vendo se pode aplicar a transição dormir
$fsm->apply("dormir");                                                                                            
=> false
// Não pode, acabou de acordar!

// Vendo se pode aplicar a transição comer
$fsm->apply("comer");                                                                                            
=> true
// Pode comer sim

// Bateu a larica?
$fsm->apply("comer");                                                                                            
=> true                                                                                                              

$fsm->getState();                                                                                                
=> "comendo"                                                                                                         


$fsm->getPossibleTransitions();                                                                                  
=> [                                                                                                                 
     2 => "tomar_cafe",                                                                                              
     3 => "dormir",                                                                                                  
   ]                                                                                                                 

// Tomar um cafézinho pra dar uma acordada
$fsm->apply("tomar_cafe");                                                                                       
=> true                                                                                                             

$fsm->getState();                                                                                                
=> "fritando"                                                                                                         

$fsm->getPossibleTransitions();                                                                                 
=> [                                                               
     0 => "comer",                                                                                                  
     2 => "tomar_cafe",                                                                                             
     3 => "dormir",                                                                                                 
   ]

Para salvar o estado do usuário é necessário dar um $u->save(). A máquina de estados também pode chamar métodos dos controllers, antes e depois de aplicar uma transição, dando total controle ao trocar estados e aplicar regras de negócios específicos.

@lucaseduardofarias
Copy link

Bom dia, você poderia me fornecer o projeto laravel, que você implementou esse projeto demonstrado?

@evandrododo
Copy link
Author

Olá @lucaseduardofarias, o projeto onde a máquina de estados foi aplicado infelizmente foi desenvolvido para uma instituição que não permite a divulgação do source code :/
Esse exemplo que eu utilizei (do usuário que toma café, come e dorme) eu "desenvolvi" direto no tinker por ser fácil de testar, mas também sei que o conceito de state machine pode ser meio complicado algumas vezes, então fique a vontade para me enviar um email caso eu possa te ajudar com alguma dúvida ou aplicação prática da máquina de estados. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment