Programs which can be started and stopped by the user frequently need to maintain state between invocations. In the case of TclTutor, this includes such items as current lesson, expertise level, course, and color preferences.
Brent Welch recommends the use of an array for state information. [Welch95]. This technique allows the programmer to keep all of the related variables in the same 'place', and provides a bit of name-space protection from collisions with other packages.
I used this technique, with some extensions, in TclTutor.
The variables which control the state of the tutorial are maintained in a
global array named tutorGlobals
. The tutorial package uses a
separate megaWidget library for the GUI, and state for these widgets
is maintained in an array named widgetGlobals().
To save and restore the state, I use this common construct:
foreach item [array names tutorGlobals] {
puts $stateFile "set tutorGlobals($item) $tutorGlobals($item)"
}
which allows the state to be restored by sourceing the state file.
A library like the megaWidget library also needs to maintain
state. However, putting a SaveState
proc into such a package
is a bad idea.
A library should only contain functions that are required for
its primary purpose. Adding functions that are ancillary to
the primary purpose of a library makes it difficult to use that library
outside the environment where it was developed.
This megaWidget library includes a proc which iterates through the
widgetGlobals
array and builds a list of
set widgetGlobals(item) value
strings. This list is returned to the
calling program which can save, maintain, or modify the state variables
as necessary.
The TclTutor package simply appends this list to the state file, and
sets these variables when the state is restored.