wandres.dev
STATECHARTS · jerarquía y paralelismo

Statecharts: la respuesta de Harel a la explosión de estados

Una FSM plana modela un sistema como una lista de estados y transiciones, y funciona de maravilla hasta que el sistema adquiere varias dimensiones independientes o preocupaciones transversales. Entonces el número de estados y de aristas crece de forma explosiva y el diagrama se vuelve ingobernable. En 1987 David Harel publicó los statecharts, un formalismo visual que añade jerarquía, ortogonalidad, historia y comunicación por difusión a la máquina clásica. Esta lección explica por qué la FSM plana se rompe, qué añade exactamente cada mecanismo de Harel, y por qué XState v5 y SCXML son su encarnación ejecutable en 2026.

⏱ 16 min

La máquina de estados finita es una de las abstracciones más limpias de la computación: un conjunto de estados, uno inicial y unas transiciones etiquetadas por eventos. Funciona de maravilla para un torniquete o un semáforo. Pero en cuanto la usas sobre un sistema real —un reproductor que además descarga, un formulario que valida mientras envía, una UI con media docena de conmutadores independientes— la FSM plana se desborda: los estados se multiplican y las aristas se repiten hasta volver el diagrama ilegible. David Harel bautizó ese fenómeno como la explosión de estados y, en 1987, propuso la cura. Los statecharts no sustituyen a la FSM: la extienden con cuatro ideas que la vuelven componible. Es el punto de partida del formalismo que domina el modelado de estado en 2026.

🎯 Al terminar esta lección sabrás
  • Nombrar las debilidades de la FSM plana que disparan la explosión de estados.
  • Distinguir la explosión aditiva de aristas de la multiplicativa de estados.
  • Enunciar la fórmula de Harel: statechart igual a FSM más jerarquía, ortogonalidad, historia y difusión.
  • Situar XState v5 y el estándar SCXML como la encarnación ejecutable del formalismo.

El techo de la FSM plana

En una FSM plana el sistema está siempre en exactamente uno de sus estados, y todos viven en un mismo saco sin estructura. Esa planitud es su virtud y su condena. Considera un semáforo que, además de su ciclo normal, puede averiarse desde cualquier fase y quedar en modo intermitente. Como no hay jerarquía, el evento AVERIA debe salir de cada estado por separado.

import { createMachine } from 'xstate'

// FSM plana: la misma salida de emergencia repetida en cada estado
const semaforo = createMachine({
  id: 'semaforo',
  initial: 'verde',
  states: {
    verde: { on: { TICK: 'ambar', AVERIA: 'intermitente' } },
    ambar: { on: { TICK: 'rojo', AVERIA: 'intermitente' } },
    rojo: { on: { TICK: 'verde', AVERIA: 'intermitente' } },
    intermitente: { on: { REPARAR: 'rojo' } },
  },
})

La arista AVERIA aparece tres veces, una por estado operativo. Con tres estados es un fastidio; con treinta, es una fuente inagotable de olvidos: basta añadir un estado nuevo y olvidar su salida de emergencia para que el sistema quede atrapado. La FSM plana no tiene forma de decir de una vez por todas.

stateDiagram-v2
verde --> ambar: tick
ambar --> rojo: tick
rojo --> verde: tick
verde --> intermitente: averia
ambar --> intermitente: averia
rojo --> intermitente: averia
intermitente --> rojo: reparar

Dos explosiones, no una

La explosión de estados no es un solo problema, sino dos con orígenes distintos, y confundirlos lleva a soluciones equivocadas.

La primera es aditiva y afecta a las aristas. Cada preocupación transversal —un evento válido desde cualquier estado, como AVERIA, CANCELAR o CERRAR_SESION— obliga a dibujar una transición desde los n estados existentes. Añadir un solo evento global multiplica las aristas por el tamaño de la máquina. El diagrama se convierte en una maraña donde la lógica esencial queda enterrada bajo la repetición.

La segunda es multiplicativa y afecta a los estados. Cuando un sistema tiene k dimensiones independientes, cada una con sus propios valores, la FSM plana está obligada a representar el producto cartesiano de todas ellas. Un fragmento de texto con negrita, cursiva y subrayado —tres conmutadores binarios— exige dos elevado a tres, es decir ocho estados, solo para recordar qué combinación está activa. Añade tachado y son dieciséis. Cada nueva dimensión duplica el universo de estados, aunque conceptualmente solo hayas sumado un interruptor más.

Explosión aditiva

Un evento común a todos los estados cuesta n aristas idénticas. El culpable es la falta de un lugar donde declarar lo compartido. La cura será la jerarquía.

✖️

Explosión multiplicativa

Dimensiones independientes obligan al producto cartesiano: k conmutadores binarios dan dos elevado a k estados. La cura será la ortogonalidad.

🧭

Pérdida de memoria

Una FSM plana que sale de una región y vuelve no recuerda dónde estaba. Reconstruir esa posición a mano añade aún más estados. La cura será la historia.

📡

Coordinación rígida

Que un cambio en una parte afecte a otra exige cablear transiciones a mano. La cura será la comunicación por difusión de eventos.

Las cuatro adiciones de Harel

Harel resumió su formalismo en una ecuación que conviene memorizar: un statechart es una FSM más profundidad, más ortogonalidad, más comunicación por difusión, con la historia como refinamiento práctico. Cada término ataca una de las patologías anteriores.

