home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.umcs.maine.edu
/
2015-02-07.ftp.umcs.maine.edu.tar
/
ftp.umcs.maine.edu
/
pub
/
WISR
/
wisr6
/
proceedings
/
ascii
/
lea.ascii
< prev
next >
Wrap
Text File
|
1993-10-19
|
15KB
|
295 lines
Cataloging Ob ject Oriented Software Reuse
Doug Lea
SUNY Oswego, Oswego NY 13126 and
NY CASE Center, Syracuse NY 13244-4100
Tel: (315) 341-2688
Email: dl@g.oswego.edu
Fax: (315) 443-4745
Abstract
Ob ject-Oriented design is often said to be a positive factor in reuse. This position paper
attempts to clarify some of the contributing factors and a few problem areas.
Keywords: Reuse, Object-Oriented, Design
Workshop Goals: Learning; networking;
Working Groups: Reuse and OO methods, Reuse and formal methods, Domain analy-
sis/engineering, Design guidelines for reuse - OO
Lea- 1
1 Introduction
Among the many reasons people adopt Object-Oriented (OO)methods is the widely held reputation
for enhancing software reuse. However, many different, even conflicting accounts have been offered
in explanation of this reputation. The remainder of this position paper attempts to categorize and
clarify some of the ways in which OO developers obtain reuse.
2 Composition
OO methods support a version of the most basic and essential form of reuse, the combination
of possibly many individual components to serve some aggregate purp ose. Object composition is
different in both concept and execution than procedure, function, or module composition. However
it may be used to identical or similar effect. In compositional OO design, a developer defines a
class whose instances serve as "hosts". Hosts maintain the identities of other"help er" objects and
send them messages in the course of achieving required functionality.
Many variants exist. For example, one common form of composition is often termed "delegation".
Here, any of some subset of messages are simply forwarded (delegated) to the ob ject referred to
by a certain connection link, but the exact object on the other side of the link may change (be
rebound) over time.
Compositional designs may also be categorized with respect to their encapsulation and modularity
properties. Pure closed composition is a form of black box reuse. It is among thesafest and most
conservative possible design strategies, due to:
fflOutward Closure. Helpers never send messages except simple replies to objects outside some
known scope. Replies never reveal the identities of inner objects.
fflInward Closure. The host maintains the sole link to each helper. The host never reveals
the identities of helpers. No other objects may access the helpers or otherwise exploit their
existence.
ADT-style OO designs rely on closed composition. The success of basic libraries containing many
such black-box components attests to the utility of closed composition in addressing in-the-small
reuse needs.
2.1 Architecture
The above closure restrictions may be lifted either by choice or by necessity, resulting in a continuum
of open composition strategies involvingcollab oration networks, resource sharing, and larger scale
opportunities for reuse. And larger scale opportunities for disaster: aliasing, interference, and
lack of independence and local verifiability. These must be dealt with via combinations of design
rules (e.g., access control policies), organizing constructs (e.g. "groups", "roles"), and worst-case
implementation techniques (e.g., locking, atomic transactions). The presence of such dangers,
along with the sheer difficulty of their diagnosis, prevention, and control can be a limiting factor
in successful reuse of individual classes. However, semi-isolated networks in which these factors are
known to be under control are often reusable as a group.
Lea- 2
Moreover, by abstracting over the functionality of a system or subsystem of components, and
only paying attention to their static and dynamicinterrelations, one may use/reuse the resulting
design architectures. Architectural reuse ranges from the everyday use of "standard forms" of
static connections (e.g., simple linked lists), to the incorporation ofdesign patterns that represent
solutions to common structuring problems (e.g., model-view-controller designs), to the system-wide
adoption of large-scale architectural frameworks (e.g., software bus, Linda tuple space).
Architectural reuse may or may not involve any actual code reuse. Some architectural elements may
indeed be completely isolated from application-specific functionality. The isolationof elements into
nodes and use of parameterized code to construct lists of such nodes represents afamiliar example.
Similarly, "protocol objects" such as multicast controllers may be reused in the construction of
group broadcast designs without regard for the contents of multicast messages.
However, there may be at least an equal numb er ofexamples in which no code reuse is possible.
For example, OO components assisting in the construction of many general graph structures seem
little used, perhaps because of typical application-specificity of node and edge semantics. Instead,
the general ideas are manually adapted to the situations at hand. It is not clear (and not worth
debating) where to draw the line between this formof reuse and the application of "general design
knowledge".
3 Inheritance
3.1 Classes as Specifications
Class constructs provide developers the opportunity to declaratively specify the behaviors of objects.
While there is an enormous range in support for declarative specification, nearly all methods,
languages, database tools, etc., possess some means of indicating what objects do without saying
how they do it, or at least without allowing other software to depend on how they do it. Constructs
may include simple method interfaces, method signatures, invariants, preconditions, postconditions,
and other specification devices. Unlike similar module-based constructs, classes allow the reuse of
the same specification for an arbitrary number of software entities (objects).
3.2 Specification Inheritance
The simplest way to reuse a specification that does not quite apply to anew problem is to extend
it. Specification inheritance (also known as property inheritance) supports extension by addition of
specifications. Subclasses may add newprop erties (e.g., methods, attributes) and/or add further
constraints on existing ones. However, additions may not invalidate any property listed in any
superclass. Beyond its technical uses, the emphasis on specification inheritance in OOdevelopment
can lead to increased human understandability andconceptual reuse that accompanies any effort
to hierarchically categorize entities in a given domain.
3.3 Polymorphism
Specification is an analysis and design concept. However, OOlanguages and tools integrate at least
some declarative and operational aspects of types and inheritance, thus linking the expression of
Lea- 3
properties and code in software. The resulting type systems enable exploitation of subclass poly-
morphism: A software client c may require that a particularserver ob ject s p ossess the properties
listed in some class A. However, s may well be an instance of a subclass SubA with additional
properties. Specification inheritance rules, taken seriously, ensure that none of theextra prop erties
in SubA invalidate c's assumptions andrequirements about s.
The primary effect on reuse is support for interoperability. Since client code is decoupled from
inessential features, new subclasses of A may be developed and plugged while at the same time
reusing existing client code. In practice, this remains more of an ideal than an everyday occurrence.
Client code is too often written in a way that needlessly depends on inessential features of a
specialized class rather than a less committal, more generalsup erclass. (Design rules and languages
distinguishing interfaces from implementations can alleviate this but tend to leave architectural
specifications hidden as "implementation" matters.) Also, the introduction of a new subclass may
suggest better ways of factoring and expressing superclasses and clients.
OO frameworks (e.g., for GUIs) typically combine these forms of polymorphic client code reuse
with architectural reuse. Frameworks declare one or more inheritance hierarchies in which most
classes are listed mainly in terms of their abstract interfaces. However, the classes may also contain
code-based commitments to interconnection rules and protocols that holdindep endently of how
other functionality is implemented. Framework users must add subclasses that implement (and
perhaps add to) the desired functionality in an application-specific manner whilestill ob eying the
connection patterns and protocols listed in superclasses.
Additional reuse opportunities stem from constructs allowing classes to be parameterized with
respect to other types. The techniques are similar to those used in modular design techniques
for languages such as Ada. However, inheritance and parameterization (genericity) are not purely
orthogonal concepts. Interactions among them lead to new design strategies, about which there is
as yet little to conclude with respect to reuse.
3.4 Defeasible Inheritance
Few languages enforce pure property inheritance rules. They instead support a form of defeasible
inheritance in which some superclass properties may be overridden in subclasses. In most languages,
this overriding is limited to redefining method implementations in subclasses.
Overriding can enhance reusability. Overriding rules can make it easier to obtain code decoupling.
In a system with overriding, clients cannotdep end on any features of listed method code, since it
may change in subclasses. (Since in most languages, only method code, not data representation
commitments may be overridden, representational coupling remains a potential problem.) It also
provides additional opportunities for internal reuse. A superclass may include default method
implementations that are reused by most subclasses without forcing all of them to do so.
However,this form of reuse-driven inheritance can have harmful effects on other aspects of reuse and
software quality. Most languages do not contain powerful enough declarative constructs to require
subclass designers to preserve all essential guarantees of their superclasses. Even inlanguages that
do possess these features, programmers tend not to use them enough. It is often so much easierto
write code that implements functionality than declarations describing its effects that people don't
even attempt the latter. Thus, a subclass implementation of a method may alter semantics in a
way that does not preserve interoperability prop erties that clients depend on. As a limiting but
very common case, a new class may list another as a superclass solely to reuse a few bits of its
Lea- 4
implementation without in any way preserving superclass declarative properties. (Some languages
do provide constructs that distinguish at least this extremecase.)
Sometimes this form of implementation inheritance is used by developers just because it is easy to
express in OO languages. Reuse goals could be better preserved via compositional techniques such
as using another object as a delegated helper rather than listing its class as a superclass. Worse,the
fact that many programmers see these two options as nearly equivalent can lead to other conceptual
design errors. Worse still, languages, user manuals, and textbooks themselves obscure these issues
by attempting to relate subclassing concepts to the use of runtime storage layout schemes that can
be viewed as representationally "embedding" superclass objects inside subclass objects. Design
decisions are sometimes based on these considerations. Sometimes this is due to an unfortunate
but correct concern for representational compatibility with existing reused software (e.g., between
C and C++), but more often results from simple confusion about efficiency consequences.
Defeasible inheritance is also used by programmers in order to evade language-based encapsulation
rules. In most languages, a client/host is not allowed to evenreference internal implementation
matters listed in a class, but a subclass is. Thus, inheritance is used to simplify white-box reuse of
incidental implementation features. While such code mangling is not an optimal form of reuse, it
is often preferable to no reuse at all, so does have its place. It is unfortunate that OO languages
force such tradeoffs against non-local reusability goals.
To the extent to which sp ecification reuse is more important than code reuse, defeasible inheritance
appears to be a net loss. There are certainly better language constructs available that still support
decoupling, default code, and opportunistic white-box reuse, and even the convenience of expressing
specifications, interfaces, and code in the same framework. In fact, even without adding new
constructs, it is very possible to ban all use of defeasible inheritance in languages including C++
and Smalltalk, and still obtain these forms of reuse. However, the constructions are awkward and
unnatural enough that programmers do not employ them in practical development.
4 Biography
Doug Lea teaches computer science at the State University of New York at Oswego, teaches
software engineering courses at Syracuse University, co directs the Software Engineering Lab at
the New York State Center for Advanced Technology in Computer Applications and Software
Engineering, and works on projects involving object-oriented design, specification, distribution,
compilation, reusability, and libraries.
Lea- 5