Objects Essay
Objects Essay
Jonathan Aldrich
Carnegie Mellon University
Pittsburgh, PA, USA
[email protected]
Abstract 1. Introduction
Three years ago in this venue, Cook argued that in Object-oriented programming has been highly suc-
their essence, objects are what Reynolds called proce- cessful in practice, and has arguably become the dom-
dural data structures. His observation raises a natural inant programming paradigm for writing applications
question: if procedural data structures are the essence software in industry. This success can be documented
of objects, has this contributed to the empirical success in many ways. For example, of the top ten program-
of objects, and if so, how? ming languages at the LangPop.com index, six are pri-
This essay attempts to answer that question. After marily object-oriented, and an additional two (PHP
reviewing Cook’s definition, I propose the term ser- and Perl) have object-oriented features.1 The equiva-
vice abstractions to capture the essential nature of ob- lent numbers for the top ten languages in the TIOBE in-
jects. This terminology emphasizes, following Kay, that dex are six and three.2 SourceForge’s most popular lan-
objects are not primarily about representing and ma- guages are Java and C++;3 GitHub’s are JavaScript and
nipulating data, but are more about providing ser- Ruby.4 Furthermore, objects’ influence is not limited
vices in support of higher-level goals. Using examples to object-oriented languages; Cook [8] argues that Mi-
taken from object-oriented frameworks, I illustrate the crosoft’s Component Object Model (COM), which has
unique design leverage that service abstractions pro- a C language interface, is “one of the most pure object-
vide: the ability to define abstractions that can be ex- oriented programming models yet defined.” Academ-
tended, and whose extensions are interoperable in a ically, object-oriented programming is a primary focus
first-class way. The essay argues that the form of inter- of major conferences such as ECOOP and OOPSLA,
operable extension supported by service abstractions and its pioneers Dahl, Nygaard, and Kay were honored
is essential to modern software: many modern frame- with two Turing Awards.
works and ecosystems could not have been built with- This success raises a natural question:
out service abstractions. In this sense, the success of
objects was not a coincidence: it was an inevitable con- Why has object-oriented programming been success-
sequence of their service abstraction nature. ful in practice?
To many, the reason for objects’ success is not obvi-
Categories and Subject Descriptors D.1.5 [Program- ous. Indeed, objects have been strongly criticized; for
ming Techniques]: Object-Oriented Programming example, in an interview Stepanov explains that his
STL C++ library is not object-oriented, because he finds
Keywords Object-oriented programming; frame-
OO to be technically and philosophically unsound,
works; interoperability; service abstractions
and methodologically wrong [29]. In addition, popular
object-oriented languages are often criticized for their
Permission to make digital or hard copies of all or part of this work for flaws; for example, Hoare states that the null references
personal or classroom use is granted without fee provided that copies are not most OO languages provide were his “billion dollar
made or distributed for profit or commercial advantage and that copies bear
this notice and the full citation on the first page. Copyrights for components 1 http://www.langpop.com/
of this work owned by others than the author(s) must be honored. Abstracting
with credit is permitted. To copy otherwise, or republish, to post on servers or 2 http://www.tiobe.com/index.php/content/paperinfo/
to redistribute to lists, requires prior specific permission and/or a fee. Request tpci/index.html
permissions from [email protected]. 3 http://sourceforge.net/directory/, click Advanced and
Onward! 2013, October 29–31, 2013, Indianapolis, Indiana, USA.
Copyright is held by the owner/author(s). Publication rights licensed to ACM. mouse over Programming Language, accessed 4/7/2013
ACM 978-1-4503-2472-4/13/10/13/10. . . $15.00. 4 https://github.com/languages, accessed 4/7/2013
http://dx.doi.org/10.1145/2509578.2514738
mistake”[13]. These and other criticisms have led some To support this thesis, we need a careful defini-
to argue that object-orientation became popular essen- tion of interoperable extension and an analysis of how
tially for marketing reasons: because “it was hyped objects provide it—by contrast, we’ll see that obvi-
[and] it created a new software industry.”5 ous alternatives such as abstract data types don’t (Sec-
While there has unquestionably been some hype tion 3). Alternative mechanisms can provide inter-
about objects over the years, I have too much respect operable extension only by using service abstraction
for the many brilliant developers I have met in indus- themselves—and thus are equivalent to what we con-
try to believe they have been hoodwinked, for decades sider the essence of objects.6 Interoperable extension is
now, by a fad. The question therefore arises: might essential to many modern software systems and frame-
there be genuine advantages of object-oriented pro- works, in that the core architectural requirements of
gramming that could explain its success? these systems cannot be fulfilled without it (Section 4).
Some of the advantages of object-oriented program- The rise of objects, therefore, is not a coincidence: it
ming may be psychological in nature. For example, is an inevitable response to the needs of modern soft-
Schwill argues that “the object-oriented paradigm...is ware.
consistent with the natural way of human think- Pieces of the story told here are known, more or less
ing” [28]. Such explanations may be important, but formally, within the object-oriented and programming
they are out of scope in this inquiry; I am instead in- language communities, but the larger story has not
terested in whether there might be significant technical been well told. With that story in place we can begin
advantages of object-oriented programming. to explain the success of objects on a purely technical
The most natural place to look for such technical basis.
advantages is the essential characteristics that define Along the way, we’ll connect Cook’s definition of
the object-oriented paradigm. On this question there is objects with Kay’s focus on messaging as a key to
some controversy, but I follow Cook’s definition: “an object-orientation; investigate a mystery in the design
object is a value exporting a procedural interface to of object-oriented vs. functional module systems; and
data or behavior” [8]. In other words, objects are in use the theory sketched here to make predictions both
their essence procedural data structures in the sense of about the technical feasibility of statically typed, fully-
Reynolds [27]. Cook’s definition essentially identifies parametric modules in object-oriented systems, and
dynamic dispatch as the most important characteris- about the effect of adding first-class modules to lan-
tic of objects. Each object is self-knowing (autognostic guages that do not support objects.
in Cook’s terms), carrying its own behavior with it, I hope that the arguments in this essay will inspire
but assuming nothing about other objects beyond their researchers to gather data and build systems that can
own procedural interfaces. This autognosis property, properly validate the propositions described here.
in turn, enables different implementations of an object-
oriented interface to interoperate in ways that are diffi- 2. The Nature of Objects
cult when using alternative constructs such as abstract A clear understanding of the nature of objects is essen-
data types. tial to my argument. Cook’s definition was intended
Could data structure interoperability really be so to distinguish objects from ADTs, with which objects
important? It is an excellent question, but too narrow. are often confused. However, his definition extends be-
As we will see, to understand the value of objects we yond data abstraction, following Alan Kay’s emphasis
must consider service abstractions that go beyond data on objects providing services that support high-level
structures, because it is for abstractions of components behavioral goals. As we will see, it is in its ability to ab-
and services that interoperability becomes critical. This stract behavior that object-oriented programming pro-
leads to the following thesis: vides its greatest benefits.
Note that different IntSet implementations can in- As with the abstract SetModule1.IntSet de-
teroperate. For example, as shown in the code below, scribed earlier, all instances of IntSetA are instances
we can have instances of two different implementa- of the same class and have the same internal represen-
tions of type IntSet and test if one contains all el- tation.8
ements of the other. An object-oriented set type can The disadvantage of ADTs, relative to objects, is the
be described using an interface in Java; an example lack of interoperability. Consider what happens if we
is java.util.Set, or simply the interface above re- define a second Java class, called IntSetB, analogous
placing the keyword type with interface. Different to the first one above:
classes can then implement that interface. Each set ob- // different code but the same interface
ject carries its hidden implementation type with it. In final class IntSetB {
type theory, we say that objects have existential types; bool contains(int element) { ... }
the existential is opened on every access to each object. bool isSubsetOf(IntSetB other) { ... }
class IntSet1 implements IntSet { ... } }
class IntSet2 implements IntSet { ... } // in main()
IntSetA sA = new IntSetA(...);
// in main() IntSetB sB = new IntSetB(...);
IntSet s1 = new IntSet1(...); boolean x = sA.isSubsetOf(sB); // ERROR!
IntSet s2 = new IntSet2(...); Now if we create an instance of IntSetA and
boolean x = s1.isSubsetOf(s2); an instance of IntSetB, we cannot invoke the
In contrast a set ADT might be abstractly defined as isSubsetOf operation to compare their contents. The
follows: reason is that IntSetA and IntSetB are different ab-
stract types; neither is a subtype of the other. This is,
module SetModule1 { in fact, an inevitable consequence of the fact that bi-
// implementation...
nary operations on abstract data types can depend on
} with signature {
type IntSet;
the internal representation of the second object passed
in. This dependence has performance advantages, but
bool contains(IntSet set, int element); makes interoperation impossible, since IntSetB may
bool isSubsetOf(IntSet s1, IntSet s2);
ple dispatch, in which the implementation of an operation is chosen
}
dynamically according to the class of all arguments to a generic func-
Set ADTs matching this identical signature can be tion [3]. Other solutions include using double-dispatching idioms or
more ad-hoc instanceof-style class tests. A full discussion of these
implemented by multiple modules (SetModule1, solutions, including the significant modularity issues involved, is
SetModule2, etc.), but each module SetModuleN out of scope here.
defines a separate type SetModuleN .IntSet. 8 Note that the Java implementation of IntSetA uses a final class
The ADT type SetModule1.IntSet denotes the in order to sidestep the use of inheritance. Cook argues that inheri-
tance, while valuable, is a secondary and optional feature of objects.
fixed but hidden representation defined in module
The design of the Self language illustrates this point, providing code
SetModule1. All instances of SetModule1.IntSet reuse via delegation instead of inheritance [32]. Others agree that
have the same representation, and both Cook and inheritance is secondary to dynamic dispatch. For example, when
Reynolds point out that this has some advantages: the Kay discusses the six main ideas of Smalltalk, inheritance is not men-
tioned, but dynamic dispatch is (in the form of messaging) [18]. Like-
isSubsetOf operation can be defined in terms of the wise, Gamma et al. argue that a central principle of object-oriented
hidden representation, which can be asymptotically design is to “favor object composition over class inheritance,”[11]—
more efficient than implementing isSubsetOf in and note that composition typically leverages dynamic dispatch in
terms of contains, as must be done in a pure object- the setting of patterns. When discussing framework design, John-
son and Foote distinguish white-box frameworks based on inheri-
oriented implementation of the IntSet interface. This tance from black-box frameworks based only on dynamic dispatch,
efficiency difference can be critical in practice.7 and argue that “black-box relationships are an ideal towards which
a system should evolve” [16]. While acknowledging that inheritance
7 In practical object-oriented settings, the efficiency of binary opera- is a feature of many OO languages and may have significant value
tions can often be regained, aside from any cost associated with dis- in many designs, I will not consider it further, so as to focus on the
patching itself. This is done most elegantly through the use of multi- most important, and most unique, feature of objects.
very well have an internal representation that is incom- What I got from Simula was that you could now
patible with that of IntSetA. replace bindings and assignment with goals. The
Because each module hides the representation of the last thing you wanted any programmer to do is
ADT it defines, ADTs are also existential types. How- mess with internal state even if presented figu-
ever, these existential types are opened once, when the ratively. Instead, the objects should be presented
defining module is imported into the program, rather as sites of higher level behaviors more appropriate for
than on every invocation of an operation. Thus the dis- use as dynamic components. [18]
tinction between objects and ADTs can be thought of in
type theory as the difference between closed and open
Thus, while comparing objects to ADTs may be use-
existentials.
ful for making intellectual distinctions, Kay suggests
Discussion. Cook’s essay focuses on the technical and that the power of objects is not in representing data
theoretical differences between objects and ADTs. He structures, but in representing higher-level goals. The
highlights the tradeoff between the interoperability idea of goals suggests an analogy to planning in ar-
provided by objects and the shared representation pro- tificial intelligence: rather than express an algorithm
vided by ADTs. But due to the focus of his essay, the with even high-level state and assignment, it is bet-
larger consequences of the interoperability provided ter to express declarative goals and declarative rules
by objects are only briefly discussed. At this point a for achieving them, and rely on a search engine to
reader may be forgiven for asking, what is the big deal apply the rules in a way that accomplishes the goal.
about interoperation? After all, Cook quotes Liskov Object-oriented programming is not fully declarative,
making the following cogent argument: but Kay’s point is that the abstraction provided by a
method-based interface enables a lot of client code to
Although a program development support approach the declarative ideal.
system must store many implementations of When discussing his view of objects in Smalltalk,
a type..., allowing multiple implementations Kay writes of the “objects as server metaphor” in
within a single program seems less impor- which every “object would be a server offering ser-
tant. [22] vices” that are accessed via messages9 to the object [18].
Perhaps Liskov is right. Does it really matter In fact, Kay considers objects the “lesser idea” and
whether we have two different implementations of Set states that “the big idea is messaging.”10 On a techni-
in a program? Why don’t we just pick one that is effi- cal level, in Smalltalk messages are “a procedural in-
cient and has the features needed for the program? terface to data or behavior,” which is consistent with
As far as data abstraction goes, this defense of ADTs Cook’s definition, but again Kay de-emphasizes data
may be correct. To investigate why having multiple abstraction in favor of behavior and high-level goals.
implementations of an abstraction might be important This focus on goals also suggests that whereas ADTs
indeed, we must broaden our view and look beyond are focused on lower-level data representation and ma-
data abstraction. nipulation concerns, objects are focused more on ab-
stractions that are useful in high-level program orga-
2.2 Beyond Data Abstraction: Behavior, Messages, nization. Thus, in looking for the advantages of ob-
and Services jects, perhaps we ought not to focus on data abstrac-
Cook’s essay focuses primarily on data abstraction, be- tions for our examples. Instead of Reynolds’s proce-
cause he is comparing objects to ADTs and data ab- dural data structures, in the remainder of this essay I
straction is what abstract data types are intended to will generally use the term service abstractions, reflect-
do. However, his definition of objects is more gen- ing Kay’s view of objects as servers that provide ser-
eral: “...a value exporting a procedural interface to data vices to their clients. A service abstraction is, on a tech-
or behavior.” This reflects a broader view of object- nical level, the same form of abstraction as a procedu-
orientation, one that can be seen even more clearly in ral data structure, but it may be used to abstract any
OO’s origins in Simula and Smalltalk. Dahl and Ny- set of services, not just data structure manipulations.
gaard, for example, related object-oriented program- We could also simply use the term object, following
ming to simulation, saying that “a program execution Cook’s definition, but the term service abstraction will
is regarded as a physical model, simulating the behav-
ior of either a real or imaginary part of the world” [21]. 9 Note that messages in Smalltalk are synchronous method calls; they
While this quote focuses more on the purpose of OO
are not asynchronous or distributed in the sense of network mes-
rather than its mechanisms, a simulation nevertheless sages, although Kay derives substantial inspiration from network-
focuses on behavior more than data. Alan Kay under- based metaphors.
scores this point: 10 Alan Kay, email sent October 10, 1998, to [email protected]
remind us that we are focused specifically on the dy- intuition from the widget example that this might
namic dispatch feature of objects.11 take on increased importance in service abstractions,
Taking Smalltalk’s pioneering work in GUI libraries I now propose a candidate for the leverage provided
as an inspiration, we will explore the generalization to by object-oriented service abstractions in design:
service abstractions through the example of a widget:
The key design leverage provided by objects is the abil-
interface Widget { ity to define nontrivial abstractions that are modu-
Dimension getSize(); larly extensible, where instances of those extensions
Dimension getPreferredSize();
can interoperate in a first-class way.
void setSize(Dimension size);
void paint(Display display); Let me define the these terms with more care:
}
• Nontrivial abstraction. An interface that provides
While a widget certainly has data—its size, and
at least two essential services.
perhaps widget-specific data related to what the wid-
get is displaying—abstracting that data is not the pri- • Modular Extensibility. New implementations not
mary purpose of a widget. Rather, a widget’s pur- anticipated when the abstraction was designed can
pose is to abstract the behavior of a user interface el- be provided without changing the original abstrac-
ement. In the simple interface above, inspired by the tion.
ConstrainedVisual interface from Apache’s Pivot • First-class Interoperability. Clients can instantiate a
UI framework,12 the service abstraction captures the number of different implementations of an abstrac-
negotiation between a UI element and its container tion and manipulate those instances together in a
concerning how large the UI element should be, as well first-class way. First-class interoperability has three
as the goal of painting itself on a display device. facets:
More importantly, the interoperability advantages
of object-oriented service abstractions over ADTs Direct interoperation. If the abstraction defines
suddenly become more obvious with this example. a binary operation, the arguments to that oper-
While a framework such as Apache Pivot provides ation need not be instances of the same imple-
many widgets, the space of possible widgets is much mentation. This form of interoperation is analo-
larger, and so programmers using the framework will gous to gears that mesh; mathematically, it corre-
likely want to define their own, or even use wid- sponds to a fold operation.
gets developed by strangers.13 GUI frameworks pro- Uniform treatment. Clients can uniformly in-
vide facilities to recursively and dynamically com- voke operations on instances of different im-
pose atomic widgets into composite widgets, and ul- plementations, without distinguishing the par-
timately into a complete user interface. For example, a ticular implementations involved (e.g. by using
CompositeWidget might be defined as: a static type or an explicit typecase operation).
interface CompositeWidget extends Widget { This form of interoperation is analogous to balls
void addWidget(Widget chld, Position p); within a ball bearing, which may not touch each
} other directly but nevertheless must match each
other closely; mathematically, it corresponds to a
Here addWidget is a binary operation: Compos-
map operation.
iteWidget is a kind of Widget, and it must interoperate
with other kinds of widgets that are added to it. It is First-class manipulation. Instances of different
essential, in particular, that custom widgets written by implementations can be manipulated together as
programmers can take their place in a user interface to- first-class values. For example, it should be pos-
gether with widgets from the base framework, as well sible to store a collection of instances of differ-
as widgets written by strangers. ent implementations in a single data structure in-
stance, then dynamically select element(s) from
3. The Design Leverage of Objects the collection and invoke operations on them.
Based on Cook’s insight that different object-oriented
implementations of a set can interoperate, and the Discussion. The reason to consider only nontrivial ab-
11 e.g. as stated before, I am not considering inheritance—surely the
stractions is that if an abstraction has only one service,
one can use a function to abstract it. Functions are com-
question of whether inheritance contributes to the success of objects
is interesting, but it is out of scope for our current purposes. pletely ideal in such cases—but some abstractions that
12 http://pivot.apache.org/ at first appear to be simple turn out to be richer than ex-
13 we will see an example of this later when looking at the Microsoft pected in practice. Consider the Widget example: the
Office plugin ecosystem. most important function in the interface is probably
paint, and a trivial academic example might include above, the C++ compiler must know the precise im-
only that, leading to the mistaken impression that just plementation class of each iterator so that it can sup-
passing a first-class function around suffices to encap- port template code generation. This is a reasonable as-
sulate the widget abstraction. In reality, widgets must sumption in the typical modes of use of generic pro-
manage other concerns, such as their size, which re- gramming, but it is nevertheless a serious limitation
quires communication with both their container and in many other cases. For example, if we store differ-
their children. I have in fact already oversimplified: the ent kinds of iterators in a list, typical type systems lose
true interface on which the Widget example is based track of the particular implementation class of each it-
has nine methods, and adds the additional concern of erator, and so we cannot use pure generic program-
revealing the widget’s baseline.14 ming to invoke copy operations on them; we must fall
The definition of modular extension captures back on dynamic dispatch to make copies.
Meyer’s open-closed principle [24], which states that ab- Objects, on the other hand, are first-class values; we
stractions “should be open for extension, but closed can see this in Cook’s definition, which starts “objects
for modification.” It is particularly important when an are values....” We therefore characterize object-oriented
abstraction is designed by one organization, but ex- service abstractions as providing a first-class notion of
tended in an unanticipated15 way by another; in this interoperability. With service abstractions, one can use
case, the second organization may not be able to mod- multiple implementations of an abstraction together,
ify the original abstraction.16 even when instances of the abstractions are handled in
Reynolds originally suggested interoperability as a a first-class way.
benefit of procedural data structures [27], and Cook To illustrate first-class interoperation, consider a
points out that as a consequence, when using a pure scenario in which we build a composite widget that
object model, binary operations should work on differ- allows the user to select one of several visualizations,
ent implementations. This direct interoperability prop- which are swapped when the user clicks a button.
erty is critical in the Widget example, where the Here the choice of a visualization widget to go in-
CompositeWidget must be able to integrate widgets side the CompositeWidget is made dynamically, yet
defined by strangers. the composite widget interoperates with the visualiza-
It turns out that simple forms of interoperability tion widget in the sense that the latter is passed to the
can be supported through mechanisms other than ob- addChild method of the former.
jects, however. A notable example is generic program- I use the term first-class interoperation broadly, to
ming [25] as represented in the C++ Standard Template include not just invoking binary methods, but also the
Library (STL). For example, iterators in the STL can be general ability to operate uniformly on instances of
used to copy elements from one collection to another. multiple different implementations. For example, the
The copy operation is binary, accepting a source and CompositeWidget must store its child widgets to-
a destination iterator. Although iterators are C++ ob- gether in some kind of data structure. When the paint
jects, dynamic dispatch is not used to enable interop- method of CompositeWidget is invoked, it must iter-
eration of different iterator implementations. Instead, ate over the child widgets and invoke paint in turn
they are defined using C++ templates, which essen- on each one of them. Note that the implementation
tially generate a fresh version of the copy operation for of CompositeWidget.paint() must not rely on an
every pair of source and destination iterator types. explicit typecase to determine the implementation of
A key limitation of the interoperability provided by each child widget before invoking paint on the child;
generic programming mechanisms is that it is second- a typecase would enable the container to work with a
class, precluding the manipulation of iterators as truly fixed set of widget implementations, but in that case
first-class values. For instance, in the iterator example the unmodified container code could not work with
new widget implementations.
14 see http://pivot.apache.org/2.0.3/docs/api/org/
apache/pivot/wtk/ConstrainedVisual.html Alternatives to objects. Are there technical ap-
15 By unanticipated extension I mean an extension for which neither
proaches, besides the service abstraction technique
the extension’s code, nor the particular feature(s) being added by the used in objects, that can provide the design benefits de-
extension, were explicitly anticipated by the designer of the abstrac-
tion being extended. Of course, in order to design an extension point scribed above?
at all, the designer must have some idea of the class of features the I have already established that abstract data types
extension point is intended to support, but it is typically impractical do not provide the required interoperability for bi-
to enumerate all features that fall into that class. nary methods. In fact, even in the absence of binary
16 Such modifications may be literally impossible if the abstraction
methods, they fail the first-class interoperability test:
is distributed in binary form; or they may merely be infeasible in
practice because the second organization wishes to avoid modifying a data structure may be a list of IntSet1 or a list of
(and then maintaining) a component it did not develop IntSet2, but we cannot define a list that mixes in-
stances of the two types.17 ADTs are therefore not a As an example of such a technique, consider the fol-
solution.18 lowing Standard ML implementation of a Set service
A module is a similar kind of abstraction to an ob- abstraction:20
ject: both typically present a procedural interface to datatype IntSet = IntSet of {
the outside world, both encapsulate state, and both are contains : int -> bool,
typically given types (or module signatures) that per- isSubsetOf : IntSet -> bool
mit subtyping. To attain the expressiveness of objects, }
however, modules must be made first class, a property
rarely found in widely-used languages, but which is an fun makeSingletonSet(x:int) = IntSet {
ongoing topic of research [5]. I would consider a first- contains = fn(y:int) => (y = x),
class module system, such as that provided in recent isSubsetOf =
versions of OCaml, to provide service abstractions.19 fn(s:IntSet) =>
let
Haskell’s type classes [34] cannot directly express
val (IntSet srec) = s
service abstractions, but rather are similar to generic
val scontains = #contains(srec)
programming in their support for interoperation. The in
natural signature of a binary operation in a Haskell scontains(x)
type class requires both arguments to have the same end
type; thus, binary operations typed in this way can- }
not operate on two different implementations of a type
Here the IntSet object interface is defined as an
class. More fundamentally, different implementations
ML datatype consisting of a record with two fields.
of a type class cannot be manipulated together in a
Each field stores a function that implements a method:
first-class way, for example by putting them in the
same list. Achieving direct interoperability with type the contains field, for example, holds a function
that takes an int parameter and returns a bool re-
classes is possible, but requires more complexity in the
sult. The makeSingletonSet function creates a sin-
definition of the type class, so that binary operations
take two type arguments as well as two value argu- gleton set holding the single value x, passed as an ar-
gument to this “constructor.” The constructor returns
ments. In order to regain first-class manipulation—for
an instance of the IntSet datatype, with the “meth-
example to put different instances of different imple-
mentations of a type class into the same list—each in- ods” implemented appropriately to match the behav-
ior of a singleton set. contains simply holds a func-
stance must be wrapped in a datatype, creating an ex-
istential that stores the type class of each instance. The tion (introduced with the fn keyword) that compares
the method argument y to the single set element x.
use of such an encoding is inconvenient, but I would
isSubsetOf is slightly more complex. We must un-
consider it a use of service abstractions.
pack the IntSet datatype s to get at the record srec
Object encodings. Various techniques have been pro- inside. Then we can select the contains method us-
posed for encoding objects using functions [7, 19]. ing ML’s record selection operator, #. Finally, we can
Not just topics of theoretical study, these techniques implement isSubsetOf by checking if the other set
have been used to construct frameworks in an object- contains the singleton element x.
oriented style within non-OO languages. For example, The code above is more verbose than necessary in
the GTK+ framework is an object-oriented toolkit for order to make it more accessible to those not famil-
creating graphical user interfaces that is implemented iar with Standard ML. Using the pattern matching,
in C. I consider a use of these techniques to be uses of type inference, and currying facilities of Standard ML,
service abstractions. one can define makeSingletonSet much more suc-
cinctly as follows:
17 A language with union types could support heterogeneous lists,
fun makeSingletonSet x = IntSet {
but then we cannot use the sets when we get them out of the list contains = fn y => y = x,
without using a typecase operation isSubsetOf = fn IntSet S =>
18 Please note that I am not arguing against ADTs. There are good
#contains S x
reasons to support ADTs well in programming languages—for ex-
}
ample, the increased efficiency that ADTs provide when implement-
ing binary methods. I am only arguing that ADTs do not solve the Is this solution—or similar encodings [19] in
particular interoperability problem that service abstractions solve.
We will see, from a discussion of frameworks and ecosystems, that other languages—an adequate replacement for ob-
this problem is important in practice. jects? Clearly it is a service abstraction, and therefore
19 Some module import constructs could even be viewed as a simple realizes all the benefits that objects obtain from their
kind of inheritance—but as usual a detailed examination of this is
out of scope. 20 Thanks to Adam Chlipala for suggesting this encoding style.
service abstraction nature. On the other hand, ML does seminal paper on the criteria to be used in decompos-
not provide direct language support for service ab- ing systems into modules [26]. Parnas’s argument has
stractions, e.g. via class and method constructs; this become a pillar of software design: nearly all software
is instead an encoding, and that involves tradeoffs. In must change over time, so a software system should be
the example above, the drawbacks include some ver- decomposed in a way that hides (i.e. isolates) decisions
bosity and awkwardness, caused by the need to wrap that are likely to change. The implication is that when
and unwrap the IntSet datatype to get at the record change comes, it can be accommodated by providing
inside, and the encoding of methods by binding first- a new implementation of the abstraction captured by
class functions to fields. There are potential advantages the module’s interface.
too—for example, we can avoid some type annotations So extension is important for facilitating software
due to the type inference provided by Standard ML. evolution. However, is the interoperability of exten-
For programs that have only incidental need of ser- sions necessary in practice, beyond examples such as
vice abstractions, such encodings may be adequate or widgets?
even desirable. On the other hand, it is my anecdo-
tal observation that few object-oriented programmers 4.1 Software Frameworks
find such encodings acceptable. While the GObject en- To consider whether interoperation between extensions
coding used by GTK does have a significant user base, is commonly needed, let us turn our attention next to
it is painfully verbose—to the extent that the Vala21 software frameworks. A software framework is “the
language and the GObject Builder preprocessor22 were skeleton of an application that can be customized by
developed to allow GTK/GObject developers to write an application developer” [15]. This customization oc-
higher-level object-oriented code, which is then trans- curs when the developer “supplies it [the framework]
lated into C code compatible with GObject. This sug- with a set of components that provide the application
gests that direct language support for service abstrac- specific behavior” [16]. These components are imple-
tions is almost a requirement for programs that are ex- mentations of “abstract designs” defined by the frame-
pected to benefit significantly from their use. Let us work; thus frameworks inherently require extensible
now therefore look at what kind of software requires abstractions.
a significant use of service abstractions, and whether How do frameworks differ from more well-known
that class of software is important. approaches to reuse, such as libraries? While libraries
typically provide reusable primatives such as func-
4. The Importance of Interoperability tions and data structures, frameworks provide archi-
So far I have argued that objects provide a form of tectural reuse [10, 14, 15]: reuse of the overall design
extension in which extensions are interoperable, and of an application, along with code that realizes that de-
that this form of extension can be achieved in other sign. This reused code may include architecturally im-
technologies only with service abstractions that closely portant abstractions (typically interfaces), default im-
simulate the essence of objects. Does this matter? plementations of those abstractions, and glue code that
To answer this question, let us return to the idea that ties the abstractions together and allows them to com-
objects are focused on abstractions for high-level pro- municate. The architectural reuse provided by frame-
gram organization. This suggests that we study how works is inherently higher-order in nature, because the
extensibility and interoperability are used in high-level framework code invokes extensions provided by the
software design. We will first review the theory ex- application.23
plaining how modular extensibility can facilitate soft- The importance of frameworks. Why are frameworks
ware change. Second, we will look at how interopera- interesting to study? First, because the architectural
ble extensions are leveraged by software frameworks reuse they provide is unique and important, both in
in order to provide a higher-level form of reuse com- theory and in practice, and second, because as we will
pared to libraries. Third, we will look at how frame- see, many frameworks would not be possible without
works facilitate software ecosystems, which constitute the technical benefits provided by service abstractions.
some of the most high-value software we see today. Consider first the theoretical benefits of frameworks
Let us first consider the theory of how modular ex- in design. Frameworks support reuse at an architec-
tension facilitates software evolution. The need for a tural granularity, which is larger than classes:
software system to support new, unanticipated imple-
mentations of an abstraction was discussed in Parnas’s [Frameworks] provide a way of reusing code
21 https://wiki.gnome.org/Vala
that is resistant to more conventional reuse at-
22 http://www.jirka.org/gob.html – developed because 23 This is sometimes called the Hollywood principle: “don’t call us,
32 http://en.wikipedia.org/wiki/Object-oriented_
programming