 |
Easy Wizard State Machine
To understand how the Easy Wizard is different, first let us
recap how the classic finite state machine (FSM) works. Most web flow
implementations use a variation of a
Mealy machine, in which
the resulting state depends on current state and input command.
Classic finite state machine approach

Picture 1 |
Lets us design a simple New User Signup flow. The
flow will consist of three main states (Name, Details and Confirm) and of
two helper states (Start and Finish). In each state the machine can receive
different commands (or events, or just inputs), and react on them by
choosing a transition to the next state. The process of changing states is represented on the
left picture with a directed graph. This graph is quite simple, it has only
one starting point, one ending point, and it does not have cycles.
We begin at the Start state. If "get name" command is received, we move
to Name state, where user's name should be collected. Then, we can either
enter user's detailed information or skip it. The choice depends on the
command. If the "get details" command is received in the Name state, then
the FSM moves to Details state. If "comfirm" command is received, then FSM
moves directly to Confirm state. If "confirm" command is received in the
Details state, then FSM moves to Confirm state. And the last transition, is
when "done" command is received in the Confirm state, and FSM moves to the
terminating Finish state.
Seems easy and simple. We can write the state transition process in a more
formal way, using transition table. Actually, directed graph and
transition table are two different ways of representing a FSM. Columns
contain commands, rows contain states. To decide which transition to take,
find a row with current state and then intersect it with the command. The
resulting cell contains the transition and resulting state.
|
| |
get name |
get details |
confirm |
done |
| start (S) |
show name page, N |
|
|
|
| name (N) |
|
show details page, D |
show confirm page, C |
|
| details (D) |
|
|
show confirm page, C |
|
| confirm (C) |
|
|
|
completed, F |
| finish (F) |
|
|
|
|
|
Finite state machine does not play along with other stateful entities

Pictire 2
|
In the example above Classic FSM does not interact with other components which
can hold state. Nor does it synchronize itself with these components.
When
developing state machine engine to control different stages of a user
interface, it is important to remember, that user interface (UI) must not only skip from
one page to another because FSM instructs to do so, but also to properly update underlying domain model and
to stay in sync with it.
Below is the modified state transition table, which involves an external
entity: application domain model. When FSM changes its state,
the domain model is updated as well.
- What if domain model update fails? Which state FSM should choose next?
- What if model was updated, but it does not correspond to new FSM state?
- Should FSM depend on domain model or vice versa?
FSM must detect failure in the domain model and decide, whether it should
move to the next state, or to stay at the same state, or to move to some
error state.
The problem is that domain model also has states. These states are
changed when input data is applied to the model. If FSM defines the states
of the UI, and domain model defines the states of the backend, these states
must be kept in sync to ensure, that:
- the model contains data, which properly corresponds to the UI page;
- and vice versa, a certain page can display certain model data.
FSM states and domain model states must be synchronized. This
issue is usually not addressed by most web flow solutions.
|
| |
get name |
get details |
confirm |
done |
| start (S) |
show name page, N |
|
|
|
| name (N) |
|
store name, show details page, D |
store name, show confirm page, C |
|
| details (D) |
|
|
store details, show confirm page, C |
|
| confirm (C) |
|
|
|
persist updated data, F |
| finish (F) |
|
|
|
|
|
Easy Wizard: state machine and domain model combined
|

Picture 3 |
Easy Wizard is designed as a specific type of FSM, and is better represented with
directed graph, than with transition table.
Easy Wizard FSM does not allow cycles, that is, it is represented with directed
acyclic graph (DAG)
- Each node of a graph represents a state, each edge represents
a transition.
- Every wizard state is an object, referring to domain model properties.
- Every transition is an object, which can validate itself.
- Input data, which does not belong to current state, can be easily detected
and rejected.
|
Easy Wizard also uses input commands to calculate the resulting state, so one
might say that it is the same Mealy FSM that was discussed above. But Easy
Wizard is slightly different: it is tightly integrated with application
domain model, thus synchronizing UI states and model states.
Instead of calculating the transition based on current state and command,
Easy Wizard iterates over all possible transitions for current state and
validates them. Transitions usually verify the standing of application domain
model, and decide, what state FSM should move next. If a transition considers
itself valid, FSM state is changed to the output state for this transition. As simple as it gets.
|

Picture 4: First step, Identification |
Tight integration of Easy Wizard FSM and
domain model allows to update only data, corresponding to current state.
Take a look at the picture 4. The brown frame around the first
wizard state and domain data indicates that wizard resides in the first
state, Name. This state refers to domain model data, relevant to it, which
is name, repeated name and a password of a new user.
Each node refers only to the data that it can modify.
Note, that web browser displays the page, relevant to the same state,
which shows input form. When browser submits data to the server, server verifies the state of the
wizard. After that it can easily locate domain data that corresponds to that
state.
|
|
|
|
|

Picture 5: Second step, Details |
On picture 5 you can see, that New User Signup
Wizard moved to the second state. This state refers to favorite book and
movie properties, which can be used later for password recovery purposes.
In this case browser is still synchronized with the wizard, and displays
"Details" page. When this page is submitted, wizard receives favorite book
and movie information from the browser, and updates the model. |
|
|
|
|

Pictire 6: Second step,
browser shows stale page |
Picture 6 shows the situation which may happen
with Easy Wizard, if a browser does not honor cache control response
headers, such as Opera. Easy Wizard always tries to keep web pages in sync
with the server state, so if a user click browser's Back button, browser
would always reload a page, corresponding to current server state. This does
not work well with Opera, which caches everything. So, if a user clicks Back
button in Opera, he would see a stale page.
In case shown on picture 6, this stale page shows information,
corresponding to first state, Name, while wizard now in the second state,
Details. What would happen if the user submits name and password from the
stale page?
The wizard would validate current state and submitted data, and would
reject submitted name and password because they do not correspond to the
current state. Also, it would generate error message, notifying the user,
that the browser went out of sync with the wizard, and that this particular
browser does not support Back button correctly. |
What if domain model cannot be updated? The answer is simple: Easy Wizard
does not move from the current state, until there is at least one valid outgoing
transition. Transitions can validate any conditions they need. Usually
transitions check the validity of input data and the validity of domain model.
So, if the domain model cannot be updated (that is, cannot change its state), then
flow engine cannot move forward either. This is how flow engine is synchronized
with domain model.
|