Photo by Thomas M. Evans on Unsplash
Giggle With Deterministic Finite State
X-State: A better way to manage state.
Recently, at our company, candidates were given a seemingly trivial but exciting challenge related to state management.
The Challenge
A light bulb can only be in 1 of 3 finite states at any time. Once broken*, it can neither be* lit nor unlit*. Write a Vue component that accurately represents such a light bulb.*
Attempt 1: Use of conditional statements (booleans)
If You Have a Hammer, Everything is a Nail. it’s very tempting to rush into such an exercise with conditional statements shouting "hoo·ray, I know my booleans." That's exactly what Joanne did. She came out of that interview room very optimistic. And this is what her code looked like.
<div class="container mx-auto column items-center">
<q-btn v-if="broken" fab color="dark" icon="fas fa-lightbulb"/>
<div v-else>
<q-btn v-if="!isLit" fab color="dark" icon="fas fa-lightbulb"/>
<q-btn v-else fab color="orange" icon="fas fa-lightbulb" />
</div>
<div class="row justify-center q-gutter-md">
<q-radio v-model="isLit" :val="true" label="Lit" />
<q-radio v-model="isLit" :val="false" label="Unlit" />
<q-radio v-model="broken" :val="true" label="Broken" />
</div>
</div>
</template>
<script setup>
import { ref, watch } from "vue";
let broken = ref(false);
let isLit = ref(false);
watch(
// If broken its definitely unlit
() => broken.value,
(newVal) => {
if (newVal) {
isLit.value = false;
}
}
);
watch(
// If it's lit it can not be broken
() => isLit.value,
(newVal) => {
if (newVal) {
broken.value = false;
}
}
);
</script>
Wow! This is a handful of booleans. But the challenge is, when *broken**, Joanne's bulb is still unlit and can still be lit.
Attempt 2: Enumerating the state
Andrew on the other hand was a little bit careful, he understood that the bulb in question was supposed to be in exactly 1 of 3 (a finite number of) states at any given time and decided that the variable in each instance was the state of the bulb. For starters, the state of a component is the internal private data (usually an object) that holds information representing the behavior of that component at that instance that may change over the lifetime of the component. Anyway, Andrew's code looked like this:
<template>
<div class="container mx-auto column items-center">
<q-btn
fab
color="dark"
icon="fas fa-lightbulb"
v-if="state === 'broken'"
/>
<div v-else>
<q-btn
fab
color="dark"
icon="fas fa-lightbulb"
v-if="state === 'unlit'"
/>
<q-btn
fab
color="orange"
icon="fas fa-lightbulb"
v-if="state === 'lit'"
/>
</div>
<div class="row justify-center q-gutter-md">
<q-radio v-model="state" val="lit" label="Lit" />
<q-radio v-model="state" val="unlit" label="Unlit" />
<q-radio v-model="state" val="broken" label="Broken" />
</div>
</div>
</template>
<script setup>
import { ref } from "vue";
let state = ref("unlit");
</script>
Surely Andrews' approach was more meticulous. At any instance, his bulb will either be lit, unlit or broken. The challenge is, when broken, it can still be lit or unlit at a later point in time.
Attempt 3: Use of state machines (x-state)
Without further adieu, let me tell you who won. Diane; knew precisely what the right tool for the job was. X-State! First, she used X-State's Visualizer to design a lightbulb state machine as shown below:
The tool automatically generated the javascript code below which represents the lightbulb finite state machine
import { createMachine } from "xstate";
export default createMachine({
predictableActionArguments: true,
initial: "unlit",
states: {
unlit: {
on: {
BREAK: {
target: "broken",
},
TOGGLE: {
target: "lit",
},
},
},
broken: {
type: "final",
},
lit: {
on: {
BREAK: {
target: "broken",
},
TOGGLE: {
target: "unlit",
},
},
},
},
description: "A light bulb machine",
id: "lightBulb",
});
She then used this lightBulb x-state machine in her component using the @xstate/vue library as follows:
At this point, you all must be saying. Wow! Dianne is brilliant. Yes, you're right. She's amazingly Brilliant. In fact, before this interview, she had enrolled in JSchool. That's why she could precisely make informed choices for the tool to use here.
JSchool is our mentorship program that aims at practically equipping future developers with intuitive skills for the ever-growing software development market. Learn more.