La profundidad, o jerarquía, permite que un estado contenga a otros. Un superestado operativo agrupa verde, ambar y rojo, y la transición AVERIA se declara una sola vez en el superestado: vale para todos sus hijos. La explosión aditiva desaparece.

const semaforo = createMachine({
  id: 'semaforo',
  initial: 'operativo',
  states: {
    operativo: {
      initial: 'verde',
      states: {
        verde: { on: { TICK: 'ambar' } },
        ambar: { on: { TICK: 'rojo' } },
        rojo: { on: { TICK: 'verde' } },
      },
      on: { AVERIA: 'intermitente' }, // UNA arista cubre los tres subestados
    },
    intermitente: { on: { REPARAR: 'operativo' } },
  },
})
stateDiagram-v2
[*] --> Operativo
state Operativo {
  verde --> ambar: tick
  ambar --> rojo: tick
  rojo --> verde: tick
}
Operativo --> Intermitente: averia
Intermitente --> Operativo: reparar

La ortogonalidad permite que dos regiones estén activas a la vez sin combinarse en un solo estado. Las tres dimensiones del texto viven en tres regiones paralelas de dos estados cada una: seis estados en total en lugar de ocho, y la ventaja crece exponencialmente con cada dimensión. La historia recuerda el subestado activo al abandonar un superestado, para retomarlo al volver. Y la difusión hace que un mismo evento llegue a todas las regiones, de modo que una acción en una pueda desencadenar una transición en otra sin cableado explícito.

ℹ️
OR-states y AND-states

Harel distingue dos maneras de descomponer un estado. Un superestado OR contiene subestados de los que exactamente uno está activo: es la jerarquía, la descomposición exclusiva. Un superestado AND contiene regiones de las que todas están activas a la vez: es la ortogonalidad, la descomposición concurrente. Toda la potencia del formalismo sale de anidar ambas descomposiciones libremente. Un estado ya no es un escalar, sino un árbol de estados activos que se llama configuración.

Del formalismo al runtime: XState y SCXML

El formalismo de Harel no se quedó en el papel. El W3C lo estandarizó como SCXML, un lenguaje XML de máquinas de estado con semántica precisa de jerarquía, paralelismo e historia. En el ecosistema JavaScript de 2026, XState v5 es su implementación de referencia: su API setup más createMachine expresa los cuatro mecanismos con tipos completos, y Stately Studio permite editar y simular el statechart visualmente, cerrando el círculo con la intención original de Harel de que el diagrama fuera el programa. Aprender statecharts hoy es aprender a pensar en configuraciones, no en estados sueltos, y a apoyarse en un runtime que respeta la semántica formal en lugar de improvisarla.

Elegir entre los cuatro mecanismos no es cuestión de gusto, sino de diagnosticar qué clase de complejidad tienes delante. Una heurística breve acierta casi siempre.

💡
Qué mecanismo aplicar y cuándo

Ante un comportamiento enrevesado, diagnostica antes de dibujar. Si el mismo evento se repite en muchos estados, te falta jerarquía: súbelo a un superestado y déjalo declarado una sola vez. Si un estado parece ser la mezcla de varias decisiones que no se estorban entre sí, te falta ortogonalidad: parte esas decisiones en regiones paralelas. Si al regresar a una pantalla el usuario espera reencontrarla tal como la dejó, te falta historia. Y si un cambio en una parte debería repercutir en otra, te falta coordinar por difusión. Cada patología tiene su cura exacta, y nombrarla es ya medio trabajo hecho.

El statechart es la FSM hecha componible

La lección profunda no es que los statecharts tengan más funciones que las FSM, sino que las vuelven composicionales. Una FSM plana es como un programa sin funciones ni módulos: todo el comportamiento vive en un único espacio de nombres global, y la única forma de expresar algo compartido es copiarlo. La jerarquía introduce el equivalente al ámbito léxico —un comportamiento declarado arriba aplica a todo lo de abajo—; la ortogonalidad introduce el equivalente a la composición de módulos independientes; la historia, una forma de memoria local; la difusión, un canal de comunicación entre módulos. Por eso la explosión de estados no era un problema de tamaño, sino de expresividad: la FSM plana carece de las abstracciones para factorizar lo común y aislar lo independiente, y sin ellas cualquier sistema real la desborda. Cuando interiorizas que un estado es un árbol de estados activos y no un punto, dejas de contar estados y empiezas a componerlos. Ese cambio de mentalidad —de escalar a configuración, de lista a árbol— es lo que separa el modelado ingenuo de la ingeniería seria del comportamiento, y es la base sobre la que se apoyan las cuatro lecciones siguientes de este nivel.

⚔️ Mide la explosión
  1. Modela un reproductor con reproduciendo, pausado y detenido, y añade un evento APAGAR válido desde cualquier estado con una FSM plana: cuenta las aristas.
  2. Refactoriza envolviendo los tres en un superestado encendido y declara APAGAR una sola vez; compara el número de aristas.
  3. Añade tres conmutadores binarios independientes a una UI y calcula cuántos estados exige una FSM plana; luego cuántos estados de statechart si cada conmutador es una región ortogonal.
  4. Escribe la fórmula de Harel de memoria y asocia cada término con la patología que cura.
  5. Abre Stately Studio, pega tu statechart del semáforo y simula la transición AVERIA desde cada fase para comprobar que la única arista del superestado las cubre todas.
  6. Argumenta en un párrafo por qué la explosión de estados es un problema de expresividad y no de tamaño.