Spring Statemachine utilizando Kotlin

Alkxyly Samyr
4 min readFeb 8, 2022

--

O conceito de máquinas de estado finita ou autômato finito é muito antigo. Fazendo uma lida rápida sobre o assunto encontramos algumas definições, dentre elas:

FSM- do inglês Finite State Machine é um modelo matemático usado para representar programas de computadores. O conceito é concebido como uma máquina abstrata que deve estar em um número finido de estados.

Então vamos lá, um pouco de história…

A descrição de autômatos finitos nasceu em 1943 quando Warren McCulloch e Walter Pitts escreveram um artigo sobre isso e mais tarde, George H. Mealy introduziu o conceito de máquina de estado que ficou conhecido como Máquina de Mealy em 1955.

Um ano depois em 1956 Edward F. Moore apresentou um artigo ao qual descreveu o que é conhecido hoje como Máquina de Moore. Se você já leu um pouquinho sobre, vai reconhecer esses nomes aqui citados.

Mas, qual o propósito desse framework?

O Spring Statemachine(SSM) é um framework que utiliza conceitos sobre máquinas de estados e prover algumas features relacionadas.

Neste post irei fazer uma demonstração prática em Kotlin baseada na documentação do Spring Statemachine, alguns exemplos mais detalhados você poderá encontrar aqui.

Para aplicar o projeto busquei em um site focado em padrões de projeto e refatoração, o Refactoring Guru, e nele contém um exemplo que apresenta o padrão de projeto State, disponível aqui.

O problema

Temos um documento que pode assumir alguns estados, dentre eles:

  • RASCUNHO, MODERACAO e PUBLICADO.

Esses estados são definidos a partir de eventos e podemos definir esses eventos como:

  • PUBLICADO_POR_ADMINISTRACAO
  • PUBLICADO_POR_USUARIO
  • REVISAO_OU_FALHA, APROVADO ou EXPIROU.

Guarde o nome desses estados e eventos por que vamos utiliza-los em breve para a implementação da nossa máquina de estados.

Ilustração do Problema

Imagem obtida em: https://refactoring.guru/pt-br/design-patterns/state

Vamos adicionar a dependência do projeto Spring Statemachine no Maven.

Com a dependência configurada e o projeto OK, vamos partir para a implementação. Precisamos agora criar as enumerações que representam os estados e os eventos da nossa máquina de estados. Para representar os estados crie a enum DocumentoStates e nele adicione os estados da sua máquina.

E, para representar os eventos crie a enum DocumentoEvents.

Agora que definimos nossas Enums vamos criar a classe de configuração que irá representar a máquina de estados e nessa classe iremos implementar a configuração dos estados, transições, eventos e guardas.

Chamei a classe de DocumentoStateConfig e nela adicionei as seguintes anotações @Configuration e @EnableStateMachine. Além disso, estendi a classe EnumStateMachineConfigurerAdapter e passei como parâmetro as Enums que representam os estados e os eventos da máquina de estados.

No primeiro método a ser sobrescrito, vamos implementar a configuração inicial e o listener que irá identificar as transições dos estados da nossa máquina de estados.

No método getListener() estamos criando uma instância da classe StateMachineListenerAdapter e tornando essa classe um Bean gerenciado pelo Spring, com a anotação @Bean.

O segundo método que iremos sobrescrever é esse abaixo, nele dizemos quem é o estado inicial e quais os estados que fazem parte da máquina. É possível adicionar um evento quando o estado chegar no estado PUBLICADO, nesse caso estamos enviando um e-mail.

Para essa action funcionar é necessário implementar a interface Action e sobrescrever o método execute, para isso vamos criar a classe EnviarEmailAction.

Agora precisamos definir as transições, quando um evento ocorrer, o estado saíra de seu estado (source) e irá para o estado destino (target). Também é possível adicionar guards para validar se o evento será ou não executado.

Depois que definimos quais os fluxos de estados a partir dos eventos, vamos implementar o método responsável por verificar as mudanças de estado. Crie uma classe que estende a classe StateMachineListenerAdapter e implemente o método stateChenged.

Para verificar o fluxo dos estados a partir dos eventos, vamos colocar a máquina de estados para funcionar.

Como resultado obtemos o log ao executar o código acima e a explicação do passo a passo é:

  1. É configurado um estado inicial RASCUNHO.
  2. Quando o evento PUBLICADO_POR_USUARIO ocorreu o estado saiu de RASCUNHO para MODERACAO.
  3. Em seguida o evento aprovado foi disparado e com isso o estado foi de MODERACAO para PUBLICADO
  4. o envio do email ocorreu devido a mudança de estado do item 3.
  5. Com o evento EXPIROU o estado foi de (source) PUBLICADO para (target) RASCUNHO

Conclusão

O Spring State Machine é uma boa pedida quando você quer representar parte do seu sistema como estados finitos ou dividir a parte mais complexa em tarefas menores e gerenciáveis.

O principal ganho ao utilizar uma solução como o Spring State Machine é evitar que o código das transições e dos estados fiquem dispersos em seu código tornando assim a manutenção cada vez mais difícil. Dessa forma a consistência do seu software se torna muito melhor e o controle sobre os eventos e estados se concentram em um único ponto, ou seja, temos um único ponto de mudança.

Com certeza ainda é possível explorar outros pontos do projeto Spring State Machine. Este post tem o intuito de apresentar o conceito de uma forma breve e realizar um pequeno estudo de caso utilizando a linguagem de programação Kotlin.

Referências

--

--