Visual Basic

Dealing with Complexity

Building a mechanism like the one above is a good way to get a feel for the architectural design of your GUI. However, it's tempting to channel design resources into such details as how many forms you're going to use and what fields you need on each form and to let seemingly peripheral issues such as navigation and modality take a back seat. You can get away with this for smaller projects because it's possible to have an intuitive grasp of the interactions among a small number of forms. In general, however, ignoring questions such as how each form is invoked and which forms can be on the screen at the same time can lead to disaster.

By allowing multiple forms to be active at the same time, you dramatically increase the complexity of the underlying code because manipulating data on one form can affect other forms that are also being displayed. For even a modest-size application, the view ahead is daunting, since you have to examine every possible combination of forms that can be active at the same time and then consider the effects of all possible inputs for each combination. Any modes you've designed will help to limit form interactions, but doing the analysis ad hoc invites unplanned side effects-inevitably, you'll fail to plan for some situations.

Figure 13-3 shows an application that manages a cascade of forms that lead the user down through successive layers of data. If you use modeless forms, editing the data on form A invalidates the data on forms B and C. You also need to consider what happens if the user closes form A before closing forms B and C. Clearly, you need to decide whether these actions have any useful meaning in the application; if they don't, you can simply prevent them. If they do, you want to know up front because they can affect the implementation. (You don't want the forms to share data, for example.)

You might be feeling skeptical about the complexities of a three-form application. Some simple arithmetic can be illuminating. There are seven possible ways in which combinations of the modeless forms A, B, and C can be active. (Let's call these combinations "states.") Now let's say the user presses the Cancel button on form A. Let's also assume you've decided never to leave forms B and C up when the user closes form A. It's clear that the event handler for form A's Cancel Click can't simply unload the form-it must look around to see what other forms are up and maybe close those forms too.

Figure 13-3 A cascade of forms-but modal or modeless?

If you add another form to the application, the number of states goes up to 15. Even discarding the states that don't contain form A, you are left with 8 different situations to consider in each Cancel Click event handler. In fact, the number of states (combinations of forms) is 2n -1, where n is the number of forms. This number increases geometrically as you add forms, which means the number of states gets out of hand very quickly. There is a set of events for which you must consider all of these states, and the handlers for such events need to be aware of the environment and adjust their behavior accordingly.

It should be clear by now that you need a formal way to define the interactions between forms. The model we'll use to track form interactions is the finite state machine (FSM). The principles of an FSM, which is essentially an abstract representation of a set of states and events, are described in the following section.