Yesterday, I wrote about the biggest difficulty of state machines - state explosions. When David Harel published his paper Statecharts: A visual formalism for complex systems in 1987, he did not only fix the problem of state explosions, he essentially created state machines on steroids. Today, we'll cover how to define such statecharts.
Limited by the fact that our state architecture in state machines needed to follow a sequential structure, we had to duplicate a lot of transitions.
Statecharts do not have this limitation as they allow us to define parallel state regions and nested states.
interface VideoChatStateSchema {
states: {
audio: {
states: {
enabled: {};
disabled: {};
};
};
video: {
states: {
enabled: {};
disabled: {};
};
};
};
}
As seen in the TypeScript definition above, enabled/disabled are child state nodes
of video and audio. The parent nodes are orthogonal to each other which means both states are fully independent and don't even know about the other's existence. Naturally, to let XState know that the video and audio states are not a sequence but exist at the same time, we set the type
property in our machine definition to parallel
.
type VideoChatEvent =
| { type: 'ENABLE_AUDIO'}
| { type: 'DISABLE_AUDIO'}
| { type: 'ENABLE_VIDEO'}
| { type: 'DISABLE_VIDEO'};
const videoChatMachine = Machine<any, VideoChatStateSchema, VideoChatEvent>({
id: 'videoChat',
type: 'parallel',
states: {
audio: {
initial: 'disabled',
states: {
disabled: {
on: {
ENABLE_AUDIO: 'enabled'
}
},
enabled: {
on: {
DISABLE_AUDIO: 'disabled'
}
},
}
},
video: {
initial: 'disabled',
states: {
disabled: {
on: {
ENABLE_VIDEO: 'enabled'
}
},
enabled: {
on: {
DISABLE_VIDEO: 'disabled'
}
},
}
},
}
});
If you've read the posts from the previous days, you'll see that our XState definition barely changed. XState allows us to define state machines and statecharts with the same API. Conceptually, we should think about each parallel state node as a tiny state machine. Both of them need an initial state and have states + events that drive their particular state changes.
Above all, the most compelling argument for statecharts can be seen by looking at the graph from yesterday's implementation and the one from today. A world of difference.
Yesterday using pure state machines
Today using a statechart with parallel states
As our video chat requirements grow and we'd like to add screen sharing, we can simply add another parallel node to our statechart without worrying about state explosions.
If you are curious about the original paper from David I mentioned at the very beginning, you can find the pdf here.
About this series
Throughout the first 24 days of December, I'll publish a small blog post each day teaching you about the ins and outs of state machines and statecharts.
The first couple of days will be spent on the fundamentals before we'll progress to more advanced concepts.
Top comments (0)