O TOPO Contábil tem um workflow de conciliação bancária. Quando mapeei pela primeira vez, contei 16 estados distintos. De "importacao_bruta" até "conciliado," "parcialmente_conciliado," "contestado," "revisao_manual," "aprovado," "lancado," e mais uns nove que existem porque contabilidade é um pesadelo vestido de planilha Excel.
A primeira versão usava isRevisado, isAprovado, isLancado, isContestado e isConciliadoManualmente. Cinco booleanos dão 32 combinações, das quais talvez 16 sejam válidas. O resto é dado corrompido esperando pra estourar. Pegamos uma transação "contestada" e "aprovada" ao mesmo tempo porque duas pessoas clicaram no botão juntas. As flags alternaram independentemente. Caralho.
Com máquina de estado, uma transação em "contestado" só pode ir pra "em_revisao" ou "rejeitado". Ela não pode virar "aprovado" porque essa aresta não existe no grafo. As combinações impossíveis dos booleanos deixam de ser representáveis.
Cada estado é um objeto com transições permitidas, condições de guarda e efeitos colaterais. O guard checa a regra de negócio antes de permitir a transição: esse usuário pode aprovar uma transação acima de R$10K? A documentação de suporte tá anexada? Depois da transição bem-sucedida, os efeitos mandam a notificação, registram o log de auditoria e atualizam o livro razão.
O problema da explosão de estado é real. 16 estados com média de 3 transições cada = 48 arestas no grafo. Cada aresta tem guard e efeito colateral. É muito código se tu não tomar cuidado. Solução: convenção sobre configuração. A maioria dos guards é composável. "temPermissao AND temDocumentacao AND valorAbaixoDoLimite." Tu monta uma biblioteca de funções guard pequenas e compõe. Mesma coisa pros efeitos colaterais.
A gente armazena o estado atual e o histórico completo de transição. Cada mudança de estado é entrada append-only no log com timestamp, usuário, estado anterior, estado novo e resultados dos guards. Isso não é opcional pra software contábil. Auditor vai perguntar "quem moveu isso de contestado pra aprovado e quando." Se tua resposta for "é, deixa eu checar as colunas booleanas," tu tá ferrado.