DrakonHub logo

An interactive state machine demo

An online interactive demo of automata-based programming with DRAKON

by Stepan Mitkin
updated on 18 August 2018

Go to the demo

The source code for this demo has been generated from DRAKON diagrams.

Browse the source code: https://github.com/stepan-mitkin/lift-demo

DRAKON Editor (needed to open the .drn files):
http://drakon-editor.sourceforge.net/editor.html
https://github.com/stepan-mitkin/drakon_editor

The unknown state machines

Late in 2017, I surveyed my fellow developers. The survey had only two questions: do you know what state machines are and do you use them. The staggering 95% had no idea on the subject. One of the developers said: "I know what state machines are but I don't need to worry about them because I develop software, not hardware." It's like saying "I write C#, so I don't need the internet. It's the Java programmers who surf the internet."

State machines are not limited to electronics. State machines are a universal tool for modeling behavior. Every piece of software that runs longer than a fraction of a second has behavior. Therefore, almost all programs could benefit from state machines.

The demo

Press the buttons below to play with the lift.

A hierarchy of machines

This demo uses several state machines to control a virtual lift. Having more than one machine is a typical situation. Most practical applications are too complex to be modeled with just one automaton. The state machines in the demo form a tree-like structure, a hierarchy. It is essential to have a hierarchy. An unrestricted net of machines, where all can connect to all, is hard to test and support.

In an event-driven environment, a master machine talks to a slave machine by calling methods, as if the slave machine was a regular class. The slave machine, however, can only communicate with its master by sending messages through the event loop.

The requirement to arrange machines in a tree is sometimes too strict. For practical purposes, it is okay to add some additional links between the machines. The important thing is that the graph of machines must not have cycles. A machine that sits lower in the graph must never directly call methods of the machine above it.

DRAKON makes automata-based programming practical

Even though state machines are a solid concept, it is hard to use them.

The mainstream programming languages do not have first-class support for state machines. If a programmer wants to make a machine, he has to follow some informal patterns in code. Such hand-made machines are better than just classes, but they are not easy to comprehend.

Visualization might help. But how to draw a state machine? The traditional state machine diagrams are confusing and inconsistent. They do not give quick answers to questions like "which signals does this machine accept in this specific state?" or "which states can the machine switch to from this state?"

Another problem is that the programmer often needs to manually write part of the machine in a separate file.

These difficulties seem to be the reason why the software industry does not widely accept state machines.

The DRAKON visual language could be a solution to these problems. A state machine can be represented with a DRAKON chart of type "silhouette". Silhouette combines state machines with decision trees. A silhouette diagram shows the states, the transitions, and the machine's decision logic in the same visual scene. As a result, working with machines becomes easier.

Another benefit of using DRAKON for state machines is that DRAKON is an ergonomically optimized visual language. DRAKON diagrams are clean, predictable and consistent.

How to build a state machine with DRAKON

This demo shows a way to represent state machines with DRAKON silhouette diagrams. This is how to turn a DRAKON chart into a state machine:

This way, DRAKON Editor generates one state machine class from one silhouette diagram.

The machines from the demo

The Door controls the inner and outer lift doors as one. There are one internal door and several external doors, one per floor. motor.connect() method connects the inner door to one of the outer doors.

The Door translates the logical "opened" and "closed" positions into coordinates and sends them to the motor.

The Door can have the following states: Closed, Opening, Open, and Closing.

When the door is in the Closed state, it accepts only the "open" message. Having gotten this message, the door sends a command to the motor to open the physical door and enters the Opening state. While in the Opening state, it is possible to send the "close" message to the Door and it will start closing. When the motor has fully opened the physical door, it sends the "done" message to the Door. The Door reports that it is now officially open.

When the Door is in the Open state, it accepts only the "close" message. The Closing state is similar to Opening. While Closing, the Door is waiting for the "done" message from the motor to switch to the Closed state.

DRAKON chart for Door state machine

The Cabin translates floor numbers into coordinates and controls the motor that moves the lift cabin.

A cabin can be either moving or standing still. These two possibilities make up the states of the Cabin machine: Moving and Still.

Having gotten the "move" command, the Cabin sets the new target for the motor. "move" is accepted in both Moving and Still states. While the cabin is moving, it waits for the "done" message from the motor. "done" means the motor has transferred the cabin to the target floor.

DRAKON chart for Cabin state machine

The job of the Scheduler is to choose the next floor. The Scheduler makes this choice based on three pieces of information: which buttons are pressed, the direction of movement—up or down, and the current floor.

