Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

JVM Languages

State Machines & User Interfaces


Jan03: Programmer's Toolchest

Brían is a programmer living in Ireland. He can be contacted at [email protected].


When designing software, you need to think of the application as two objects—the model and the user interface (UI). The model represents the problem to be solved—it has no UI and no concept of how users might interact with it. It is accessed through a set of APIs that could be anything from mainframe programs hidden behind messaging middleware to web services. The UI, on the other hand, lets users exploit the model to perform necessary tasks. The UI depends upon the model and is a client to the model's services.

If you apply this approach to your development efforts, you find yourself with two projects that, while interdependent, have different requirements and priorities—one project is concerned with producing an accurate model of the problem and providing services for the UI, while the other is focused on producing a UI appropriate for your users.

In this article, I present a means of designing the UI using a framework that includes your design as an integral part of the deployment. This forces the implementation to behave as intended. In designing the UI, I am concerned only with behavior. The UI's appearance and the technology that deploys it are less important than stating how it should behave and ensuring it behaves as you intend.

Statecharts

To define the behavior, I treat the UI as a finite state machine and draw an appropriate UML statechart to represent it. The interface is a single object that responds to events from users by sending messages to the model and displaying some or all of the results of these messages to users. As users perform tasks, various events come in and out of scope.

Figure 1 is a statechart for a simple e-mail client. Users can log on, read messages, compose/send new messages, and reply to existing messages. The chart describes the behavior of the UI while saying nothing at all about how it is rendered. It is a simple, complete, and well-defined behavioral description.

Having a design is all well and good, but there's still the issue of creating a good implementation. This is where the JStateMachine framework comes in.

JStateMachine is a freely available software project I built to control a UI at run time by keeping it within the bounds of a statechart. This state machine lets you produce your own MVC-like View and Controller classes, and link them through a representation of statecharts. JStateMachine handles transactional conversations, default states, and application exceptions. The initial implementation of the project is in Java and can control UIs delivered using the Swing or Servlet APIs. It is based on a design completed by David Anderson, Marcus O'Connell, and myself in 1999 (http://www.uidesign.net/1999/papers/webmvc_part1.html). The complete source code and related files for JStateMachine are available electronically from DDJ (see "Resource Center," page 5), and at http://sourceforge.net/projects/jstatemachine/ and http://www.jstatemachine.org/.

The key to JStateMachine's control is a representation of the statechart that it keeps in memory while the application is running. Figure 2 is a class diagram with the relevant interfaces. The IApplication interface provides references to the application's root and start states. IState objects are composed into the tree of states on your chart. Each IState can have IEvents—the events that users can fire when the UI is in that state. Events are not explicitly mentioned on a statechart diagram. In my representation, they are defined as being the composition of all transitions with the same event name and the same source state. Therefore, each IEvent must have at least one IStateTransition. State transitions reference their result states, each transition leading to exactly one state. To complete the basic picture, transitions can lead to history (H) or deep history (H*) pseudostates, and states can contain default events. I have not addressed the issue of concurrency, having made the assumption that the UI is in exactly one state at any moment. Adding concurrency to the JStateMachine framework would add complexity without adding much value.

These interfaces are intended to represent any chart. For them to control your UI, you must provide code that implements your required behavior and renders the UI as you want it. You provide this code as delegates to be loaded by the IState and IEvent objects.

The UI is rendered by IView objects and loaded by the states. Whenever the UI rests in a state, the IView delegate for that state is called upon to update the display. Each view should be the simplest possible class that will update the display. The views have no behavioral or decision-making responsibilities.

Behavior is provided by IController objects. Whenever an event arrives from the UI, the IController delegate for that event is called upon first to determine which state transition to follow, and then to perform any side effects (updating the model) appropriate for that transition.

UI Classes and Instances

While the UI is a single object, JStateMachine is capable of handling many instances of the UI object at once. Each UI instance is differentiated within the framework by having a unique IUserSession object. The user session is responsible for keeping a history of the user's actions so that the history and deep history pseudostates can be properly handled. It also keeps details such as the user's Locale and authorizations to permit framework localization and access control functions. JStateMachine can also handle many different charts at once, in effect providing support for different classes of UI.

