Statecharts: máquinas de estado hierárquicas
(statecharts.dev)- Um formato para estruturar visualmente o comportamento de sistemas complexos, reforçando a state machine básica para lidar com o problema de state explosion
- Torna possível a separação entre comportamento e componentes, facilitando mudanças no funcionamento, o raciocínio sobre o código, testes independentes dos componentes e a exploração de casos excepcionais
- No processo de criar um statechart, acaba-se explorando todos os estados possíveis, e há resultados de pesquisa mostrando menos bugs em código baseado em statecharts do que em código tradicional
- Com o padrão SCXML e ferramentas e bibliotecas em várias linguagens, é possível ler, escrever e executar modelos, além de ajudar a tratar corretamente a ordem de execução de ações como entry/exit action
- Ao usar um formato de máquina executável, é possível adotar uma única definição como single source of truth para manter juntos o comportamento em runtime e o diagrama, tornando importante manter implementação e design sincronizados
Visão geral de Statecharts
- Statechart é um formato visual para lidar com sistemas complexos, uma extensão da state machine básica
- Ele foi reforçado para lidar com o problema de state explosion que surge quando a state machine cresce
- Embora seja possível representar o comportamento como um diagrama, em engenharia de software isso está mais próximo de modelagem de comportamento e estruturação do que da visualização em si
- Explicações básicas relacionadas continuam em What is a state machine? e What is a statechart?
Por que usar Statecharts
- Têm uma estrutura fácil de entender, sendo mais fáceis de compreender do que muitas outras formas de código
- Permitem a separação entre comportamento e componentes
- Fica mais fácil alterar o funcionamento
- Fica mais fácil raciocinar sobre o código
- É possível testar o comportamento independentemente dos componentes
- No processo de criar um statechart, você explora todos os estados possíveis
- Há resultados de pesquisa mostrando menos bugs em código baseado em statecharts do que em código tradicional
- São adequados para lidar com situações excepcionais que costumam passar despercebidas
- Conforme a complexidade cresce, a escalabilidade melhora
- Também são fáceis de entender para pessoas não desenvolvedoras, e o QA pode usá-los como ferramenta de exploração
- Muito código já contém implicitamente uma state machine, e o statechart funciona como uma forma de explicitar isso
Custos e fatores contrários aos Statecharts
- Exigem um novo custo de aprendizado
- O conceito-base de state machine em si pode já ser familiar para muitos programadores
- Como são bem diferentes da forma tradicional de programar, podem parecer um paradigma pouco familiar
- Isso pode gerar resistência no nível do time
- Em statecharts pequenos, o processo de separar o comportamento pode aumentar o número de linhas de código
- Entre os motivos para não serem amplamente usados estão a falta de conhecimento e o YAGNI atuando em conjunto
- Argumentos contrários comuns incluem a ideia de que não são realmente necessários, de que não combinam com certos direcionamentos técnicos e de que aumentam o número de bibliotecas
- Em aplicações web, o tempo de carregamento pode aumentar
- Mesmo considerando esses prós e contras, o efeito da adoção tende, no geral, a ser positivo
Forma de uso e SCXML
- SCXML é um formato padronizado pela W3C entre 2005 e 2015 que define várias regras semânticas dos statecharts e o tratamento de edge cases
- Existem ferramentas em várias linguagens para ler, escrever e executar SCXML
- Também existem formatos derivados com sintaxe diferente, mas mantendo o mesmo modelo
- Há bibliotecas de statecharts para várias plataformas, com diferentes níveis de suporte às regras semânticas do SCXML
- Essas bibliotecas ajudam a tratar corretamente a ordem de execução de ações como entry/exit action
- Um guia adicional de uso continua em how to use statecharts
Statecharts executáveis
- Em vez de usar statecharts apenas como documentação, é possível usar um formato de máquina executável tanto no design quanto no runtime
- Uma única definição pode servir como single source of truth, acionando ao mesmo tempo o comportamento real em runtime e o diagrama visual
- Isso elimina a necessidade de traduzir o diagrama para código
- Também reduz bugs gerados na tradução manual
- O diagrama e a implementação permanecem sempre sincronizados
- O diagrama se torna mais preciso
- Por outro lado, o diagrama pode ficar bastante complexo
- As opções de formatos e ferramentas para statecharts executáveis são limitadas
- É difícil garantir com força a segurança de tipos entre o statechart e os componentes
- Se a definição do statechart estiver no código, é possível gerar automaticamente um statechart visual a partir dessa representação
- Isso fica mais simples quando a definição está em um arquivo separado, como JSON ou XML
Comunidade e materiais adicionais
- A conversa da comunidade continua no gitter.im, e é possível ver o chat sem fazer login
- Discussões em formato de perguntas e respostas continuam em statecharts GitHub discussions
- Livros e materiais de apresentação estão reunidos na página resources
- Materiais produzidos por você podem ser compartilhados em GitHub Discussions
-
Leituras adicionais
- Use case: Statecharts in User Interfaces
- Concepts — conceitos centrais de statecharts e como aparecem em diagramas
- Glossary — termos usados com frequência e suas definições
- FizzBuzz — aborda conceitos de statecharts com base no FizzBuzz
- Acknowledgements
1 comentários
Comentários do Hacker News
Fico feliz em ver statecharts continuarem recebendo atenção
Eu criei o XState, uma biblioteca para escrever/executar/visualizar máquinas de estado e statecharts para JS/TS, e ela pode ser vista em https://github.com/statelyai/xstate
A principal lição que aprendi em mais de 10 anos trabalhando nisso é que statecharts têm muito mais valor quando são tratados não como documentação simples, mas como comportamento executável
Não é algo para usar em todo lugar, mas é especialmente poderoso quando "o que acontece a seguir?" depende tanto do estado atual quanto do evento
Esse tipo de gráfico pode ser usado como um oráculo que responde: "neste estado atual, se este evento chegar, qual é o próximo estado e quais efeitos serão executados?"
A próxima grande versão alfa do XState também está quase pronta, com foco em ergonomics, segurança de tipos, composability e um novo visualizer/editor
A ferramenta básica de visualização open source está em https://sketch.stately.ai
No lado de especificação formal, vale a pena ler SCXML: https://www.w3.org/TR/scxml
O artigo original de David Harel também é muito valioso: https://www.weizmann.ac.il/math/harel/sites/math.harel/files/users/user50/Statecharts.pdf
Também existe um vídeo de uma apresentação na Laracon em que organizei minhas ideias sobre state machines e statecharts
https://www.youtube.com/watch?v=1A1xFtlDyzU
É uma implementação bastante madura que chega bem perto de SCXML, mas elimina a exigência de XML, especialmente no conteúdo executável
O XState também aparece como referência na seção de prior art
Eu o apliquei junto com lit.js em um componente de navegação estilo drawer que reage à largura da página e tem muitas props e estado interno, e nem consigo imaginar o quão terrível teria sido sem XState
Estou ansioso pela próxima versão, e muito obrigado mesmo
A inferência automática de tipos em TS é bem boa, então é prático para casos em que você precisa de lógica leve de máquina de estado
Antigamente parecia que statecharts estavam ganhando impulso aos poucos no ecossistema de frontend/UI, e é uma pena que essa onda tenha desaparecido por algum motivo
Quando se usa máquinas de estado para interações de UI, especialmente composições de máquinas de estado como statecharts, fica muito mais fácil raciocinar sobre fluxos complexos
Se você está tendo o primeiro contato com isso, recomendo fortemente "Constructing the user interface with statecharts", de Ian Horrucks
Embora seja um livro de 1999, ele ainda está entre os melhores como introdução que explica como aplicar e usar isso na prática
https://archive.org/details/isbn_9780201342789/mode/2up
Os downloads semanais no npm já passam de 4 milhões, e ferramentas de animação como Rive e LottieFiles também destacam fortemente funcionalidades de máquina de estado
Ferramentas de IA como LangGraph também são construídas sobre uma base de máquina de estado
Talvez esses apps e ferramentas ainda precisem de mais tempo para explorar totalmente o potencial dos statecharts, mas o começo é bom
https://github.com/derkork/godot-statecharts
Algo que frequentemente fica de fora dos materiais introdutórios são os history pseudo-states
Quando se usa H, H, de fora o statechart se torna formalmente não determinístico
Costuma-se explicar isso como "o estado atual é uma função pura da entrada", mas history quebra essa premissa
Se você entra novamente no estado pai via H, volta para o filho que estava ativo por último, então mesmo com o mesmo evento e o mesmo estado externo é possível entrar em estados internos diferentes
Esse "último filho ativo" oculto já é, por si só, um estado, mas normalmente ele não aparece desenhado no diagrama
O artigo original de Harel reconhece isso, e SCXML e XState também implementam isso, mas curiosamente quase não se fala dessa parte
Então, se você preserva o estado da subárvore ao reentrar com deep history, está basicamente transferindo o bookkeeping para o lado do mecanismo do gráfico
É uma escolha razoável, mas isso significa que só o desenho não consegue explicar todo o comportamento, e transições de history também precisam de testes separados como qualquer outra lógica de estado
Nessa segunda interpretação, a máquina é totalmente determinística, e o ponteiro de deep history é apenas parte do estado da máquina de estados
Por exemplo, você pode expandir os nós H, H em vários nós e tratar H' como algo parecido com um write-ahead log colocado antes de cada nó
Fico curioso se daria para combinar mecanismos de execução durável como Temporal, DBOS, Restate com statecharts
Na empresa usamos Cloudflare Workflows para gerenciar workflows de onboarding e pagamento, e os diagramas de flowchart gerados automaticamente ajudam a entender rapidamente o comportamento do workflow
No fim, isso parece bem parecido com o valor que statecharts tentam oferecer
https://zindex.ai/
Diagramas gerados por IA geralmente são Mermaid/SVG/PNG gerados uma vez e prontos, sem um estado persistente do diagrama que possa ser atualizado, validado, comparado por diff e reutilizado
O Zindex trata o próprio diagrama como estado estruturado
Quando agentes aplicam patches em nós, arestas, grupos, relações, restrições e revisões via Diagram Scene Protocol (DSP), o Zindex cuida de validation, layout, rendering, versioning e storage
Por isso, acho que ele pode ficar ao lado de Temporal/DBOS/Restate/Cloudflare Workflows, deixando a fonte da verdade da execução com o mecanismo e fazendo o Zindex gerenciar um modelo visual persistente e inspecionável derivado do código ou do histórico de execução
Na prática, statecharts também conseguem fazer isso tranquilamente se você adicionar durable execution
A Cloudflare parecia estar caminhando por um tempo na direção do modelo de ator com durable object, mas não sei se eles abandonaram esse projeto
Queria saber se é um recurso embutido no Cloudflare Workers ou algo que a equipe construiu por conta própria
Eu realmente adoro XState
Ele resolveu inúmeros problemas em vários codebases, e recentemente se tornou a espinha dorsal principal de um app de voz que estamos criando para o setor bancário
Obrigado por investir tanto tempo e esforço para torná-lo tão bom
Também organizei um pouco num blog a minha experiência com finite state machines e a arquitetura que montei com XState + Mastra
Depois da publicação, troquei o Mastra por Pipecat
https://blog.davemo.com/posts/2026-02-14-deterministic-core-agentic-shell.html
Vou deixar isto aqui também
ETL State Chart e Hierarchial FSM:
https://www.etlcpp.com/state_chart.html / https://www.etlcpp.com/hfsm.html
Quantum Leaps:
https://www.state-machine.com
Usei principalmente em sistemas safety-critical, onde complexidade, timing e possibilidade de verificação do comportamento são especialmente importantes
O fato de ser possível separar tomada de decisão e ação ajuda muito
Essa forma de reduzir a tomada de decisão a "neste estado atual, se este evento chegar, o que devo fazer em seguida" é um pouco diferente da estrutura usual dos programas, mas cria uma boa separação e torna mais fácil raciocinar sobre o comportamento em várias condições
Sempre esperei que a adoção de máquinas de estado crescesse mais
Numa era em que código gerado por IA não é compreendido pelos humanos tão profundamente quanto código escrito por pessoas, a compreensão visual do estado se torna cada vez mais importante
Ainda assim, frameworks de frontend parecem continuar preferindo estado reativo baseado em store
Eu mesmo costumo usar isso como padrão, então nunca fiz questão de mudar, e também existe a percepção de que bibliotecas como xstate são mais difíceis de aprender e mais verbosas
Mas com IA essa barreira quase desaparece, então fico me perguntando se existe algum outro motivo que eu não esteja vendo, ou se statecharts ainda não atingiram seu auge
A superfície da API vai diminuir, a curva de aprendizado vai cair, e tanto desenvolvedores quanto agentes vão conseguir escrever com mais facilidade
Ao mesmo tempo, os modelos de fronteira mais modernos já escrevem código em XState bastante bem
Enquanto trabalhava no projeto https://github.com/xlnfinance/xln, percebi que precisava de um jeito de emular a rede de forma determinística na prática
Aí me ocorreu que toda blockchain é, no fim das contas, uma máquina de estado replicada, então por que não envolver cada nó de usuário em uma hierarquia de máquinas de estado em 3 níveis: Runtime -> Entity -> Account
É uma estrutura em que a máquina externa controla completamente a máquina interna, então seria algo como "blockchain dentro de blockchain" com diferentes modos de consenso
Depois procurei por "hierarchical state machines" e encontrei statecharts, e senti que as duas ideias eram bem parecidas
Na minha visão, mais software deveria usar hierarquias de máquinas de estado para reduzir os piores bugs causados pela não determinismo
No setor automotivo, esse tipo de abordagem já é usado há muito tempo
Se você olhar para matlab/simulink, dá para desenhar algoritmos como máquinas de estado e até gerar código a partir disso
Recentemente implementei uma máquina de estado para gerenciar um componente React bem complexo, que passava por várias condições visuais durante transições de CSS
A máquina de estado em si não era tão difícil, mas as pessoas ainda não parecem estar familiarizadas o suficiente com isso
Na empresa, desde que eu criei um interpretador dentro do Postgres, estamos executando todos os processos de negócio com statecharts
A experiência foi muito boa, os processos ficaram muito resilientes a mudanças e continuam fáceis de entender mesmo quando voltamos a eles anos depois
Também deixei a biblioteca em open source
https://github.com/kronor-io/statecharts