Response by Mary Shaw

Open Implementations --
Abstractions, Separation of Concerns, and Degrees of Control

Open Implementations

When I think about open implementations, I think about machinery with maintenance panels as well as user controls: Interestingly enough, the things that spring immediately to my mind are not dominated by performance tuning -- but most of the examples in the foil are. I believe Figure 4.

The Essential Question

The guiding principle of software requirements is that they should state *what* the system should do and should not make decisions about *how* to do it. The trouble is, in many cases it's very, very hard to isolate the abstract function. People are pretty concrete, and (a) the implied generalization step is tough; (b) the language available for most requirements lends itself to giving examples for definiteness.

The same principle holds at any specification/implementation boundary: the specification makes the guarantees, the implementation achieves them. There's clearly a tradeoff: the more flexible the specification is, the more likely it is to be broadly useful, but the more constrained the implementation will be. No free lunch: Better value in the component means higher constrtuction costs.

Seems to me that the essential question here is:

How can we separate essential properties (at any stage of the design) from inessential or incidential ones, allowing the latter to be provided later?

Here are some questions to help focus on the distinction:

  1. What information should be available, to whom, and when? Who provides it?
  2. How can this be done without adverse interactions or other interference? (This is why single-hierarchy defintion chains are so much simpler than multiple chains; it's why reconciling different design views is hard.)
  3. How do you decide how much generality/flexibility to provide?
  4. When can various kinds of decisions be bound (i.e., what can be meta-parameters, and are they handled at compile or execute time?)

Freedom vs License

It is suggested that breaking the black box boundary and allowing the meta-interface any control over the semantics allows arbitrarily bad things to happen and should therefore be disallowed. However: The "generator" construct in Alphard is an example. It separated the loop construct into three parts:
  1. the essential init-(test-advance)* pattern (which is the responsibility of the language),
  2. the definitions of init, test, and advance (which are the responsibility of the designer of a structure that supports iteration), and
  3. the loop body (which is the responsibility of the programmer).
But it gets better: the set {init, test, advance} was required to satisfy a requirement. Specifically, a theorem had to be true of their joint pre- and post-conditions. In exchange, you got a case-specific Hoare-style proof rule for the resulting loops. You could *not* break the essential semantics of loops, but you could tune it to your needs.

It is also suggested that the designer of a language/metalanguage should try to prevent bad programs from being written. This is not a useful goal, as perverse programmers will find a way to do Bad Things with any tool you give them. A better goal is to design the language to help programmers express their designs clearly and concisely, without requiring unnecessary decisions at any point.

Abstraction at the Meta-interface

The foil doesn't say much about the level of abstraction at the meta-interface. This does require attention. We learned this when we designed a symbol table in Alphard. [Alphard was an abstract data type langauge that explicitly separated the formal specification of a component from its implementation. The specification presented the abstract model, the implementation the code. There was an explicit abstraction function to connect the two.]

The specification of the symbol table included among its initialization parameters an integer. The integer was not mentioned any place in the specification, so it appeared to have no effect -- a useless parameter. Well, the integer controlled the size of a hash table.

It affected performance rather than functionality -- the specs didn't address anything except functionality, so this integer had no role. Further, even explaining the integer as hash table size would have been wrong -- there's no reason the user of a symbol table should know about the implications of hash table size. It would have been better to express the parameter as a tuning function, assigning values with understandable effect on speed and converting them internally into hash table size. Or something else.

Structured interfaces

My control access panel analogy leads to a further question: why just interface and metainterface? After all, a physical system might have maintenance panels for mechanical, electrical, hydraulic, engine...

More to the point, a software component might well have (at least conceptually) interfaces for:

These may be scrambled together in such a way that it's hopeless to sort them out, but conceptually they're often there)

Now in some ways each of these except the first looks like a meta-interface. You can certainly make both data changes and policy changes without affecting the general nature of the overt function. I don't think you want to join them in a single meta-interface. First, that would violate separation of concerns. Second, it would probably violate operating policy.

A good concrete example is the Scribe text formatter. It was of the *ROFF/PUB generation, came on the scene a little before TeX. What Scribe got *really* right was the separation between: the document, the style in which the document is formatted, and the device on which the document is printed. The same notation was used for all three. The differences involved what you could control. The style and the device are both meta-stuff, but it's important to keep them separate.

Another thing Scribe got right was incrementality. You could make small changes in the style with small amounts of knowledge. You could make large changes in the style with modest amounts of knowledge. You could do truly arcane things if you wanted to badly enough. In another community this property is called the "gentle-slope system" property, referring to the slope of the learning curve required to use the system well, or at all.

Back to Alphabetical List of Responses

Back to Main OI Workshop Page

Back to OI Home Page


Mary Shaw, Mary_Shaw@cs.cmu.edu

(Last Revised March 1996)