Event Processing

When an event arrives from the UI, JStateMachine processes it via a series of steps:

1. Locate the source state and event on the chart.

2. Ensure users have permission to fire that event, throwing an exception if not.

3. Load the IController delegate for the event and ask it for the correct result transition.

4. Ask the controller to perform any required side effects.

5. Follow that transition, including computing the history or deep history if required.

6. Ensure users have permission to enter the result state.

7. If there is a default event, follow it. Keep processing default events until you end in a state with none, always ensuring permissions are not broken.

8. Load the IView delegate for the result state and ask it to update the display.

Writing the UI

To deploy a JStateMachine-based UI, you must define the behavior of the UI as a statechart. Start by building a list of the tasks that users must be able to perform, noting these as events. Group the events in terms of when they are available to users; in Figure 1, users can only send a message if they are currently composing one. This gives you an idea of the states you need. Examine the states in terms of the data they will display or gather; these are your views. You may find that the statechart can be refactored to reduce the number of views or controllers you require. Keep the statechart as a working document; don't be afraid to change it as the application develops.

From the chart, you can read the number of required views and controllers. Each state the UI can rest in requires a view. Some states may be able to share the same view if they display and gather similar sets of information. Each event with more than one transition or with side effects requires a controller. Trivial events, with exactly one result and no side effects, can be handled by the same controller class. These numbers (read directly from your designs) help estimate the amount of work required to complete the implementation.

Next, convert the chart into the XML format used by the JStateMachine. Once you have this XML file written, you can begin deploying your UI. Remember now that your chart includes a tree of states. You can deploy and test small parts of the UI by creating XML files that contain only one branch of the tree. JStateMachine contains a number of added extras that are intended to make deploying your UI easier or to better define its behavior.

AutoViews

One of these extras is AutoView. Recall that JStateMachine retains a copy of the statechart in memory. This includes all the possible events and transitions from each state. All of this information is available to the IView class that updates the display. I have written two classes (one each for the Swing and Servlet APIs) that use this information to build a view on the fly. The AutoView class interrogates the current state for the list of all possible events, then displays a form on screen for each event. For reference, it displays the possible transitions from each event beneath the form. It also displays information that has been passed to it by the controllers or user session.

To use AutoView, you need to provide a list of all the parameters required by each event. You can provide these as properties of the event within the XML file. AutoView displays an input box on screen for each parameter and includes the contents in the event it fires.

AutoView is a way to produce a prototype UI directly from the design. You can demonstrate the flow of the UI and test controllers without writing any view code. You can gradually replace AutoView in your test deployment with the finished view classes, maintaining a complete working prototype UI from very early in development.

Exception Handling

One aspect of UI behavior neglected far too often is exception handling. JStateMachine brings exception handling into the design by letting you specify states within your chart as exception states. When an exception is thrown, either by the framework or by your controller or view classes, the framework catches the exception and finds a state within the chart that can handle it. This means that, even when an exception is thrown, your UI behaves in a predictable and controllable manner.

Different exception states can be defined to handle different exceptions, and each state can inherit the exception states of its parent or define exception states of its own.

Access Control

JStateMachine includes access control features that let you restrict access to both states and events. Each user session can contain a set of authorization tokens (strings that indicate the user has certain authorizations). Each state and event can contain sets of sufficient, required, and forbidden tokens. Users can enter a state or fire an event if, and only if, the user's session contains any sufficient or all required tokens and no forbidden tokens. The tokens for each state and event are defined in the statechart XML file, making access control an integral part of the UI design.

Conclusion

User interfaces can benefit greatly from the behavioral definition given by finite state machine concepts and statechart diagram notation. This behavioral definition is largely independent of the appearance or deployment technology used.

The JStateMachine framework lets you make best use of such a definition by referring to the statechart while the UI is running and ensuring the chart is followed at all times. With the definition available at run time, it is easy to include extras such as access control, exception handling, and rapid prototyping.

DDJ


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.