Technical Info

Taking Advantage of an Object-Oriented Application Architecture

In addition to the various facilities provided by IRIS ViewKit, using the IRIS ViewKit library also has a less tangible, but even more valuable affect on application development. The IRIS ViewKit framework encourages an object-oriented approach to application development that results in cleaner architectural design and more easily maintainable code. The IRIS ViewKit architecture is based on the concept of a component. A component is simply a C++ class that encapsulates related elements of the user interface along with the semantics of those elements. Nearly everything in the IRIS ViewKit library is a component, including the application class, VkApp, the top-level window class, VkWindow, and the various menu classes such as the VkSubMenu class. Components can be nested, and a single logical user interface component often consists of collections of smaller user interface components. Programmers are encouraged to develop their own components and to base the architecture of their applications on collections of objects, which may include pre-defined IRIS ViewKit components, custom components, as well as other classes and objects.

The first step when developing an object-oriented application based on the IRIS ViewKit framework is to identify a set of objects that can be used to construct the program. There are many ways to design an object-oriented system, but one common approach is somewhat analogous to functional decomposition, a common design technique used with traditional programming styles. In functional decomposition, a programmer starts with a single function and breaks it down into multiple functions. The process is usually repeated until many small, easily understood functions have been identified. In object-oriented decomposition, the starting point is a large-scale object that can be broken down into smaller objects. For example, an automobile is an object that contains many smaller objects an engine, a body, a chassis, and so on. These objects can be decomposed further. For example, an engine has valves, pistons, and so on. Programs can usually be organized in a similar way.

A mock-up of the user interface can be a useful place to start the design of an interactive application, because it is common for some parts of a program to correspond to logical groupings of elements of the user interface.

Looking at the proposed rolodex interface, one can observe several logical user interface components. First, it might be useful to encapsulate the entire panel in a class that can be instantiated whenever a rolodex is needed. Besides the user interface, there must be some way to store the information associated with the rolodex, so we might create a Database class. It might also be useful to abstract the information stored in the database, so a Record class could be created to represent a single name and address. So, the list of classes that can be used to construct the rolodex program include the Command, Address, LabeledText, Database, and Record classes. All these classes work together to form a subsystem that forms a single logical user interface component, bound together by the Rolodex class.

The next step is to determine the interfaces between the various objects. For the best results, these interfaces should be based on the role the object plays in the system, and have little to do with internal implementation details. For example, the Address class might support member functions for clearing the current display, displaying a new record, and creating a record from the information typed in by a user. The Command object simply sends messages to other objects. For example, the Command object might send a "clear" message to the Address object, an "add" message to the Database object, and so on.

Once an initial design has been developed, the individual classes can be implemented. Many of these classes can be implemented as subclasses of the VkComponent class. The modular design makes it easy to extend or modify the system if needed. The new classes will fit smoothly with existing IRIS ViewKit classes to form a complete application.

Expanding the IRIS ViewKit Framework Through Reusable Classes

One of the primary reasons for the current interest in object-oriented programming techniques is the promise of greater productivity through reusable code. The IRIS ViewKit framework itself represents a large body of reusable code, and should provide a significant productivity gain to those who use it. However, an even more important goal of the IRIS ViewKit framework is to support developers who want to create new reusable classes. IRIS ViewKit defines a stylistic approach to developing applications, which, if followed carefully, can help produce reusable code.

The rolodex program described above provides one example. This simple program could be written in any number of ways. The object-oriented design described above may actually take longer to develop and require more code to implement than some other approaches, although the IRIS ViewKit library will provide a substantial amount of support, which tends to reduce the amount of code to be written. The additional work is a result of the emphasis on clean, abstract interfaces and a well-defined separation of tasks. In return for the additional time spent designing for an object-oriented model, the rolodex example has the potential to yield some new classes that may be reusable in some situations. The Rolodex class is rather specialized, but it could be useful in some applications. The LabeledText class is very simple, but is quite general purpose and could easily be useful elsewhere. The Address class is less task-specific than the Rolodex class, and might also be useful in other situations. Thus, the design of this simple application has resulted in three new, potentially reusable classes, which could be added to the pool of IRIS ViewKit compatible components available to future applications.

IRIS ViewKit supports the creation of such components in several ways. First, the VkComponent class defines a common interface to be supported by all components. As long as user interface components are implemented as subclasses of VkComponent, the IRIS ViewKit library provides additional services that can operate on and work with these classes. The VkComponent class also supports C++ member function callbacks, which provides a way for classes to interact with one another without requiring hard-coded dependencies between classes. (Hard-coded dependencies decrease reusability.) Finally, the IRIS ViewKit framework provides a core set of services that all components can depend on. Classes can readily use dialogs, the undo facility, and so on, knowing that these core IRIS ViewKit facilities will always be available in any IRIS ViewKit application.

Using Interactive Development Tools with the IRIS ViewKit Framework

One of the most promising types of tools to be developed in recent years is the interactive user interface builder. These tools are known by different names depending on their exact capabilities. Common names include builders, User Interface Management Systems (UIMS), and Interactive Development Tools (IDT). This paper simply refers to all such tools as builders.

