Chapter 20. Mirror, Mirror

Mirror, mirror, on the wall, who's the fairest of them all? The wicked queen in Snow White had only to look in her mirror to get the true picture. Software engineers should be so lucky. They need good mirrors that simply and accurately reflect the software being engineered. The wicked queen may have been displeased by what she learned, but at least her mirror gave a true image with no difficulty in interpretation.

That's what a good modeling notation offers: a clear image of software—unambiguous and easy to interpret. Unlike a looking glass, a useful modeling notation cannot simply reflect a detailed picture with a one-to-one correspondence to code. A good model is an accurate but selective embodiment of software, a necessarily simplified picture. The effectiveness of a modeling notation for expressing problems and their software solutions depends on how this simplification is achieved. The precise nature of the translation between the medium of the programming language and the medium of the modeling notation should be simple, straightforward, logical, and easy to learn.

Unfortunately, many of today's proliferating program analysis and design notations fail in these fundamental requirements. They are overly complex, arbitrary, ambiguous, difficult to learn, and difficult to interpret. And, of course, there are far too many of them.

Complete modeling of software is complicated, involving numerous views of static and dynamic aspects: the structure and composition of information, the nature of the algorithms and their realization as procedures, factoring into component parts, and communication among parts. If the data model, procedural model, communication model, state model, and functional composition of software are all conflated into a single diagram in one comprehensive notation, the result is baroque, visually cluttered, and hard to understand.

Getting the Picture

Software engineering models serve much the same purposes as the wicked queen's mirror. Notations should make clear the difference between the fairest of solutions and those that are only fair. Developers need to be able to tell by looking at a model whether the design is sound or stupid. A software design model is not merely a holding place for as-yet-unbuilt software ideas. It allows developers to spot problems and shortcomings in the design and to compare approaches to see which is superior. Ultimately this is why good developers draw pictures before they code—it's cheaper to build paper models than to build software, and good models make it easier to see how to do things well.

Good notation allows for simple, direct, and unambiguous translation between model and code: to develop code from a model and to model existing code. Sloppy, obscure, or imprecise notation makes for sloppy, obscure, and imprecise translation. Every visual element in the notation should correspond with some specific and relevant aspect of the software being modeled; every important feature in the code should be expressible in the notation.

A good notation produces pictures that can be interpreted analytically, through a thorough study of details, and understood intuitively as a gestalt—a whole representing the overall character of a system. Complicated designs should look more complicated than simple ones, good architecture should be more visually appealing than bad design. In other words, a good notation allows developers to use both sides of the brain; it helps them think both logically and intuitively about the system being designed.

To accurately mirror software, yet present a substantially simplified view, good notation highlights things that are important and hides or suppresses those that are not. Dominant features and major components are writ large, while minor details are annotations or disappear from view.

The picture is kept simple by not showing internal details. A software component that is basically a black box becomes a simple box drawn on screen or paper; internal details are invisible. Lines pointing to these graphical boxes suggest programming references to software boxes, not to their internal features.

Ideally, we want the kind of selective control over visibility only possible in a computerized tool. We would like, for instance, to browse through an object communication diagram, skimming over a landscape of tiny objects, then zoom in to study relationships in one region. We might close in on one object to see what methods it supports. We double-click and are looking at the C++ code defining one method. Or we might flip to a view that superimposes user interaction scenarios on the communication diagram, highlighting or coloring objects participating in one scenario.

Notation and Usability

It's easy to develop your own notation; all too many people do. It's hard to do it well, and many notations that fill our journals and magazines are not very good as modeling tools.

Designing a good notation is like designing a good user interface. The goal is to reduce human memory load. The Great Law of Usability says a system should be usable—without training, assistance, or manuals—by someone who knows the application but not the software (Constantine 1991b). A really good notation, then, is one that an experienced software engineer who knows how to design and build software can interpret directly and intuitively without a week-long class or a complicated cheat-sheet. You shouldn't have to remember arbitrary things like a double-barred box as a dynamic object or one with a flag in the corner as a reused library component.

Things should look like what they are. Symbol shapes and line styles cannot be arbitrary or counter-intuitive. For instance, the basic foundation upon which other components are built through inheritance and reuse should look like solid and well-defined elements, not ephemeral clouds.

Strong connections between parts should look strong; weaker ones should look more tenuous. Stable objects should appear solid, dynamic ones should convey some sense of activity or changeability. For example, inheritance by one class of the features and characteristics of another means that the subclass is strongly dependent on the superclass, just as a child's genetic characteristics are strongly dependent on those of both parents. To accurately reflect the characteristics of software using it, inheritance should be shown in a way that looks stronger than message passing or reference to an object as an attribute (Page-Jones, Constantine, and Weiss 1990).

What makes a notation intuitive and easy to learn can be a matter of small and subtle details. In Jacobson's notation for object-oriented software (Jacobson et al. 1992), objects that interface with the outside have a “lazy-tee” (I– )on one side as a visual reminder of the interface. Dynamic objects that control sequences of interaction have an arrowhead imbedded in the border, suggesting a loop or iteration. In several notations, internal features of components that are externally accessible are shown straddling the border of the component.

A good notation also builds on and uses what software engineers already know, especially what they know about notations. That means not using new symbols for old concepts and not recycling the same pictures for new and incompatible ideas. In fact, we probably don't need any new notations. Our efforts would be better spent standardizing and consolidating what we already have, applying sound principles of modeling and human thought.

Think about it.

From Software Development, Volume 2, #3, March 1994.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.116.40.53