The direction of movement is stored as the state: Up or Down. The current floor comes to the Scheduler in the "chooseNext" message. The knowledge about pressed buttons is kept in the slave machine "buttons". Since "buttons" is a slave machine, the Cabin can call the methods of the "buttons" machine directly.

If the lift is moving up towards the fourth floor and button 3 inside the cabin is pressed, the Scheduler will decide that the lift should stop on the third floor first. But if button 3 inside the cabin is not pressed and the "Down" button on the third floor is pressed instead, the lift should skip the third floor and proceed to the fourth.

DRAKON chart for Scheduler state machine

LiftMain is the king of the hierarchy in this example. LiftMain makes the decisions what to do next based on user input and events from the lift machinery.

LiftMain is effectively a class because it has only one state: Ready.

Here are the rules that LiftMain implements:

DRAKON chart for LiftMain state machine

What exactly is awesome here?

DRAKON shows both the state machine and the decision trees for transition logic on the same diagram.

Other types of state machine diagrams are not as useful as DRAKON in representing transition logic. On a UML statechart, for example, it is possible to specify which combination of conditions triggers a specific state transition of the machine. However, these combinations of conditions are encoded in textual logical formulas like this one: X1 and X2 and not X3 or X4. Textual logical formulas are hard to read. DRAKON offers visual decision trees which are a significant improvement over textual formulas. Instead of deciphering the formula, the developer follows the paths that go through the decision tree. Decision trees make automata easier to comprehend, and that increases the developer's productivity and reduces the number of errors.

Another benefit is the ability to alternate between questions and actions in a decision tree. Let's take the Scheduler machine as an example. In the handler of the "chooseNext" message in the "Up" state, the Scheduler tries to find if there is a pressed button that wants the lift to go above the current position. The scheduler queries a slave machine to get this information. If no such button is pressed, the scheduler asks the slave if there are any requests to send the lift down from its current position.

This sequence of interactions with the slave machine goes down a continuous path through the decision tree. There is no need for "technical" states that interrupt the flow, like "waiting for a response from the slave machine."

As a result, the machine states in the system are concrete observable modes of operation. A lift cabin can be either moving or standing still. Such concrete states are intuitive; they are easy to find during the design stage.

Testing

Behavior is notoriously difficult to test. The number of possible paths that a typical interactive program has is combinatorial. Besides, the previous actions affect the program's state, and thus its future responses.

State machines drastically reduce the number of combinations that need to be tested. However, to be useful, state machines must be organized in a strict hierarchy. A well-chosen hierarchy removes irrelevant combinations of states.

DRAKON helps create test scenarios. Here is how: for each state we go over each message that the machine accepts in that state. We take each silhouette branch one-by-one and then iterate over the Case icons under the "receive" keyword. For each Case icon, we write short tests. We make one test for every path that starts with that Case icon.

Every test runs one real state machine surrounded by mocks. Since a machine can talk only to its master and immediate slaves, mocking is easy. All tests have a similar structure. First, we build the machine tree and assign input values to the properties of the mocks and the machine under test. Then, we send a message to the machine and finally, check the expected values.

Run the tests now

Conclusion

State machines are an efficient technique for modeling behavior. Since behavior permeates most types of the modern software, state machines can be of great help to many developers.

Unfortunately, software developers rarely use state machines because it is hard to work with them.

DRAKON changes the way how we build and test state machines. Thanks to DRAKON, automata-based programming becomes as practical and affordable as object-oriented programming.

References

  1. F. Wagner, R. Schmuki, T. Wagner, P. Wolstenholme. Modeling Software with Finite State Machines. New York: Auerbach Publications, 2006.
  2. V. Parondzhanov. Friendly algorithms that are understandable to everyone. Moscow: DMK Press, 2016.
  3. Shalyto A.A., Tukkel N.I. SWITCH-Technology: An Automated Approach to Developing Software for Reactive Systems. Programming and Computer Software. 2001. 27(5).
  4. YAKINDU Statechart Tools
  5. S. Mitkin. State Machines in DRAKON Editor.
  6. S. Mitkin. DRAKON, Actors and Message Passing.
  7. S. Mitkin. State Machines in DRAKON-Erlang.
  8. Machina.js http://machina-js.org/.
  9. Boost Meta State Machine.
  10. UniMod. http://unimod.sourceforge.net/
  11. Rosmaro. https://rosmaro.js.org/

Contact: stipan.mitkin@gmail.com