Have you ever noticed the warnings on medication about not operating heavy machinery? How many industrial accidents are there because an equipment operator took a healthy swig of Nyquil before getting to work? Apart from the warning sticker, there’s no real prevention of this condition. If you stretch this metaphor to software development, you’d have a pretty good understanding of why errors get to production.
On a Recent React Wednesdays episode, we interviewed David Khourshid, creator of the XState library, on State Machines, and how to use them to write better code. Christian Pillsbury from the Digital Primates team joined the broadcast. He’s been a user and advocate of XState for a long time. He initially submitted articles about XState to our Enterprise React Newsletter, where I learned about XState. Christian helped bring some color commentary to the broadcast as he’d used XState the most out of us.
Much of user interface programming and even programming, in general, is creating and maintaining sets of application state. A state is a specified condition made up of application properties, data, history, and potential next steps. An application can be in one of a set of states. Consider the two states UnMedicated and Medicated. It’s not possible to be in both states at the same time. Either the equipment operator has taken medication, or they have not.
Some states might even be unintended or illegal. Imagine our Heavy Equipment program. If our HeavyEquipmentOperator accidentally gets the IngestedNyquil property set to true, we could have a fatal error condition in the real use of the word. Naturally, the software developer would write lots of if statements to prevent this from occurring. Designing the appropriate guardrails around state creation and attribute combination comprise a fair amount of the necessary work in application development. The Write Custom Code approach leaves state definition, consistency, illegal state prevention, and other constructs in the software developer’s hands. Many of the production errors that exist in applications are traceable to invalid state conditions. There is a better way.
XState is a library for creating, interpreting, and executing finite state machines and statecharts and managing invocations as actors. Let’s unpack the words and get an understanding of how they relate to application development.
- State Machines are a concept that states an application can be in one (and only one) of a set of valid states at a given time. Think back to our Unauthenticated and Authenticated example.
- Statecharts are extended state machines for modeling states and are used to extract behavior from a component. Statecharts have helpful features like Guarded transitions, Actions, and History.
- Actors refer to the Actor model whereby messages trigger state changes, not direct invocation.
Taken together, we have a method for defining the realm of valid application states, built-in features to help maintain and transition between valid application states without having to put behavior code in components.
Nothing, at face value. IF statements are an essential logical control structure, and you should keep using them, but don’t OVER use them. Using IF statements to manage state leads to disarray in the state conditions and the guardrails to prevent invalidity. If the state checks and controls are sprinkled all over your application, you will have a harder time ensuring the right conditions are in place. Further, more time is spent reading code in the software lifecycle than writing code. That means it is the most efficient and best practice to write software that can be more easily read and reasoned. The true nature of software is complicated by having too many IF statements to read and mentally track. It would be better architecture to have state elements centralized. XState provides a centralized repository for state, state conditions, and transitional processing.
How To Implement a State Machine with XState
Passing Messages Is Bad in High School, Good in Programming
Many software developers, especially in early career stages, write software the way they think. Much of transitioning to Senior Developer involves retraining out these intuitive but suboptimal behaviors. XState, State Machines, and the Actor model, advocate passing messages as the method to trigger state changes. The contrast to message passing is direct invocation. When something invoked directly in software development, the software developer must reference the object or property to manipulate, then perform the manipulation. Most people think in direct invocation. For example, when you want to open a door, you grab the door handle, then pull or push the door the appropriate amount.
An alternative to direct invocation is broadcasting and receiving messages. The software developer can decouple the high-level representation of the behavior’s needed action by encapsulating out behaviors into messages. Rather than grabbing the door handle, the door user would broadcast a message like OpenSesame, and the door would open. This indirection prevents the door user from having to be concerned with the implementation of the door.
How to Diagnose and Follow State and Transitions Visually
I’m a sucker for a good visual tool. David showed us the XState Visualizer, a tool for visually representing the XState configuration. When a developer inserts State config into the visualizer, the software developer can examine and interact with the state, potential transitions, and outcomes in a visual way. Software developers can use this tool to get a high level of understanding of their configuration. Additionally, software developers can use the visualizer to walk through the application states with non-technical users to validate the application will respond and transition appropriately.
We were excited to hear David has new visual tools in the works. He’s building out a new state visualizer with more features. He is also working on a graphical tool where users can build out state machines with drag and drop tools. On the Statecharts website, he lists the key features planned in the Creator tool:
- Create statecharts with a visual drag-and-drop interface
- Import & export statecharts directly into real projects
- Simulate statecharts visually
- Share statecharts with collaborative tools
- Automatically analyze logic modeling problems
We’ll be watching this project with interest as the ability to use a visual tool to create and examine state and state flow promises to be a big productivity enhancer.
When Should You Use XState and When Is It Overkill?
Around 34:17 of the XState React Wednesday episode, I asked David to discuss the point at which a reasonable developer should move away from IF statements and into a state machine architecture. He replied when there are more than two states. I understood what he meant because if there are only two states, the logic becomes a mere toggle. On/Off. Up/Down. Left/Right. If there are more than two states, there will be potential ambiguity that the developer will need to handle. There also will be room for mistakes or unintended consequences, and the State Machine architecture will reduce the opportunity for these issues to manifest. He went on to show some code-based examples of how this could happen and what to do about it. I’ll leave it to the reader to watch David’s clear explanation in his own words.
Summary and Helpful Links