Arguments and Results
James Noble
MRI, Scho ol of MPCE,
Macquarie University, Sydney.
Octob er 20, 1997
Abstract
If an ob ject oriented program is a collection of communicating ob jects, then the ob jects' pro-
to cols de ne the languages the program sp eaks. Unfortunately, proto cols are dicult to design
in isolation, so many programs' proto cols are not as well designed as they could b e. This pap er
presents six patterns which describ e how ob jects proto cols can b e designed or redesigned. By using
these patterns, programs and designs can b e made more simple, more general, and more easy to
change.
Intro duction
Ob ject's protocols, also knowasinterfaces, are very imp ortant in ob ject oriented design. An ob ject's
proto col is the face the ob ject presents to other ob jects surrounding it. Using an ob ject's proto col, other
ob jects in the program can use the ob ject as a server,thus accessing the b ehaviour the ob ject provides.
Similarly, an ob ject can act as a client to other ob jects, in turn using their proto cols to access their
services.
This pap er presents six patterns for designing ob ject oriented proto cols see Figure 1. The patterns
fo cus on two asp ects of proto col design | the messages ob jects can receive, and the results ob jects
return in resp onse to the messages. These patterns do not attempt to describ e novel techniques, rather,
they present well-established solutions for ob ject oriented design. These patterns should be useful
for intro ducing the techniques to novice programmers, and for more exp erienced programmers, should
illustrate when particular techniques are applicable and their relative strengths and weaknesses.
These patterns are interrelated, but they do not form a whole language. Rather, the patterns are
two fragments Patterns ab out Arguments and Patterns ab out Results whichmay one day form
part of a larger pattern language. Eachof the fragments has the same structure see Figure 2 with
one general pattern, and a couple of more sp eci c patterns which re ne the general pattern to handle
sp ecialised contexts. Figure 2 also illustrates two relationships between the patterns. One pattern
can re ne another pattern, meaning one pattern is a more sp eci c version of the other. Alternatively,
patterns can con ict, meaning that the patterns are mutually exclusive, each providing a di erent
solution to a similar problem [26].
Forces
Each of these patterns resolves a numb er of di erent forces, and some con icting patterns resolve similar
problems in di erentways. Many of the patterns consider the ease of reading or writing of a particular
solution | generally, solutions which are easy to write are more likely to b e chosen by programmers,
and solutions which are easy to read are likely to b e easier to maintain. Since smaller, simpler programs
are generally easier to read and write, the patterns are concerned with the complexity or size of a design,
suchasthe number of messages an ob ject understands, or the number of arguments needed by a message.
Since much complexity cannot b e avoided, the patterns prefer complexity to b e handled once in server
ob jects, rather than many times in every client ob ject which uses the servers. 1
Pattern Problem Solution
Arguments How can you simplify a complex proto col Make an Arguments Ob ject to capture the
Ob ject
that has a regular argument structure? common parts of the proto col.
Make a single message taking an ob ject
How can you simplify a proto col
Selector
representing the message selector as an ex-
where several messages di er mainly in
Ob ject
tra argument.
their names?
Curried How can you simplify an extremely com-
Send simpler messages to an intermediary
Ob ject plicated proto col?
which elab orates them within its context.
Result How can you manage a dicult answer to Make a Result Ob ject the whole answer to
Ob ject a dicult question? the question.
Future How can you answer a question while you Make a Future Ob ject which computers
Ob ject think ab out something else? the answer in parallel.
How can you answer a question that is
Lazy Make a Lazy Ob ject which can answer the
easy to answer now, but that may never
Ob ject
question later, if necessary.
b e asked?
Figure 1: Summary of the Patterns
Arguments Object Result Object
Selector Object Curried Object Future Object Lazy Object
Figure 2: The Structure of the Language
Several patterns address the cohesion and coupling of the resulting designs, as designs with high
cohesion within ob jects and low coupling b etween them are more exible, understandable, and easier
to maintain. This is often related to whether a concept is represented explicitly by a single ob ject in a
design, or whether it is implicit in the communication b etween several ob jects. Representing a concept
explicitly as an ob ject generally makes it easier to identify the concept within the design, to change the
implementation of the concept if necessary, and to reuse the concept elsewhere, esp ecially if the ob ject
represents a real concept from the program's application domain. The patterns are also concerned with
eciency | the time and space cost of a design, and the number of objects it requires at runtime.
Consequences
A common principle underlies all these patterns | that designs can often b e improved byintro ducing
nding additional ob jects from within the program. At rst, the newfound ob jects seem out of place
in the program, but as the program evolves, the found ob jects b ecome b etter integrated into the design,
and can b e recognised as mo delling concepts from the application domain.
Because they nd new ob jects, these patterns tend to generate designs with many small, simple
1
ob jects ,intro ducing an extra level of indirection, and imp osing space and time costs at runtime. All
these patterns simplify a design lo cally for example, bychanging one particular proto col but imp ose
global changes to the program b ecause extra ob jects are needed to implement the changed proto col.
As a result, although ob jects may b e easier to understand in isolation, the global design of the program
may b ecome confused. To quote Alan Perlis: In the long run every program becomes rococo | then
rubble. [20]. If these patterns are applied injudiciously they will accelerate this pro cess.
1
This is not limited solely to these patterns. Many other patterns have this e ect, including those in Design Patterns
[9] and Smal ltalk Best Practice Patterns [5], as do Parnas's criteria for program decomp osition [19]. 2
Form
The patterns are written in electric mo di ed Portland form. Each b egins with a question in italics de-
scribing a problem, followed by one paragraph describing the pattern's context, and a second describing
the forces the pattern resolves. A b oldface \Therefore:" intro duces a summary of the solution also
italicised followed by the a description of the solution in detail. Then follows an example of using the
pattern, the patterns consequences b ene ts rst, a b oldface But:, then the liabilities and nally some
known uses and related patterns.
Patterns ab out Proto cols
Ob jects communicate via proto cols | a program's proto cols are the glue that binds its ob jects together.
The following three patterns describ e how ob jects can b e found within proto cols.
1 Arguments Ob ject
How can you simplify a complex protocol that has a regular argument structure?
Some ob jects have large and complex proto cols with a regular internal structure. For example, a
graphical View ob ject will provide proto col for drawing manytyp es of ob jects in many di erentways,
but almost every message will take arguments which sp ecify the colour, stipple, and line thickness to
use when drawing. The same combinations of arguments may o ccur across many proto cols, and as a
result, many arguments may b e passed in parallel through many messages and across many ob jects.
Large proto cols are easy to use b ecause they o er a large amount of b ehaviour to their clients.
Unfortunately, they are often dicult or time consuming to implement, and for client programmers to
learn. Every client of a large proto col dep ends up on the proto col's ne details, such as the names and
arguments required by each message, and these dep endencies make large proto cols dicult to change.
Moreover, large proto cols are more likely to be changed than small proto cols | adding an eleventh
argument to a message with ten arguments is qualitatively quite di erent to adding a second argument
to a unary message. To quote Alan Perlis: If you have a procedure with 10 parameters, you probably
missed some [20].
Therefore: Make an Arguments Ob ject to capture the common parts of the protocol.
In its simplest form, an Arguments Ob ject should have one variable for each argument to be
eliminated from the proto col, and the usual messages to access and up date its variables. Change the
proto col and its implementations to accept a single Arguments Ob ject in place of the eliminated
arguments, and change the proto col's clients to create Arguments Ob jects as required. To supp ort
optional arguments, initialise the Arguments Ob ject's variables with default argumentvalues when
it is created.
Example
Consider the proto col provided by a graphical View ob ject:
drawRectangleFrom: topLeft to: b ottomRight colour: colour
llRectangleFrom: topLeft to: b ottomRight colour: colour
drawOvalFrom: topLeft to: b ottomRight colour: colour
These messages take a number of arguments in common: topLeft, b ottomRight and colour. An
Arguments Ob ject can eliminate these arguments from the proto col. The Arguments Ob ject
whichwe will call a Graphic uses three variables to replace the common arguments. Graphic's proto col
includes messages to create new Graphic ob jects, and to read and write these variables. The View's
proto col can b e changed to accept a single Graphic argument, rather than the three common arguments. 3 client view
drawRectangleFrom:to:colour:
fillRectangleFrom:to:colour:
drawOvalFrom:to:colour:
\Create a Graphic"
g := Graphic from: topLeft To: b ottomRight Colour: colour.
\Draw it"
view drawRectangle: g.
client graphic1 graphic2 graphic3 view
from:To:Colour:
drawRectangle: graphic1
from:To:Colour:
fillRectangle: graphic2
from:To:Colour:
drawOval: graphic3
Consequences
An Arguments Ob ject makes a tradeo b etween the size of a complex proto col M messages with
N common arguments versus M messages with N fewer arguments plus a new Argument Ob ject
which requires N arguments to create it. The resulting proto cols are usually easier to learn and to read.
An Arguments Ob ject decreases the coupling between ob jects involved in the proto col | ob jects
are coupled to the Arguments Ob ject ob ject, rather than to each other | so manychanges to the
proto col are limited to the Arguments Ob ject and those ob jects which fundamentally rely on the
changed proto col. Ideally,anArguments Ob ject will explicitly reveal an ob ject from the application
domain. But: Arguments Ob ject clients may be more dicult to write, as the programmer must
understand b oth the server's proto col and the Arguments Ob jects, and create the necessary Argu-
ments Ob jects as appropriate. As with all these patterns, this pattern intro duces an additional ob ject
into the design, requiring mo di cations to the program and increasing runtime space and time costs.
Known Uses
MacApp uses Event ob jects to package the arguments sent to widgets in resp onse to user actions [24].
The X Window System's drawing op erations use GraphicsContexts to package up a large number of
arguments such as the font, colour, line width, and clip region [22]. Smalltalk's Point and Rectangle
ob jects can b e seen as Arguments Ob jects which package up two or four integer arguments to describ e
p oints or rectangles [4]. Smalltalk also uses Message ob jects which record the arguments and name of
a message which has caused an error [10]. 4
Related Patterns
The following two patterns describ e how Arguments Ob ject can b e applied in particular situations.
The numb er of message names in a proto col can b e reduced by using a Selector Ob ject 2. Constant
or slowly-varying arguments can be factored out by a Curried Ob ject 3, which intro duces an
intermediary ob ject to elab orate a proto col.
2 Selector Ob ject
How can you simplify a protocol where several messages di er mainly in their names?
Some proto cols include several messages which p erform the same underlying function. For example,
a graphical View ob ject provides many messages which draw graphical ob jects. These messages take
substantially the same arguments and di er in the ne details of the precise function they p erform |
in the case of the View, whether to draw a rectangle, a lled rectangle, or an oval.
Proto cols where many messages p erform similar functions are often dicult to learn and to use,
esp ecially as the similarity is often not obvious from the proto col's do cumentation. Because the messages
are conceptually closely related, they will often need to b e maintained as a group, which will require
changing a numb er of metho d implementations in servers and many di erent message sends in clients.
Therefore: Make a single message taking an object representing the message selector as an extra
argument.
Remove the similar messages from the proto col, and replace then with a single message which takes
the Selector Ob ject as an additional argument. This message should p erform the essential function
p erformed by the messages from the original proto col, and use the Selector Ob ject argument to
discriminate b etween the functions in detail typically using multimetho ds or double dispatching [9].
Change the proto col's clients and servers to use the new proto col.
In some cases, the Selector Ob ject can be a very lightweight ob ject, such as a symbol or enu-
meration, which is used only to determine the ne details of the function to be p erformed. In other
cases, the Selector Ob ject can have substantial state and b ehaviour of its own. If you already have
an Arguments Ob ject, the Selector Ob ject can b e often b e folded into it, resulting in a Message
Ob ject.
Example
Consider the proto col provided by a graphical View ob ject, which uses a Graphic Arguments Ob ject
as describ ed ab ove.
drawRectangle: aGraphic
llRectangle: aGraphic
drawOval: aGraphic
Each of these three messages p erforms essentially the same function | drawing on a View. The
details of the function whether to draw a rectangle outline, a lled rectangle, or an oval are enco ded
in the message selector. In this example, we have an Arguments Ob ject the Graphic, so we can
apply the Selector Ob ject pattern to incorp orate the message selector into the Arguments Ob ject.
Graphic can b e extended to record a typ e, which selects either outlined rectangles, lled rectangles, or
ovals to b e drawn. View's proto col now contains only a single message, draw, mo delling the one essential
function of the whole proto col.
\Create a Graphic"
g := Graphic
typ e: rectangle from: topLeft
to: b ottomRight colour: colour.
\Draw it"
view draw: g. 5
As an alternative, a family of Graphic sub class can b e used, rather than the typ e argument.
graphic := RectangleGraphic
from: 10@10 to: 20@20 colour: red.
view draw: graphic.
client rectangle filledRectangle oval view
from:To:Colour:
draw: rectangle
from:To:Colour:
draw: filledRectangle
from:To:Colour:
draw: oval
Consequences
The Selector Ob ject pattern is a re nementofArguments Ob ject 1, and its b ene ts and liabilities
are similar. The tradeo is slightly di erent|Selector Ob ject trades o N similar messages at the
server for 1 message with an extra argument plus the Selector Ob ject and its creation message. When
this factorisation results in Selector Ob jects which have meaning in the domain, the proto col will
be smaller and easier to mo dify, and also easier to learn and to use. But: clients need to create the
Selector Ob ject, and servers need some mechanism to select the actual function the message will
p erform.
Known Uses
Selector Ob jects are often used to build ob ject oriented interfaces to existing le or graphics systems.
For example, VisualWorks uses symb ols representing le access mo des as arguments to messages to
manage les [18]. Many OO graphics systems, again including VisualWorks, provide Geometric or
Graphic ob jects which combine the Selector Ob ject and Arguments Ob ject 1 patterns.
Related Patterns
Lightweight Selector Ob jects can often b e Flyweights [9].
3 Curried Ob ject
How can you simplify an extremely complicatedprotocol?
Over the course of a program, ob jects exchange messages, and the ob jects passed as arguments to
these messages are usually di erentevery time. Sometimes, an ob ject will receive a series of messages
where one or more arguments are constant. For example, a text editor will often draw a number of
di erent strings in exactly the same font size, typ eface, and colour. Arguments may also be sent in
sequence, so that the argument to one message can b e predicted from the corresp onding argumentofa
previous message | the text editor will draw the strings with the same left margin, but each o set one
line lower on the screen.
These kinds of arguments increase the complexity of a proto col. The proto col will be dicult to
learn, as programmers must work out which arguments must be changed, and which must remain 6
constant. This information is not explicitly represented in the proto col, and often not provided by
standard do cumentation. The proto col will b e dicult to use, as clients must cache constant arguments
between sends and compute the values of slowly-varying arguments.
Therefore: Send simpler messages to an intermediary a Curried Ob ject which elaborates them
within its context.
A Curried Ob ject stores the constantorslowly varying arguments from the original proto col, and
provides a simpler proto col with these arguments eliminated. A Curried Ob ject stores the original
server ob ject, and forwards messages to this ob ject, passing along the stored arguments and up dating
the slowly varying arguments.
To use a Curried Ob ject,change clients so that rather than sending messages to the server, they
create a curried ob ject, initialise it as required, and send messages to it. Proto col can b e added to the
server for creating and initialising a Curried Ob ject which refers to that server. The original proto col
can remain publicly available in the server, or it can b e restricted to the Curried Ob ject.
Example
Consider drawing lines of text on a graphical view:
font := Font named: Times .
o set := 0 @ font textHeight.
view drawString: This is an example at: origin font: font.
view drawString: to illustrate at: origin + o set font: font.
view drawString: the problem at: origin + o set 2 font: font.
client view
drawString:at:font:
drawString:at:font:
drawString:at:font:
The drawString:At:Font message takes three arguments. The rst argument, the string to draw, is
di erent for each message sent; the second argument, the p oint at which to draw the string, varies
according to an arithmetic progression; and the third argument, the font to use, is constant.
This proto col can b e simpli ed byintro ducing a Curried Ob ject. The Curried Ob ject whichwe
will call a Pen requires three variables to hold the View server ob ject, and the origin and font arguments
of the drawString:At:Font message. Pen's proto col will include messages to read and write these variables,
and a single argument message drawString to draw a string and advance to the next line up dating the
origin variable. The View ob ject needs a single argument message pen which returns a new Pen ob ject
asso ciated with the View. Using a Pen, the example ab ove b ecomes:
p en := view p en at: origin font: font named: Times .
p en drawString: This is an example .
p en drawString: to illustrate .
p en drawString: curried objects . 7 client pen view
pen new
at:font:
drawString: drawString:at:font:
drawString: drawString:at:font:
drawString:
drawString:at:font:
Consequences
Curried Ob ject is quite similar to Arguments Ob ject 1, and shares most of the b ene ts and
liabilities of that pattern, however, it requires fewer changes to existing servers. But: Curried Ob ject
displaces the receiver of the proto col, while Arguments Ob ject 1 do es not. Curried Ob ject thus
intro duces action at a distance, b ecause messages sent to one ob ject the Curried Ob ject are actually
executed by another the original server ob ject. A Curried Ob ject is at the same level of abstraction
as its server, and acts as an alias for the server. Programmers need to know ab out b oth the original
server and the Curried Ob ject, and understand the distinctions b etween them, in particular, which
messages to send to which ob ject.
This pattern is called Curried Object b ecause the underlying mechanism is partial function applica-
tion, collo quially known as currying after the mathematician Haskell B. Curry [12]. The name Curried
Object also suggests that this pattern is a little spicy and exotic, and probably not for the b eginner.
Known Uses
Iterators are the most common kind of Curried Ob ject, as they are used in many common languages
and class libraries [9, 10, 6]. An iterator's server is a collection ob ject, and the iterator maintains a
slowly varying index into the collection. Many graphics systems use Curried Ob jects whose servers
are views, as in the example ab ove. For example, VisualWorks uses GraphicsContext ob jects [18] and
Smalltalk/V uses Pen ob jects [15]. VisualWorks also includes MessageSend ob jects, a curried version of
the Message Arguments Ob ject 1. MessageSend inherits from Message, and adds an extra variable
to store the message's receiver, allowing a message to sent without an explicit reference to the ultimate
receiver ob ject.
Related Patterns
Arguments Ob ject 1 can provide a less radical alternative to Curried Ob ject. The original
server can act as an Abstract Factory [9] to create the Curried Ob ject. A Curried Ob ject can b e
similar to an ob ject-level Adaptor [9], but where an adaptor allows an ob ject to conform to an existing
proto col, a Curried Ob ject intro duces a new, simpler proto col. The Accumulator [25] pattern is
a variant of Curried Ob ject which simpli es the proto col used to create ob jects. The Typ e-Safe
Session pattern is a Curried Ob ject which emphasises typ e safety [21].
Patterns ab out Results
Many messages ask questions of the ob jects to which they are sent, and the results of these messages
are the answers to these questions. The following three patterns describ e how ob jects can simplify the
asking and answering of questions. 8
4 Result Ob ject
How can you store and manage a dicult answer to a dicult question?
You have a long or imp ortant computation p erformed by a server ob ject, and you wish to retain
the results of the computation. Perhaps the computation returns more than one ob ject, or the result
is needed at several times or places throughout the program, or you need to keep information ab out
how the result was obtained. For example, consider a MetricCalculator for a programming environment
that calculates software metrics for a system under development. Calculating the metrics is a long
computation and needs to return values for a numb er of di erent metrics. The programming environment
needs to keep the values for the di erent metrics together, and to store the values to track the evolution
of the system over time.
The client ob ject could cache the results itself, but this increases the client's complexity, as the
resulting caching co de will obscure the main application logic, making it dicult to read and mo dify.
Alternatively, the server ob ject could cache and store the results, but this has similar problems, in that
the caching co de p ollutes the implementation of the domain computation. This also complicates the
server's proto col, since it must return b oth previous and current results.
Therefore: Make a Result Ob ject the whole answer to the question.
Make one variable in the Result Ob ject for eachvalue to b e returned, and provide the usual accessor
and initialisation messages | if additional information ab out the result is required, store this in the
Result Ob ject also. Provide the usual accessor messages so that this information can be retrieved
from the Result Ob ject. Mo dify the server to create and return a Result Ob ject, and the server's
clients to retrieve the results from the Result Ob ject.
Example
Consider a MetricCalculator ob ject for calculating software metrics:
m := MetricCalculatorfor: anObject.
m computeSizeOfInterface.
m computeNumb erOfInheritedMetho ds. m computeNumb erOfOverriddenMetho ds.
Client MetricCalculator
computeSizeOfInterface
computeNumberOfInheritedMethods
computeNumberOfOverriddenMethods
The various compute messages traverse the target ob ject's inheritance hierarchy and compute metrics.
The hierarchy is traversed whenever an individual metric is required, and rep eated if the metric is needed
again. Since each metric requires exactly the same traversal of the inheritance hierarchy, this is really
a single computation returning multiple results | the various di erent metrics.
This proto col can b e improved byintro ducing a Result Ob ject. All the metrics can b e calculated
in one traversal, and a Result Ob ject called a MetricRep ort returned. Individual metric values can
b e retrieved from the MetricRep ort. The MetricRep ort ob ject can also store ancillary information ab out 9
the metric calculation, such as the date the metrics were calculated. Using a MetricRep ort, the ab ove
example b ecomes:
metricRep ort := MetricCalculatorfor: anObject computeMetrics.
metricRep ort sizeOfInterface.
metricRep ort numb erOfInheritedMetho ds.
metricRep ort numb erOfOverriddenMetho ds.
Client MetricReport MetricCalculator
computeMetrics new
sizeOfInterface
numberOfInheritedMethods
numberOfOverriddenMethods
Consequences
A Result Ob ject is quite likea Curried Ob ject 3 and shares many of the b ene ts and liabilities of
that pattern, except that a Curried Ob ject 3 substitutes for a message's receiver, while a Result
Ob ject substitutes for a message's result. A Result Ob ject trades the server's proto col size for extra
ob jects | M messages to the server are replaced by 1 message to return a Result Ob ject plus M
messages to retrieve the result values | the resulting proto cols are usually easier to learn and to read,
and with reduced coupling, are easier to change. Result Ob ject is particularly p owerful when the new
Result Ob ject corresp onds to a concept from the domain. But: for the client ob ject programmer,
Result Ob jects are more dicult to use than server-side caching, b ecause the client needs to extract
the actual results from the Result Ob ject. For the server ob ject programmer, they similarly require
more work than client-side caching.
Known Uses
The VisualWorks Date class returns a Result Ob ject called TimeStamp to package together the
current date and time. As well as simplifying client co de, this also avoids the problems whichwould
o ccur if the time was returned at one second b efore midnight, and the date one second afterwards. Martin
Fowler discusses similar Result Ob jects called TimePoints [8]. An exp ert system used in Telecoms
capacity planning used a Result Ob ject to package the decisions it returned with the logic supp orting
the decisions. The system's users could check the supp orting logic to verify that the decisions were
b eing made appropriately. The Self Programmer's Reference Manual describ es how Result Ob jects
can b e used in Self to return multiple values from messages [1].
Result Ob jects are often used to provide error handling resulting in Error Ob jects. Represent-
ing errors with Result Ob jects allows the errors to b e queued as they o ccur, and displayed later to the
user. These Result Ob jects can also provide textual descriptions of the errors, and appropriate help
information. For example, VisualWorks includes SystemError ob jects, Result Ob jects which package
together return co des and identifying arguments from errors o ccurring outside the system [18]. 10
Related Patterns
If the question can b e answered in parallel, try Future Ob ject 5. If the question can b e answered
easily now, but the answer may never b e needed, try Lazy Ob ject 6.
5 Future Ob ject
How can you answer a question while you think about something else?
Sometimes you need to ask a question, then do something else while waiting for the answer to
arrive. For example, a programming environment may need to resp ond to its user interface while a
MetricCalculator computes the metrics for the latest release. In these cases, the computation's result
must b e returned to the program eventually, but it is not needed immediately. If the computation can
b e p erformed indep endently from the rest of the program | that is, if the computation do es not mo dify
ob jects which the rest of the program dep ends up on, and vice versa | it should b e p ossible to compute
the result in a parallel thread.
Unfortunately, managing parallel threads is quite dicult in practice. Because the computation's
result is eventually required by the program, the thread cannot be started in parallel and left to its
own devices. Rather, the result must be returned to the program when the computation nishes. If
the server starts the parallel computation, then either the server or the computation's clients must
extract the result from the thread. This will increase the complexity of the ob ject chosen to have this
resp onsibility, and reduces cohesion by contaminating it with pro cess management issues. In practice,
programmers often adopt the simplest solution, ignoring the issue and computing the result immedi-
ately, delaying the program's execution until the computation is complete, consequently reducing the
program's resp onsiveness and p erformance.
Therefore: Make a Future Ob ject which computes the answer in paral lel.
A Future Ob ject is a Result Ob ject 4 which computes an answer in a parallel thread, based
on initial information supplied by the original server [11]. The Future Ob ject should receive the
computation's arguments from the server, and then cache any information whichmaychange after the
main computation resumes. The Future Ob ject should handle the thread management | creating a
new thread to p erform the computation, and extracting the results when the thread completes. The
Future Ob ject should also provide synchronisation | clients which access the Future Ob ject while
its asso ciated thread is running should b e blo cked until the thread completes.
The Future Ob ject can also be used to control the thread p erforming the computation. This
control can b e direct | the Future Ob ject can provide an interface to control the thread, or indirect
|ifthe Future Ob ject is deleted b efore its computation completes, the unneeded computation can
also b e deleted.
Example
Consider the metricRep ort example from the Result Ob ject 4 pattern. A Future Ob ject could
implement the metricRep ort with exactly the same interface, but with a di erent p erformance pro le.
Using a Result Ob ject, the program will wait while the computation is p erformed. Using a Future
Ob ject, the computation will b e p erformed in a parallel thread started by the computeMetrics message,
and the program will wait for this thread when it accesses the metricRep ort Future Ob ject | in the
diagram, when the sizeOfInterface message is sent. If the creation of the Future Ob ject and its rst
access are suciently separated, the metrics computation will not delay the main thread.
Consequences
A Future Ob ject proto col is exactly the same as a Result Ob ject 4, and so has similar b ene ts
of increased readability and decoupling, and decreased complexity. In addition, a Future Ob ject sep-
arates concurrency issues from clients' and servers' domain co de, so the implementation of concurrency
is easier to change. But: b ecause a Future Ob ject must manage the concurrency, it will have a larger
overhead than a standard Result Ob ject. A Future Ob ject will also b e more dicult to write than a 11 Client MetricReport MetricCalculator
computeMetrics new
sizeOfInterface
numberOfInheritedMethods
numberOfOverriddenMethods
Result Ob ject, although some languages are suciently exible that a single generic Future Ob ject
can b e written once and reused as necessary [7]. A Future Ob ject cannot avoid the intrinsic problems
imp osed by concurrency: the program's p erformance will b ecome less predictable, and harder to debug
[16]. Also, this pattern should b e applied only when the parallel computation is indep endent of the rest
of the program.
Known Uses
Future Ob jects are quite common in parallel and distributed computing. They were intro duced in
Multilisp [11] and have b een used in Smalltalk [7] and Mushroom [13] amongst many other systems
[16].
Related Patterns
Future Ob ject has b een describ ed brie y as part of the Active Ob ject pattern [23]. A Future
Ob ject can b e seen as a Proxy [9] for an ob ject which hasn't b een computed yet.
6 Lazy Ob ject
How can you answer a question that is easy to answer now, but that may never be asked?
Some computations can b est b e p erformed immediately but the computation's result may never b e
needed. For example, the data needed by the MetricCalculator may only b e accessible for the current
version of the software b eing develop ed, but it is unlikely that the user would want metrics calculated for
every intermediate version. Often this kind of computation dep ends on information whichisavailable
now, but may not b e available in the future.
The simplest solution to this problem is for the client to ask the question every time, and then store
the results until they are needed. If most of the results are not needed, this will cause a large amountof
unneeded computation, and also complicate the client's co de, making it harder to write. Alternatively,
the server ob ject answering the question could compute and cache all the results, with a similar problems
of eciency and increased server complexity. The client could p ostp one asking the question until the
answer is required, but, when the question is asked, the information the answer dep ends up on maybe
lost.
Therefore: Make a Lazy Ob ject which can answer the question later, if necessary.
A Lazy Ob ject is a Result Ob ject 4 which do es not start its computation until the answer is
requested. The laziness is managed within the Lazy Ob ject, rather than by the clients or server. A
server ob ject can initialise and return a Lazy Ob ject in exactly the same wayitwould return a Result
Ob ject. The server should pass the computation's arguments to the Lazy Ob ject, which should also
cache any information whichmaychange b etween the time it is created and the time it is used. When 12
it is accessed, the Lazy Ob ject cannot return the result of the computation, b ecause the computation
has not yet b een carried out. Rather, the rst time the Lazy Ob ject is used, it should p erform the
computation and cache the results. Future requests can b e serviced from the cache.
Example
Consider again the metrics calculator example from Result Ob ject 4. A Lazy Ob ject could be
used as the metricRep ort,changing the p erformance characteristics but not the interface. Using a Lazy
Ob ject, the metrics computation will b e p erformed when the rst metric is requested | in the example,
when the sizeOfInterface message is sent. If the result is never needed, the Lazy Ob ject can b e deleted
or garbage collected, and the metrics will never b e calculated.
Client MetricReport MetricCalculator
computeMetrics new
sizeOfInterface
numberOfInheritedMethods
numberOfOverriddenMethods
Consequences
A Lazy Ob ject is a re nement of a Result Ob ject, and shares the b ene ts and liabilities of that
pattern. In addition, a Lazy Ob ject avoids the overhead of unnecessary computations by calculating
only results that are actually required. Since a Lazy Ob ject's own proto col is exactly the same as that
of a corresp onding Result Ob ject, the choice to use or not use lazy evaluation can b e completely
encapsulated from any client ob jects. Similarly, b ecause the Lazy Ob ject manages the evaluation
itself, the server is mostly insulated from the details of the laziness. But: these gains in eciency
must b e traded o against the need to identify and cache information which the computation dep ends
up on and which mightbechanged by the rest of the program, and to ensure the computation when
eventually p erformed do es not itself have side e ects on the rest of the program. A Lazy Ob ject may
make program p erformance dicult to predict, and the program dicult to debug, b ecause it is not
easy to determine when or if the calculation is actually carried out.
The Result Ob ject 4, Future Ob ject 5, and Lazy Ob ject 6 patterns are distinguished
by when the computation is started, and when the result is returned to the main thread. A Result
Ob ject starts the computation and returns the result as so on as it is created, a Future Ob ject starts
a computation as so on as it is created, but returns the result when it is rst accessed, and a Lazy
Ob ject b oth starts the computation and returns the result when it is rst accessed.
Known Uses
The mushroom system implements a generic Lazy Ob ject [13]. The LOOM virtual memory system for
Smalltalk used Lazy Ob jects called leaves to represent ob jects whichwere swapp ed out into secondary
storage [14]. Design Patterns describ es how ET++ uses Lazy Ob jects called virtual proxies to represent
large images whichmay not need to b e displayed [9].
Related Patterns
Ken Auer and Kent Beckhave describ ed many similar patterns for optimising Smalltalk programs [2]. 13
Acknowledgements
These patterns are revised versions of some patterns from the Found Objects pattern language [17 ], and were
inspired by discussions on the patterns-discussion mailing list and the WikiWikiWeb. In particular, Kent Beck
describ ed Parameters Object [4 ] and suggested Result Object [3 ]. Patrick Logan noticed the similaritybetween
these two patterns, David C. Laurence provided the Telecoms example for Result Ob ject and Mike Koss
describ ed the use of Result Ob jects to handle errors.
Authors and reviewers at the EuroPLOP'96 and PLOP'97 writers workshop provided many p ertinent com-
ments and suggestions. Lorraine Bo dy, Linda Rising, and Charles Weir provided detailed comments on the
conference draft, as did David Holmes back at MRI and a numb er of anonymous reviewers. Shepherds Ward
Cunningham and Paul Dyson provided many imp ortant suggestions regarding the pap er's form and content.
References
[1] Ole Agesen, Lars Bak, Craig Chamb ers, Bay-Wei Chang, Urs Holzle, John Maloney, Randall B. Smith,
David Ungar, and Mario Wolczko. The Self Programmer's Reference Manual. Sun Microsystems and
Stanford University, 4.0 edition, 1995.
[2] Ken Auer and Kent Beck. Lazy optimization: Patterns for ecient smalltalk programming. In Pattern
Languages of Program Design,volume 2. Addison-Wesley, 1996.
[3] Kent Beck. Result ob ject. http://c2.com/cgi/wiki?ResultO bject .
[4] Kent Beck. Parameters ob ject. Email message sent to the patterns-digest list, March 1995.
[5] Kent Beck. Smal ltalk Best Practice Patterns. Prentice-Hall, 1996.
[6] Grady Bo o ch. Object OrientedAnalysis and Design with Applications. Benjamin Cummings, second edition,
1994.
[7] Brian Fo ote and Ralph E. Johnston. Re ective facilities in Smalltalk-80. In OOPSLA Proceedings, 1989.
[8] Martin Fowler. Analysis Patterns. Addison-Wesley, 1997.
[9] Erich Gamma, Richard Helm, Ralph E. Johnson, and John Vlissides. Design Patterns. Addison-Wesley,
1994.
[10] Adele Goldb erg and David Robson. Smal ltalk-80: The Language and its Implementation. Addison-Wesley,
1983.
[11] Rob ert H. Halstead, Jr. Multilisp: A language for concurrent symb olic computation. ACM Transactions
on Programming Languages and Systems, 74:501{538, Octob er 1985.
[12] Martin C. Henson. Elements of Functional Programming Languages. Blackwell Scienti c, 1987.
[13] Trevor P. Hopkins and Mario Wolczko. Writing concurrent ob ject-oriented programs using Smalltalk-80.
The Computer Journal, 324, Octob er 1989.
[14] Ted Kaehler and Glenn Krasner. LOOM{large ob ject-oriented memory for Smalltalk-80 systems. In Glenn
Krasner, editor, Smal ltalk-80: Bits of History, Words of Advice,chapter 14. aw, 1983.
[15] Wilf Lalonde. Discovering Smal ltalk. Benjamin/Cummings, 1994.
[16] Doug Lea. Concurrent Programming in Java. Addison-Wesley, 1997.
[17] James Noble. Found ob jects, 1996. Reviewed at EuroPLOP.
[18] ParcPlace Systems. VisualWorks Smal ltalk User's Guide, 2.0 edition, 1994.
[19] David Lorge Parnas, Paul C. Clements, and David M. Weiss. The mo dular structure of complex systems.
IEEE Transactions on Software Engineering, 113, March 1985.
[20] Alan Perlis. Epigrams on programming. ACM SIGPLAN Notices, 179, Septemb er 1982.
[21] Nat Pryce. Typ e-safe session. In EuroPLOP'97 Proceedings, 1997.
[22] Rob ert W. Schei er and Jim Gettys. The X Window System. ACM Transactions on Graphics, 52, April
1986.
[23] Douglas C. Schmidt and Charles D. Cranor. Active ob ject: An ob ject b ehavioral pattern for concurrent
programming. In Pattern Languages of Program Design,volume 2. Addison-Wesley, 1997.
[24] Kurt Schmucker. MacApp: an application framework. Byte, 118, 1986.
[25] Phillip M. Yelland. Creating host compliance in a p ortable framework: A study in the use of existing design
patterns. In OOPSLA Proceedings, 1996.
[26] Walter Zimmer. Relationships b etween design patterns. In Pattern Languages of Program Design. Addison-
Wesley, 1994. 14