Often, an application runs in an environment of asynchronous, unordered and unpredictable events and the software needs to be robust enough to work seamlessly under these conditions. In this article, targeted at software designers and developers, we explore the benefits of using state machines to make robust software and the open source options available for this purpose.
Almost every software becomes complex as it evolves over a period of time, and can therefore suffer from frequent non-functional problems. These problems are linked to its maintainability, code manageability, extensibility, modifiability, determinism, etc. However, a good plan and design carved out at the initial stages could help developers enjoy the smoothness of the development process, as the software matures over a period of time.
The use of state machines is one of the oldest and best known techniques for modelling the behaviour of a system. And its adoption dates way back to the study of physical matter. As a reference, water (H20) can exist in three different states – solid, liquid and gaseous — and in each state it exhibits a specific behaviour; also, there are defined events and actions that lead to water, steam or ice transitioning through its different states. Software designers have been using this example to model and partition systems into well-defined states, with specific actions and events that define how these systems move through these states.
In this article, we look at the benefits of using state machines for modelling software along with some examples, and see what the open source world has to offer in this space.
Benefits of state machines
Some of the benefits of adopting state machines are listed below.
- A complex problem can be broken down into smaller and manageable pieces called states, with each state being delegated a narrowly defined task. Modelling the system with a state machine ensures a self-documenting and compact representation of the software that automatically satisfies non-functional demands like manageability, extensibility, modifiability and determinism. It might seem like a lot of work in the beginning but as the system grows, this technique helps to dramatically reduce the overall complexity. Enabling a state machine for code that is already developed and has evolved quite a bit can be painful. So, the one-time investment in state machines for any software module right at the beginning of the software development life cycle (SDLC) is always good.
- Once a state machine is in place, the developer can focus on tuning the behaviour of the system to meet functionality requirements and enhance business value, rather than spending time on enforcing the rules of its behaviour and other crucial non-functional attributes like code maintainability, flexibility, etc.
- When a system has its responsibilities well delegated at different states, it also ensures predictability and determinism in the system, thereby making it developer-friendly when troubleshooting.
- State machines with well-defined states and events can keep in control the growth of conditional logic as well as ad-hoc code branching out with scattered Boolean flags in the software, and thereby control the overall cyclomatic complexity.
Digressing a bit into the history of software and technology, good designs and implementations backed by state machines have always proved excellent in various verticals. These include commonly used elements in our daily life like a DBMS transaction; TCP, BGP and many other networking protocols; system processes and threads, gaming software development, etc. All these software structures have a state machine in their DNA. Even everyday occurrences like traffic lights, vending machines and other digital electronic systems could all be quickly modelled using Mealy and Moore styled finite state machines.
With all this said, let us now explore some options that the open source world has to offer developers and designers. You could enable a state machine for your code, even if it’s proprietary, with the open source state machine frameworks given below, and reap the benefits of the privileges we discussed earlier.
The StateFulJ framework
StateFulJ is an open source, lightweight, Java based finite state machine (FSM) framework that could help you embed a state machine into your application. It is a useful aid when your application has to deal with many synchronous and asynchronous events and requests, while handling concurrency in a reliable way. The user has to define the state machine model (states, events and transitions) using Java annotations, and the framework auto generates the necessary FSM infrastructure for the application. You can then define your state’s actions and various transitions using the auto generated code and StatefulJ APIs.
The spring state machine
This is an open source framework released under the Apache 2.0 licence for developers to use state machines in spring applications. It uses the builder design pattern for configuration and instantiation of states. Spring state machines provide some useful features like storing the state machine configurations in a persistent storage, UML Eclipse Papyrus modelling, Zookeeper based distributed state machine, etc.