\markboth{Lea}{Lea}
% file Lea-WISR93.tex
% based on
%%%%%% TEMPLATE.TEX for WISR'93, version 1.2, 4/22/93 %%%%%%
%%%%%% Updated by Jeffrey S. Poulin, May 1993         %%%%%%

\documentstyle[11pt]{article}

% Standard Spacing for WISR - do not change!!
%
% Page dimensions.
%
\oddsidemargin  0.26in % Leave enough for binding margin
\evensidemargin 0.26in %
\topmargin      -1.00in % (adjusted for printer bias)
\headheight      .00in  % (no headers)
\headsep         .75in  % (top margin + headers + skip)
\footheight     12.0pt  % ??? (seems to work ok)
\footskip       25.0pt  % ??? ( "   "  )
\textheight     9.425in % (instructions: 9 1/8" min, 9 7/16" max)
\textwidth      6.5in   %

\markboth{Lea}{Lea}
\pagestyle{myheadings}

%
% Paragraph changes.
%

\parindent=0pt
\parskip=10pt
%
% can make the title box even smaller
%
\def\@maketitle{\vbox to 2.6in{\hsize\textwidth
    \linewidth\hsize \vfil \centering
    {\large \@title \par}
    \vskip 2em
    {\normalsize
    \begin{tabular}[t]{c}\@author
    \end{tabular}\par}
    \vfil}
}

\begin{document}

\bibliographystyle{ieeetr}

\title{Cataloging Object Oriented Software Reuse}

\author{Doug Lea\\
\\
SUNY Oswego, Oswego NY 13126 {\em and}\\
NY CASE Center, Syracuse NY 13244-4100\\
Tel: (315) 341-2688\\
Email: dl@g.oswego.edu\\
Fax: (315) 443-4745\\
}
\date{}

\maketitle

\begin{abstract}

Object-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.

\vspace{0.2in}
\noindent
{\bf Keywords:} Reuse, Object-Oriented, Design

\vspace{0.2in}
\noindent
{\bf Workshop Goals:} Learning; networking;

\vspace{0.2in}
\noindent
{\bf Working Groups:} Reuse and OO methods, Reuse and formal methods,
Domain analysis/engineering, Design guidelines for reuse - OO

\end{abstract}

\newpage

\section{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.

\section{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 purpose.  {\em 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
``helper'' 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 object 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 {\em closed}
composition is a form of {\em black box} reuse.  It is among the
safest and most conservative possible design strategies, due to:
\begin{itemize}
  \item {\em Outward Closure.} Helpers never send
        messages except simple replies
        to objects outside some known scope.
        Replies never reveal the identities of inner objects.
  \item {\em Inward 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.
\end{itemize}
\noindent
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.

\subsection{Architecture}

The above closure restrictions may be lifted either by choice or by
necessity, resulting in a continuum of {\em open} composition
strategies involving collaboration 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.

Moreover, by abstracting over the functionality of a system or
subsystem of components, and only paying attention to their static and
dynamic interrelations, 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 of design 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 isolation of elements into
nodes and use of parameterized code to construct lists of such nodes
represents a familiar 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 number of examples 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 form of reuse and the application of
``general design knowledge''.

\section{Inheritance}

\subsection{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).

\subsection{Specification Inheritance}

The simplest way to reuse a specification that does not quite apply to
a new problem is to extend it.  Specification inheritance (also known
as property inheritance) supports {\em extension by addition} of
specifications. Subclasses may add new properties (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 OO development can lead to increased human understandability and
conceptual reuse that accompanies any effort to hierarchically
categorize entities in a given domain.


\subsection{Polymorphism}

Specification is an analysis and design concept.  However, OO
languages and tools integrate at least some declarative and
operational aspects of types and inheritance, thus linking the
expression of properties and code in software.  The resulting type
systems enable exploitation of subclass polymorphism: A software
client {\tt c} may require that a particular server object {\tt s}
possess the properties listed in some class {\tt A}.  However, {\tt s}
may well be an instance of a subclass {\tt SubA} with additional
properties.  Specification inheritance rules, taken seriously, ensure
that none of the extra properties in {\tt SubA} invalidate {\tt c}'s
assumptions and requirements about {\tt s}.

The primary effect on reuse is support for {\em interoperability}.
Since client code is decoupled from inessential features, new
subclasses of {\tt 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 general
superclass.  (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 {\em 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 hold independently 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 while still obeying 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.

\subsection{Defeasible Inheritance}

Few languages enforce pure property inheritance rules. They instead
support a form of defeasible inheritance in which some superclass
properties may be {\em 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 cannot depend 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 {\em 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 in languages that do possess these features,
programmers tend not to use them enough. It is often so much easier to
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 properties 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 implementation without in
any way preserving superclass declarative properties. (Some languages
do provide constructs that distinguish at least this extreme case.)

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 even reference 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 specification 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.


\section{Biography}

{\bf Doug Lea} teaches computer science at the State University of New
York at Oswego, teaches software engineering courses at Syracuse
University, codirects 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.


\end{document}


