Newsletter sign-up

Sign up for our technology specific newsletters.

Enterprise Java
View all newsletters

Email Address:

Build user interfaces for object-oriented systems, Part 2: The visual-proxy architecture

A scalable architecture for building object-oriented user interfaces

T his installment of Java Toolbox presents the first of several examples of how to apply object-oriented design principles that I've outlined in previous articles to build a workable user interface. I'll show you a forms-based I/O system that implements an architecture that I call "visual proxy." Subsequent articles will describe more complex systems, but I'll start with a simple one just to demonstrate the concepts.

"Build user interfaces for object-oriented systems": Read the whole series!



The problem

This month's column expands on the ideas presented in July's column, "Building user interfaces for object-oriented systems, Part 1," by actually implementing a simple system for doing forms-based I/O. The main principle that I'm demonstrating here is organizational: I'll show you how to organize your code in such a way that arbitrary forms can be constructed automatically, minimizing the coupling relationships between the GUI subsystem and the underlying logical model (the "business" objects, if you will).

One approach to this problem is to have all objects render themselves on the screen (with a draw_yourself(Graphics here) message). Though this sort of simplistic approach can work for trivial objects, it's not a realistic solution for several reasons. First, actually embedding graphical code into the methods of a model-level class is usually a bad idea for maintenance reasons. The graphical code is usually scattered throughout the methods of the object, and it becomes too difficult to make minor changes in implementation as a consequence. It's also very difficult for an object to display itself in more than one way. This month, I'll look at an approach that doesn't have the problems of Model/View/Controller (MVC) architecture, but that accomplishes the main goal of the Microsoft Foundation Classes (MFC): the decoupling of the abstraction (model) and presentation (view) layers.

Attributes

The main way to get around the problems caused by simply asking an object to display itself is to make a distinction between the entire object and its individual attributes. In the world of object-oriented design, an attribute falls under one of the following definitions:

  • A characteristic of some class of objects that serves to distinguish it from other classes of objects. For example, the notion of a salary distinguishes a class of objects (employees) from a broader class of objects (people in general). People without salaries are simply not employees -- they're volunteers, derelicts, CEOs of software startups, and the like, but they aren't employees. All employees, then, must have a salary, so salary is an attribute of an employee.
  • A characteristic of some object that serves to distinguish it from other objects. An employee's name, for example, serves to distinguish individual employees from each other. Two completely unrelated classes (person and microprocessor, for example) could have name attributes, so the class-based test above doesn't work, but the name does serve to distinguish one employee from another employee (or one microprocessor from another microprocessor).


The operations of a class are attributes as well: what an object can do certainly distinguishes one class of objects from another.

Attributes are not fields

An attribute is not the same thing as a field. A Salary, for example, could be represented internally as a float, a double, in binary-coded-decimal, as an ASCII string, as an ASCII string holding the SQL needed to get the actual salary from a database, and so forth. It might not be stored at all, but could be computed at runtime from some other attribute like a U.S. Government salary "grade" (like "GS-3"). Even in the last case -- in which no internal storage occurs -- an employee still must have a salary. That is, attributes have nothing to do with implementation. If you get the attribute set wrong, you've blown it as a designer. Moreover, the odds of an attribute going away as the program evolves are minimal, though the implementation of that attribute could change radically, and a field that used to be used for implementation could indeed go away. (You may add an attribute, but that's typically not as difficult a maintenance problem as removing one.)

The main reason you need to identify the attributes is not to decide what the fields are; rather, you need them to decide which operations are relevant. If a class of objects has some attribute, then it's reasonable to ask the objects to do something with that attribute. To paraphrase the July Java Toolbox column: "Don't ask for the information that you need to do something; rather, ask the object that has that information to do the job for you." Object-oriented designers call this process delegation.

Display attributes, not objects

It's commonplace to need to display various attributes of an object in different combinations on different screens, but to never display all the attributes of a given object in one place. Sometimes you need to display only the name of an employee; sometimes you need to display the name, salary, and social security number of the employee. And all of these attributes are displayed in arbitrary places on a given screen or within a given form. That's why a generic display-yourself method (like an Employee.draw_yourself(Graphics g) message that caused an Employee object to print its state on some window) can't work in the general case. It's worth noting, though, that a given attribute will almost always be displayed in the same way. That is, a salary, when it's displayed, will always be shown as a fixed-point number with two decimal places. (Minor formatting problems can be handled by passing in a previously initialized NumberFormat object that controls the formatting.) In fact, this sort of consistency is usually considered essential in a well-designed UI. It's typically the mix of attributes that change, not the way the attributes themselves are displayed.

Resources