A user interface builder allows programmers to draw and test an interface interactively without writing code. In many cases, such tools can have an extremely beneficial effect on a programmers' productivity during the early development and design stages. Most such tools allow a programmer to create an application's interface and then go immediately to a "play" mode, in which the interface responds to user input. Users can press buttons, type in text and so on. By reducing the time a programmer spends compiling and debugging, a builder can greatly reduce the amount of time required to create a first prototype of a user interface. Using a builder allows a programmer to show a realistic prototype of an interface to potential users before committing the design to code. Most such tools can produce code that corresponds to the interactively-developed interface. Since generated code will normally be free of syntax errors, programmers can typically have a running program with a complete user interface after the first compilation.

Not everyone has been successful using user interface builders in the past, largely due to limitations in the technology. Programmers are often disappointed in the code structure produced by builders when generating complete programs. Particularly in C-based programs, it can be difficult to automatically generate code whose structure is appropriate for large systems. Most builders generate code that is incomplete, which also causes problems for programmers working in C. Typically, the code generated by the builder must be modified, which forces the programmer to understand the generated code, and may also prevent the programmer from using the builder for further development or modifications.

The component-based approach supported by the IRIS ViewKit framework is well-suited to an interactive user interface builder, and leads to solutions to some of these problems. First, a builder can be used to create individual user interface components rather than an entire application. A builder can allow IRIS ViewKit components to be created quickly and easily. Because these components tend to be small, functionally cohesive units, the problem of an architecture based on monolithic code segments is avoided. When used in this manner, a builder can actually encourage an object-oriented architecture based on collections of components.

The object-oriented technology used by IRIS ViewKit also provides one solution to the problem of modifying generated code. All classes created by a builder can be treated as abstract base classes, which are never modified. Programmers, of course inevitably need to write some code to connect such classes to the rest of an application. When using the object-oriented approach described here, application-specific code can be added easily by creating subclasses of the generated class and modifying only the derived class. So long as no changes are made to the base class generated by the builder, the class can be reloaded into the builder at any time and modified as needed. Of course, changes made to the base class must be carefully controlled to avoid removing any elements on which derived classes depend.

IRIS ViewKit provides an interactive "builder" solution by coordinating with BuilderXcessory, a Motif® user interface builder from Integrated Computer Solutions (ICS). BuilderXcessory supports the concept of C++ components although it does not directly use IRIS ViewKit classes. SGI provides a IRIS ViewKit module that can be added to BuilderXcessory to allow BuilderXcessory to generate IRIS ViewKit style programs.

Using IRIS ViewKit with IRIS Inventor

The IRIS Inventor library supports an object-oriented model for creating 3D graphics. Although IRIS Inventor does not require IRIS ViewKit, the two libraries are designed to be compatible, and IRIS Inventor shares the IRIS ViewKit concept of a component. IRIS Inventor can be used smoothly within a IRIS ViewKit program, as demonstrated by the following simple program:

Cube.C: Demonstrate a simple use of IRIS ViewKit and IRIS Inventor

void quitCallback(Widget, XtPointer, XtPointer)
{  
    theApplication->terminate(0); // Clean shut down function
}
// Main driver. Just instantiate a VkApp and a viewer, "show" 
// the viewer and then "run" the application.
void main ( int argc, char **argv )
{
    // Init ViewKit
    VkApp             *app = new VkInventorApp("Cube", &argc, argv);
    VkInventorWindow  *win = new VkInventorWindow( "cube", new SoCube());
   
    // Add a menu pane with one menu item
    VkSubMenu  *pane  = win->addMenuPane("Application");
    pane->addConfirmFirstAction("Quit", quitCallback, NULL);
    // Show window and run
    win->show();
    app->run();
}
This program just creates an instance of VkInventorApp and an instance of window that creates an IRIS Inventor scene viewer an IRIS Inventor viewer. A new IRIS Inventor object (SoCube) is created and added the scene viewer window.

Conclusion

IRIS ViewKit combines the extensive set of low-level facilities provided by the Motif toolkit, the ToolTalkTM library, the SGI help system, and other libraries, with the architectural support available within an object-oriented application framework. When developing with the IRIS ViewKit framework, the basic elements of the underlying libraries can be used whenever necessary to provide complete flexibility. Using the Motif toolkit provides users with a standard interface with a widely-accepted behavior and appearance. IRIS ViewKit complements the Motif widget set by providing those elements required by most applications that are not completely addressed by the Motif toolkit. The IRIS ViewKit library supports commonly needed services such as context-sensitive help and network licensing, and provides support for desirable features like busy cursors, interruptible tasks, and dialog management. IRIS ViewKit also makes it easy for developers to create significant application components such as preference dialogs and dynamic menu systems. Most importantly, IRIS ViewKit offers an environment in which developers are encouraged to design applications using an object-oriented approach that takes advantage of existing components and also produces an ever-growing number of reusable classes from which to build future applications.


Footnotes
(1) The VkComponent class implements an extended superset of the component protocol described in Object-Oriented Programming with C++ and OSF/Motif, Prentice Hall, 1992. The underlying concepts are the same in each case, although the implementations differ.
(2) The classes used here are not part of current IRIS ViewKit or IRIS Inventor products.