SlideShare a Scribd company logo
84 Java™
Report | DECEMBER 2000 http://www.javareport.com
T
HERE IS A common myth that design can and
should be independent of implementation de-
tail, where design is commonly treated as an
abstract concept and implementation as its
concrete realization in code.*
If we accept that “design
is a creational and intentional act: conception of a struc-
ture on purpose for a purpose,”1
then a structure can-
not be fit for a purpose if it does not account for, and
work with, its context. The context includes the target
platform—language, tools, libraries, middleware, etc.—
along with its functional and nonfunctional properties.
We would not think it reasonable to design a
house without knowing
the lay of the land, or a sky-
scraper without knowing
the materials that could be
used. The idea that we can
treat concepts such as
threading and distribution
as mere coding detail is a
sure fire way to waste a lot
of energy (and time, money,
etc.) in big, up-front design
only to discover that the
difference between theory
and practice is bigger in practice than in theory. While
there are certainly cases when parts of a high-level de-
sign can be invariant across different technologies, it is
more often the case that we need to close the loop, al-
lowing (even encouraging) knowledge of detail and
practice to influence and inform the system’s structure.
The role of patterns is to capture such architectur-
al knowledge. They can map—prospectively or retro-
spectively—a design and its rationale, narrating from
problem to solution, accounting for context, capturing
the forces at work and the resulting consequences.
Here, I focus on two patterns—Command-Query Sep-
aration and Combined Method—for allocating re-
sponsibility to methods in a class interface, examining
how they interact and react to the context of concur-
rent and distributed vs. sequential and local execution.
InterfaceDesign. In the general sense of the word, an
interface represents a boundary between different sys-
tems or parts of a system. In software, an interface rep-
resents a partition that separates intent from
realization, conceptual from concrete, and user from
author. In Java, there are many interface concepts: the
public section of a class represents an interface of
methods and classes to all other potential users, its
protected section an interface to its subclasses and its
surrounding package, and so on. An interface repre-
sents the promise of functionality realized in a sepa-
rate class; a package has a publicly usable section; and
reflection is a different mechanism for offering and us-
ing an object’s methods interface.
Constraints and Affordances. Taking the user-ver-
sus-author perspective, an interface also establishes
and names an intended model of usage. The methods
offered in a class interface are intended for use in a par-
ticular way. It is these constraints that the class author
aims to present and enforce—at compile time through
the type system and at runtime through exceptions or
return values. The simplest example of this is the com-
monly understood meaning of encapsulation: Privacy
of representation ensures that the class user manipu-
lates information and behavior only through the pub-
lic method interface of a class.
There is, however, more to encapsulation than just
keeping data private. Encapsulation refers more gen-
erally to self-containment in design. A class that re-
quires you to know a great deal about how and when
to call which methods (e.g., “when calling this method
followed by that method in a threaded environment
you must synchronize the object explicitly”) is not as
encapsulated as one that fully contains and hides such
issues (e.g., “this method is thread-safe”). The former
design is weaker. It suffers design leakage, with many
of its constraints implied but not strictly enforced. This
puts the onus on the class user rather than the class
supplier to do the work in fulfilling the design, and is,
inevitably, tedious and error prone.
Kevlin Henney is an independent consultant and trainer
KevlinHenney / kevlin@curbralan.com
Patterns in Java
A tale of two patterns
*
Although in common currency, whether these definitions are
actually valid and useful is another matter: It is the subject of
much debate and probably another article!
85http://www.javareport.com DECEMBER 2000 | Java™
Report
In this light, affordances describe possible as opposed
to intended uses2
:
The term affordance refers to the perceived and ac-
tual properties of the thing, primarily those funda-
mental properties that determine just how the thing
could possibly be used. A chair affords (“is for”) sup-
port and, therefore, affords sitting. A chair can also
be carried. Glass is for seeing through, and for break-
ing ... Affordances provide strong clues to the oper-
ations of things. Plates are for pushing. Knobs are for
turning. Slots are for inserting things into. Balls are
for throwing or bouncing. When affordances are tak-
en advantage of, the user knows what to do just by
looking: no picture, label, or instruction is required.
Complex things may require explanation, but simple
things should not. When simple things need pic-
tures, labels, or instructions, the design has failed.
One of the class designer’s responsibilities is to reduce the
gap between constraints and affordances in the interface,
matching intended and actual degrees of freedom, mini-
mizing the scope for incorrect usage.
Context-Sensitive Design. Separating execution of a
method in space or time—e.g., threads, remote method calls,
or message-queued requests—can have a profound effect on
the correctness and effectiveness of a design. The conse-
quences of such separation cannot be papered over and ig-
nored: concurrency introduces nondeterminism and context
switching costs; distribution introduces concurrency and
method calls that are subject to failure and escalated round-
trip costs. These are design issues, not tweaks and bugs to
be mopped up later.
In each case, one of the consequences is to discourage
property-style programming—where an interface predom-
inantly comprises get and set methods, each corresponding
directly to a private field. Such classes are barely (meaning
both only just and naked) encapsulated. Field accessors in
an interface are often uninformative: They fail to commu-
nicate, simplify, or abstract the use of an object, leading to
verbose and often error-prone user code. Property-style pro-
gramming is not a great practice at the best times. Concur-
rency and distribution amplify these basic stylistic and
practical problems by introducing subtle correctness issues
and serious performance overheads.
TransparencyandBugblatterBeasts.Abstraction allows
us to ignore details as necessary, so that our design-think-
ing balances contextual forces rather than is swamped by
them. The challenge is in knowing what details are or are
not necessary. The problem†
arises when the details ignored
are actually necessary.
Design often strives to make contextual forces as trans-
parent as is reasonably and practically possible. Trans-
parency can, however, become a seductive idea: Perhaps it
is possible to make threading or remote object communica-
tion completely transparent, so that the user is unaware of
them when communicating with an object? The Proxy pat-
tern3
supports a degree of transparency for remote commu-
nication. It underpins the programming model of both RMI
and CORBA. The use of a local, surrogate object sporting the
same interface as a remote object and responsible for the bit-
bashing detail of marshaling and unmarshaling allows the
caller to use a familiar method call model. However, such
distribution transparency is not complete and it is not the
same as the absence of distribution: The effects, such as call
failure and latency, cannot be hidden fully and must still be
considered.4
Transparency is not a towel.‡
Command-Query Separation
Ensure that a method is clearly either a command or a
query.
Problem. Methods can have query characteristics, where
they return a value in response to a question, and command
characteristics, where they carry out an imperative action to
change the state of an object. A method may therefore be
Kevlin Henney / Patterns in Java
†
Note that some people treat the words problem and challenge as syn-
onyms. They are not. Anyone who believes they are is probably trying
to sell you something. History, if rewritten in this style, would sound
quite different: “Houston, we have a challenge.”
‡
“A towel ... is about the most massively useful thing an interstellar
hitchhiker can have ... [You can] wrap it round your head to ... avoid the
gaze of the Ravenous Bugblatter Beast of Traal (a mindbogglingly stu-
pid animal, it assumes that you can’t see it, it can’t see you—daft as a
brush, but very very ravenous)”.5
classified as a pure query, a pure command (or modifier), or
a hybrid of both.
For example, in java.util.Iterator, hasNext can be seen to
be a query, remove a command, and next an awkward mar-
riage of both query and command:
public interface Iterator
{
boolean hasNext();
Object next();
void remove();
}
It is not possible to query an Iterator object as to its cur-
rent value without causing it to advance to the next val-
ue. This leads to a mismatch with the structure of a for
loop, where initialization, continuation, access, and ad-
vancement are separated for clarity, defining the signature
of a loop:
for(initialization; continuation condition; advance)
{
... access for use ...
}
The result of combining query and command responsibili-
ty in the same method is often less clear. It can obstruct as-
sertion-based programming6,7
and typically requires
additional variables for retaining query results:
for(Iterator iterator = collection.iterator();
iterator.hasNext();)
{
Object current = iterator.next();
... use current...
... again use current...
}
Solution. Ensure that each method has strictly either com-
mand behavior or query behavior, so that methods return-
ing values are pure functions without side effects and
methods with side effects do not have return values. “An-
other way to express this informally is to state that asking
a question should not change the answer.”7
The combined modifier–query style is common in C,
C++, and Java, but this does not automatically make it de-
sirable. In sequential programming, segregation of roles can
make the effect of code clearer. Concentrating on the es-
sential—rather than optional—characteristics of iteration,
the standard Iterator interface could be refined by apply-
ing Command-Query Separation:
public interface Iterator
{
boolean hasCurrent();
Object getCurrent();
void next();
}
Pure query methods return the same results under the
same conditions. Assuming no modifications from other
threads or command methods, a query can be called mul-
tiple times without requiring extra variables to hold snap-
shots of query results:
for(Iterator iterator = collection.iterator();
iterator.hasCurrent();
iterator.next())
{
... use iterator.getCurrent()...
... again use iterator.getCurrent()...
}
In this case, the divorcing of roles is a happy one. The role
of each method is clearer and more cohesive. You can refac-
tor a piece of code to separate query and command roles
with the Separate Query From Modifier refactoring8
: “You
have a method that returns a value but also changes the state
of an object. Create two methods, one for the query and one
for the modification.”
Command-Query Separation better supports assertion-
based programming. It can, however, encourage property-
style programming if the convenient use of a class is not
considered. This is a stylistic problem that becomes a prac-
tical problem in the presence of threads, requiring explicit
external synchronization by the object user. Different
queries that are commonly used together can be combined
together to encapsulate the synchronization. Similarly, mul-
tiple commands can also be grouped as Combined Meth-
ods. In the presence of distribution, this also resolves the
cost of accumulated round trips. However, if there are com-
mands and queries that must be performed as a synchro-
nized group, the user is once again faced with the problem
of synchronization. This is a problem that cannot always
be correctly resolved by a synchronized block—e.g., where
the user is calling, knowingly or unknowingly, a Proxy ob-
ject rather than the actual target object.
Combined Method
Combine methods that are commonly used together to guar-
antee correctness and improve efficiency in threaded and
distributed environments.
Problem. Interfaces that offer predominantly fine-grained
methods can, at first, appear minimal and cohesive—both
desirable properties. However, during use it emerges that
some of these interfaces are primitive without being cohe-
sive. They are simplistic rather than simple, forcing the class
user to work harder to achieve common tasks and navigate
any subtle ordering dependencies (temporal coupling) that
exist between methods. This is both tedious and error prone,
leading to code duplication—the main smell to be avoided
in code8
—and offering new and exciting opportunities for
bug breeding.
A sequence of methods that must be performed success-
fully together sees problems in execution when confronted
by exceptions, threading, or distribution. If two actions,
commonly performed together, must follow commit-or-roll-
back semantics—they must both be completed successfully
or the effect of the first one must be rolled back if the second
fails—and both are expressed as separate methods, clean up
falls to (or on) the class user rather than the class supplier.
The introduction of threading makes things even less de-
terministic: A sequence of method calls on a mutable object
86 Java™
Report | DECEMBER 2000 http://www.javareport.com
Patterns in Java / Kevlin Henney
87http://www.javareport.com DECEMBER 2000 | Java™
Report
is not guaranteed to have the desired outcome if that object
is shared across threads, even assuming that each individ-
ual method is thread-safe. Consider the following interface
to an event source that allows handlers to be installed and
queried for particular events:
interface EventSource
{
Handler getHandler(Event event);
void installHandler(Event event, Handler newHandler);
...
}
Interleaved calls from other threads can lead to surprising
behavior. Assuming that the source field refers to an object
shared between threads, it is possible that a different han-
dler will be installed by another thread between statements
1 and 2:
class EventSourceExample
{
...
public void example(Event event, Handler newHandler)
{
oldHandler = eventSource.getHandler(event); // 1
eventSource.installHandler(event, newHandler); // 2
}
private EventSource eventSource;
private Handler oldHandler;
}
Again, it is the consumer rather than the supplier that pays
the cost of constraint preservation:
class EventSourceExample
{
...
public void example(Event event, Handler newHandler)
{
synchronized(eventSource)
{
oldHandler = eventSource.getHandler(event);
eventSource.installHandler(event, newHandler);
}
}
private EventSource eventSource;
private Handler oldHandler;
}
If the target object is remote, the additional overhead of
round-trip costs and the liability of method-call failure join
concurrency as part of the context. In the previous exam-
ple, we can assume that the time to execute the body of each
method is miniscule, by orders of magnitude, when com-
pared to the latency of the communication there and back.
This cost is paid twice in the example, and many more
times in other examples.
There is a further problem with required use of an external
synchronized block that is more obvious in a distributed ex-
ample but applies equally well in local threaded examples:
the use of proxy objects between the caller and the target. In
short, the use of synchronized blocks fails because the proxy
rather than the target is synchronized. It would be an under-
statement to say that this can have a rather fundamental im-
pact on the correctness of a system. Because the use of proxy
is transparent behind an interface (given an interface to an ob-
ject, how can you be sure that you are talking to the target di-
rectly, i.e., the use of custom or JDK 1.3 dynamic proxies?),
there is little the caller can do to guarantee good behavior.
Solution. Combine methods that must be executed togeth-
er coherently in the event of failure, threading, and distri-
bution. The combination should reflect common use. Thus,
a Combined Method may be clearer than a more primitive
set of methods because it reflects directly the intended use.
Recovery strategies and awkward usage can be encapsulat-
ed within a Combined Method, simplifying the interface
from the class user’s perspective. This improved encapsu-
lation reduces unwanted affordances in the interface. The
overall effect of Combined Method is to support a more
transaction-like style of method design than is traditional.
It is often reasonable to provide query methods hand-in-
hand with a combined command-query. However, this
should be done on an as-needed basis rather than as a force
of habit, otherwise the interface can grow without restraint
or reason. Providing separated command methods is less
often required because a combined command-query can
play that role: The caller simply ignores the result. If re-
turning an unused result incurs a cost—e.g., it is marshaled
across the wire—it may then become reasonable to provide
a separated command method.
Returning to the previous example, the design becomes
simpler and more self-contained if the installHandler method
returns the previous handler:
class EventSourceExample
{
...
public void example(Event event, Handler newHandler)
{
oldHandler =
eventSource.installHandler(event, newHandler);
}
private EventSource eventSource;
private Handler oldHandler;
}
The caller has been offered a safer interface and no longer
has to account for threading. This reduces the risk as well
as the size of the code, placing responsibility for class de-
sign fully with the class designer rather than the class user.
The presence of Proxy objects does nothing to affect the cor-
rectness of usage.
A Combined Method may be a combined set of queries, a
combined set of commands, or a combination of both. Thus,
it may complement or contradict Command-Query Separa-
tion. When there is conflict between the two practices, Com-
bined Method should be applied in preference where it
would make a difference in correctness and usability.
As another example, consider the case of acquiring a re-
source if it is available and continuing with something else
if it is not. Assume, in the following interface, that the ac-
quire method blocks until the resource becomes available:
interface Resource
Kevlin Henney / Patterns in Java
{
boolean isAcquired();
void acquire();
void release();
...
}
Something like the following usage code has been recom-
mended as appropriate for a threaded system6
:
class ResourceExample
{
...
public void example()
{
boolean acquired = true;
synchronized(resource)
{
if(!resource.isAcquired())
resource.acquire();
else
acquired = false;
}
if(!acquired)
...
}
private Resource resource;
}
However, even leaving aside issues of readability and us-
ability, this design is an unsuitable application of Command-
Query Separation. It fails if we introduce a Proxy arrangement:
class ActualResource implements Resource {...}
class ResourceProxy implements Resource {...}
A Combined Method resolves the issues, making the pres-
ence of concurrency and indirection more transparent:
interface Resource
{
...
boolean tryAcquire();
...
}
The following is clearly simpler as well as correct (and is
arguably, for those reasons alone, the more tasteful design):
class ResourceExample
{
...
public void example()
{
if(!resource.tryAcquire())
...
}
private Resource resource;
}
A consequence of Combined Method is that it can make
some testing and assertion-based programming practices
more awkward, where both command and query roles are
combined. However, design by contract, in its original form,
is not always an appropriate practice when reentrancy,
threading, and distribution are also features of the design.
Unit-testing approaches can provide the appropriate separa-
tion and level of confidence in these situations. Combined
Method does not significantly complicate unit testing. If ap-
plied without consideration for usage, Combined Method
can make a method interface less clear and the user’s code
longer and clumsier. In some cases, Execute Around Method9
offers an alternative to Combined Method that can ensure
atomicity and flexibility.
Conclusion
Whether or not a particular practice is appropriate can be
heavily dependent on the context and if it is possible or
practical to make the forces arising in that context trans-
parent. In the case of Java’s threading model, the oft-con-
sidered good habit of using Command-Query Separation can
become a poor design practice. For this reason, although
Command-Query Separation was articulated originally as a
principle,7
it is in truth a pattern: A principle is a general
or universal truth; a pattern offers specific advice on how to
build something, and its applicability is context-dependent.
The Combined Method pattern can reinforce Command-
Query Separation, but in some cases it is clear that the two
patterns are in tension. While both are focused on class in-
terface design, the forces at work in each pattern are not the
same, nor is their context of applicability. Command-Query
Separation is driven by requirements of testability, com-
prehensibility, primitiveness, etc. and is applicable with-
out risk in local, single-threaded contexts. Combined
Method is driven by correctness in concurrent and distrib-
uted environments and the desire to encapsulate rather than
leak nontransparent details.
Does the combination of command methods and query
methods produce a less pure design for concurrent and dis-
tributed systems than for sequential ones? The answer in
part hinges on what you mean by purity. Looked at anoth-
er way, a design using method combination resolves more
design forces than one not using them, resulting in a design
that is fitter for purpose and more encapsulated than the al-
ternative. If pure means clean, then this is more—rather
than less—pure. Context determines practice. s
References
1. Henney, K., “Design: Concepts and Practices,” keynote at
JaCC Conference, Sept. 1999, available via www.cur-
bralan.com and www.accu.org.
2. Norman, D., The Design of Everyday Things, paperback
edition, Basic Books, 1988.
3. Gamma, E. et al., Design Patterns: Elements of Reusable
Object-Oriented Software, Addison–Wesley, 1995.
4. Waldo, J. et al., “A Note on Distributed Computing,” Sun
Microsystems Laboratories, Nov. 1994, www.sun.com/
research/techrep/1994/abstract-29.html.
5. Adams, D., The Hitchhiker’s Guide to the Galaxy, Pan,
1979.
6. Mannion, M., “Concurrent Contracts: Design by Contract™
and Concurrency in Java,” Java Report, Vol. 4, No. 5, May
1999, pp. 51–66.
7. Meyer, B., Object-Oriented Software Construction, 2nd
edi-
tion, Prentice Hall, 1997.
8. Fowler, M., Refactoring: Improving the Design of Existing
Code, Addison–Wesley, 1999.
9. Beck, K., Smalltalk Best Practice Patterns, Prentice Hall,
1997.
88 Java™
Report | DECEMBER 2000 http://www.javareport.com
Patterns in Java / Kevlin Henney

More Related Content

PPT
JAVA design patterns and Basic OOp concepts
PDF
Bussolon, Betti: Conceptualize once, design anywhere
PDF
The Grammar of User Experience
PPTX
Behavioral pattern By:-Priyanka Pradhan
PDF
Basic design pattern interview questions
PDF
Semi-Automated Assistance for Conceiving Chatbots
PDF
Meetup 22/2/2018 - Artificiële Intelligentie & Human Resources
PDF
Aspect Oriented Programming
JAVA design patterns and Basic OOp concepts
Bussolon, Betti: Conceptualize once, design anywhere
The Grammar of User Experience
Behavioral pattern By:-Priyanka Pradhan
Basic design pattern interview questions
Semi-Automated Assistance for Conceiving Chatbots
Meetup 22/2/2018 - Artificiële Intelligentie & Human Resources
Aspect Oriented Programming

What's hot (10)

PDF
FinalReport
PDF
Pattern-based competence management
PDF
Simulation of Imperative Animatronics for Mobile Video Games
PDF
Usenix04
PPTX
GoF Design patterns I: Introduction + Structural Patterns
PDF
Formalizing Message Exchange Patterns using BPEL light
PPT
Meaningful Interaction Analysis
PPT
Software Architecture and Project Management module III : PATTERN OF ENTERPRISE
PDF
Machine Learning for Efficient Neighbor Selection in ...
PDF
081016 Social Tagging, Online Communication, and Peircean Semiotics
FinalReport
Pattern-based competence management
Simulation of Imperative Animatronics for Mobile Video Games
Usenix04
GoF Design patterns I: Introduction + Structural Patterns
Formalizing Message Exchange Patterns using BPEL light
Meaningful Interaction Analysis
Software Architecture and Project Management module III : PATTERN OF ENTERPRISE
Machine Learning for Efficient Neighbor Selection in ...
081016 Social Tagging, Online Communication, and Peircean Semiotics
Ad

Similar to A Tale of Two Patterns (20)

PDF
A laboratory for teaching object oriented thinking
PPTX
Design patterns
PDF
Oos Short Q N
PPTX
SAD05 - Encapsulation
PDF
The Perfect Couple
DOCX
Design Pattern Notes: Nagpur University
PDF
Bt8901 objective oriented systems1
PPTX
Advance oops concepts
PDF
Top 30 Technical interview questions
PDF
Another Tale of Two Patterns
PPT
Basic Java Concept - Practical Oriented Methodologies
PPTX
Software Patterns
DOCX
A Survey of Object Oriented Programming LanguagesMaya Hris.docx
PPT
Multilayered paper prototyping for user concept modeling
PDF
software-architecture-patterns
PDF
Software architecture-patterns
PDF
Software arquitectura patron diseño
A laboratory for teaching object oriented thinking
Design patterns
Oos Short Q N
SAD05 - Encapsulation
The Perfect Couple
Design Pattern Notes: Nagpur University
Bt8901 objective oriented systems1
Advance oops concepts
Top 30 Technical interview questions
Another Tale of Two Patterns
Basic Java Concept - Practical Oriented Methodologies
Software Patterns
A Survey of Object Oriented Programming LanguagesMaya Hris.docx
Multilayered paper prototyping for user concept modeling
software-architecture-patterns
Software architecture-patterns
Software arquitectura patron diseño
Ad

More from Kevlin Henney (20)

PDF
Program with GUTs
PDF
The Case for Technical Excellence
PDF
Empirical Development
PDF
Lambda? You Keep Using that Letter
PDF
Lambda? You Keep Using that Letter
PDF
Solid Deconstruction
PDF
Get Kata
PDF
Procedural Programming: It’s Back? It Never Went Away
PDF
Structure and Interpretation of Test Cases
PDF
Agility ≠ Speed
PDF
Refactoring to Immutability
PDF
Old Is the New New
PDF
Turning Development Outside-In
PDF
Giving Code a Good Name
PDF
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
PDF
Thinking Outside the Synchronisation Quadrant
PDF
Code as Risk
PDF
Software Is Details
PDF
Game of Sprints
PDF
Good Code
Program with GUTs
The Case for Technical Excellence
Empirical Development
Lambda? You Keep Using that Letter
Lambda? You Keep Using that Letter
Solid Deconstruction
Get Kata
Procedural Programming: It’s Back? It Never Went Away
Structure and Interpretation of Test Cases
Agility ≠ Speed
Refactoring to Immutability
Old Is the New New
Turning Development Outside-In
Giving Code a Good Name
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
Thinking Outside the Synchronisation Quadrant
Code as Risk
Software Is Details
Game of Sprints
Good Code

Recently uploaded (20)

PDF
Which alternative to Crystal Reports is best for small or large businesses.pdf
PDF
Odoo Companies in India – Driving Business Transformation.pdf
PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
PDF
Softaken Excel to vCard Converter Software.pdf
PPTX
Introduction to Artificial Intelligence
PDF
Wondershare Filmora 15 Crack With Activation Key [2025
PPTX
CHAPTER 2 - PM Management and IT Context
PPT
Introduction Database Management System for Course Database
PDF
System and Network Administration Chapter 2
PDF
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
PDF
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PPTX
L1 - Introduction to python Backend.pptx
PDF
Digital Systems & Binary Numbers (comprehensive )
PPTX
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
PDF
PTS Company Brochure 2025 (1).pdf.......
PDF
wealthsignaloriginal-com-DS-text-... (1).pdf
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
Which alternative to Crystal Reports is best for small or large businesses.pdf
Odoo Companies in India – Driving Business Transformation.pdf
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
Softaken Excel to vCard Converter Software.pdf
Introduction to Artificial Intelligence
Wondershare Filmora 15 Crack With Activation Key [2025
CHAPTER 2 - PM Management and IT Context
Introduction Database Management System for Course Database
System and Network Administration Chapter 2
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
Upgrade and Innovation Strategies for SAP ERP Customers
L1 - Introduction to python Backend.pptx
Digital Systems & Binary Numbers (comprehensive )
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
How to Migrate SBCGlobal Email to Yahoo Easily
PTS Company Brochure 2025 (1).pdf.......
wealthsignaloriginal-com-DS-text-... (1).pdf
Adobe Illustrator 28.6 Crack My Vision of Vector Design

A Tale of Two Patterns

  • 1. 84 Java™ Report | DECEMBER 2000 http://www.javareport.com T HERE IS A common myth that design can and should be independent of implementation de- tail, where design is commonly treated as an abstract concept and implementation as its concrete realization in code.* If we accept that “design is a creational and intentional act: conception of a struc- ture on purpose for a purpose,”1 then a structure can- not be fit for a purpose if it does not account for, and work with, its context. The context includes the target platform—language, tools, libraries, middleware, etc.— along with its functional and nonfunctional properties. We would not think it reasonable to design a house without knowing the lay of the land, or a sky- scraper without knowing the materials that could be used. The idea that we can treat concepts such as threading and distribution as mere coding detail is a sure fire way to waste a lot of energy (and time, money, etc.) in big, up-front design only to discover that the difference between theory and practice is bigger in practice than in theory. While there are certainly cases when parts of a high-level de- sign can be invariant across different technologies, it is more often the case that we need to close the loop, al- lowing (even encouraging) knowledge of detail and practice to influence and inform the system’s structure. The role of patterns is to capture such architectur- al knowledge. They can map—prospectively or retro- spectively—a design and its rationale, narrating from problem to solution, accounting for context, capturing the forces at work and the resulting consequences. Here, I focus on two patterns—Command-Query Sep- aration and Combined Method—for allocating re- sponsibility to methods in a class interface, examining how they interact and react to the context of concur- rent and distributed vs. sequential and local execution. InterfaceDesign. In the general sense of the word, an interface represents a boundary between different sys- tems or parts of a system. In software, an interface rep- resents a partition that separates intent from realization, conceptual from concrete, and user from author. In Java, there are many interface concepts: the public section of a class represents an interface of methods and classes to all other potential users, its protected section an interface to its subclasses and its surrounding package, and so on. An interface repre- sents the promise of functionality realized in a sepa- rate class; a package has a publicly usable section; and reflection is a different mechanism for offering and us- ing an object’s methods interface. Constraints and Affordances. Taking the user-ver- sus-author perspective, an interface also establishes and names an intended model of usage. The methods offered in a class interface are intended for use in a par- ticular way. It is these constraints that the class author aims to present and enforce—at compile time through the type system and at runtime through exceptions or return values. The simplest example of this is the com- monly understood meaning of encapsulation: Privacy of representation ensures that the class user manipu- lates information and behavior only through the pub- lic method interface of a class. There is, however, more to encapsulation than just keeping data private. Encapsulation refers more gen- erally to self-containment in design. A class that re- quires you to know a great deal about how and when to call which methods (e.g., “when calling this method followed by that method in a threaded environment you must synchronize the object explicitly”) is not as encapsulated as one that fully contains and hides such issues (e.g., “this method is thread-safe”). The former design is weaker. It suffers design leakage, with many of its constraints implied but not strictly enforced. This puts the onus on the class user rather than the class supplier to do the work in fulfilling the design, and is, inevitably, tedious and error prone. Kevlin Henney is an independent consultant and trainer KevlinHenney / kevlin@curbralan.com Patterns in Java A tale of two patterns * Although in common currency, whether these definitions are actually valid and useful is another matter: It is the subject of much debate and probably another article!
  • 2. 85http://www.javareport.com DECEMBER 2000 | Java™ Report In this light, affordances describe possible as opposed to intended uses2 : The term affordance refers to the perceived and ac- tual properties of the thing, primarily those funda- mental properties that determine just how the thing could possibly be used. A chair affords (“is for”) sup- port and, therefore, affords sitting. A chair can also be carried. Glass is for seeing through, and for break- ing ... Affordances provide strong clues to the oper- ations of things. Plates are for pushing. Knobs are for turning. Slots are for inserting things into. Balls are for throwing or bouncing. When affordances are tak- en advantage of, the user knows what to do just by looking: no picture, label, or instruction is required. Complex things may require explanation, but simple things should not. When simple things need pic- tures, labels, or instructions, the design has failed. One of the class designer’s responsibilities is to reduce the gap between constraints and affordances in the interface, matching intended and actual degrees of freedom, mini- mizing the scope for incorrect usage. Context-Sensitive Design. Separating execution of a method in space or time—e.g., threads, remote method calls, or message-queued requests—can have a profound effect on the correctness and effectiveness of a design. The conse- quences of such separation cannot be papered over and ig- nored: concurrency introduces nondeterminism and context switching costs; distribution introduces concurrency and method calls that are subject to failure and escalated round- trip costs. These are design issues, not tweaks and bugs to be mopped up later. In each case, one of the consequences is to discourage property-style programming—where an interface predom- inantly comprises get and set methods, each corresponding directly to a private field. Such classes are barely (meaning both only just and naked) encapsulated. Field accessors in an interface are often uninformative: They fail to commu- nicate, simplify, or abstract the use of an object, leading to verbose and often error-prone user code. Property-style pro- gramming is not a great practice at the best times. Concur- rency and distribution amplify these basic stylistic and practical problems by introducing subtle correctness issues and serious performance overheads. TransparencyandBugblatterBeasts.Abstraction allows us to ignore details as necessary, so that our design-think- ing balances contextual forces rather than is swamped by them. The challenge is in knowing what details are or are not necessary. The problem† arises when the details ignored are actually necessary. Design often strives to make contextual forces as trans- parent as is reasonably and practically possible. Trans- parency can, however, become a seductive idea: Perhaps it is possible to make threading or remote object communica- tion completely transparent, so that the user is unaware of them when communicating with an object? The Proxy pat- tern3 supports a degree of transparency for remote commu- nication. It underpins the programming model of both RMI and CORBA. The use of a local, surrogate object sporting the same interface as a remote object and responsible for the bit- bashing detail of marshaling and unmarshaling allows the caller to use a familiar method call model. However, such distribution transparency is not complete and it is not the same as the absence of distribution: The effects, such as call failure and latency, cannot be hidden fully and must still be considered.4 Transparency is not a towel.‡ Command-Query Separation Ensure that a method is clearly either a command or a query. Problem. Methods can have query characteristics, where they return a value in response to a question, and command characteristics, where they carry out an imperative action to change the state of an object. A method may therefore be Kevlin Henney / Patterns in Java † Note that some people treat the words problem and challenge as syn- onyms. They are not. Anyone who believes they are is probably trying to sell you something. History, if rewritten in this style, would sound quite different: “Houston, we have a challenge.” ‡ “A towel ... is about the most massively useful thing an interstellar hitchhiker can have ... [You can] wrap it round your head to ... avoid the gaze of the Ravenous Bugblatter Beast of Traal (a mindbogglingly stu- pid animal, it assumes that you can’t see it, it can’t see you—daft as a brush, but very very ravenous)”.5
  • 3. classified as a pure query, a pure command (or modifier), or a hybrid of both. For example, in java.util.Iterator, hasNext can be seen to be a query, remove a command, and next an awkward mar- riage of both query and command: public interface Iterator { boolean hasNext(); Object next(); void remove(); } It is not possible to query an Iterator object as to its cur- rent value without causing it to advance to the next val- ue. This leads to a mismatch with the structure of a for loop, where initialization, continuation, access, and ad- vancement are separated for clarity, defining the signature of a loop: for(initialization; continuation condition; advance) { ... access for use ... } The result of combining query and command responsibili- ty in the same method is often less clear. It can obstruct as- sertion-based programming6,7 and typically requires additional variables for retaining query results: for(Iterator iterator = collection.iterator(); iterator.hasNext();) { Object current = iterator.next(); ... use current... ... again use current... } Solution. Ensure that each method has strictly either com- mand behavior or query behavior, so that methods return- ing values are pure functions without side effects and methods with side effects do not have return values. “An- other way to express this informally is to state that asking a question should not change the answer.”7 The combined modifier–query style is common in C, C++, and Java, but this does not automatically make it de- sirable. In sequential programming, segregation of roles can make the effect of code clearer. Concentrating on the es- sential—rather than optional—characteristics of iteration, the standard Iterator interface could be refined by apply- ing Command-Query Separation: public interface Iterator { boolean hasCurrent(); Object getCurrent(); void next(); } Pure query methods return the same results under the same conditions. Assuming no modifications from other threads or command methods, a query can be called mul- tiple times without requiring extra variables to hold snap- shots of query results: for(Iterator iterator = collection.iterator(); iterator.hasCurrent(); iterator.next()) { ... use iterator.getCurrent()... ... again use iterator.getCurrent()... } In this case, the divorcing of roles is a happy one. The role of each method is clearer and more cohesive. You can refac- tor a piece of code to separate query and command roles with the Separate Query From Modifier refactoring8 : “You have a method that returns a value but also changes the state of an object. Create two methods, one for the query and one for the modification.” Command-Query Separation better supports assertion- based programming. It can, however, encourage property- style programming if the convenient use of a class is not considered. This is a stylistic problem that becomes a prac- tical problem in the presence of threads, requiring explicit external synchronization by the object user. Different queries that are commonly used together can be combined together to encapsulate the synchronization. Similarly, mul- tiple commands can also be grouped as Combined Meth- ods. In the presence of distribution, this also resolves the cost of accumulated round trips. However, if there are com- mands and queries that must be performed as a synchro- nized group, the user is once again faced with the problem of synchronization. This is a problem that cannot always be correctly resolved by a synchronized block—e.g., where the user is calling, knowingly or unknowingly, a Proxy ob- ject rather than the actual target object. Combined Method Combine methods that are commonly used together to guar- antee correctness and improve efficiency in threaded and distributed environments. Problem. Interfaces that offer predominantly fine-grained methods can, at first, appear minimal and cohesive—both desirable properties. However, during use it emerges that some of these interfaces are primitive without being cohe- sive. They are simplistic rather than simple, forcing the class user to work harder to achieve common tasks and navigate any subtle ordering dependencies (temporal coupling) that exist between methods. This is both tedious and error prone, leading to code duplication—the main smell to be avoided in code8 —and offering new and exciting opportunities for bug breeding. A sequence of methods that must be performed success- fully together sees problems in execution when confronted by exceptions, threading, or distribution. If two actions, commonly performed together, must follow commit-or-roll- back semantics—they must both be completed successfully or the effect of the first one must be rolled back if the second fails—and both are expressed as separate methods, clean up falls to (or on) the class user rather than the class supplier. The introduction of threading makes things even less de- terministic: A sequence of method calls on a mutable object 86 Java™ Report | DECEMBER 2000 http://www.javareport.com Patterns in Java / Kevlin Henney
  • 4. 87http://www.javareport.com DECEMBER 2000 | Java™ Report is not guaranteed to have the desired outcome if that object is shared across threads, even assuming that each individ- ual method is thread-safe. Consider the following interface to an event source that allows handlers to be installed and queried for particular events: interface EventSource { Handler getHandler(Event event); void installHandler(Event event, Handler newHandler); ... } Interleaved calls from other threads can lead to surprising behavior. Assuming that the source field refers to an object shared between threads, it is possible that a different han- dler will be installed by another thread between statements 1 and 2: class EventSourceExample { ... public void example(Event event, Handler newHandler) { oldHandler = eventSource.getHandler(event); // 1 eventSource.installHandler(event, newHandler); // 2 } private EventSource eventSource; private Handler oldHandler; } Again, it is the consumer rather than the supplier that pays the cost of constraint preservation: class EventSourceExample { ... public void example(Event event, Handler newHandler) { synchronized(eventSource) { oldHandler = eventSource.getHandler(event); eventSource.installHandler(event, newHandler); } } private EventSource eventSource; private Handler oldHandler; } If the target object is remote, the additional overhead of round-trip costs and the liability of method-call failure join concurrency as part of the context. In the previous exam- ple, we can assume that the time to execute the body of each method is miniscule, by orders of magnitude, when com- pared to the latency of the communication there and back. This cost is paid twice in the example, and many more times in other examples. There is a further problem with required use of an external synchronized block that is more obvious in a distributed ex- ample but applies equally well in local threaded examples: the use of proxy objects between the caller and the target. In short, the use of synchronized blocks fails because the proxy rather than the target is synchronized. It would be an under- statement to say that this can have a rather fundamental im- pact on the correctness of a system. Because the use of proxy is transparent behind an interface (given an interface to an ob- ject, how can you be sure that you are talking to the target di- rectly, i.e., the use of custom or JDK 1.3 dynamic proxies?), there is little the caller can do to guarantee good behavior. Solution. Combine methods that must be executed togeth- er coherently in the event of failure, threading, and distri- bution. The combination should reflect common use. Thus, a Combined Method may be clearer than a more primitive set of methods because it reflects directly the intended use. Recovery strategies and awkward usage can be encapsulat- ed within a Combined Method, simplifying the interface from the class user’s perspective. This improved encapsu- lation reduces unwanted affordances in the interface. The overall effect of Combined Method is to support a more transaction-like style of method design than is traditional. It is often reasonable to provide query methods hand-in- hand with a combined command-query. However, this should be done on an as-needed basis rather than as a force of habit, otherwise the interface can grow without restraint or reason. Providing separated command methods is less often required because a combined command-query can play that role: The caller simply ignores the result. If re- turning an unused result incurs a cost—e.g., it is marshaled across the wire—it may then become reasonable to provide a separated command method. Returning to the previous example, the design becomes simpler and more self-contained if the installHandler method returns the previous handler: class EventSourceExample { ... public void example(Event event, Handler newHandler) { oldHandler = eventSource.installHandler(event, newHandler); } private EventSource eventSource; private Handler oldHandler; } The caller has been offered a safer interface and no longer has to account for threading. This reduces the risk as well as the size of the code, placing responsibility for class de- sign fully with the class designer rather than the class user. The presence of Proxy objects does nothing to affect the cor- rectness of usage. A Combined Method may be a combined set of queries, a combined set of commands, or a combination of both. Thus, it may complement or contradict Command-Query Separa- tion. When there is conflict between the two practices, Com- bined Method should be applied in preference where it would make a difference in correctness and usability. As another example, consider the case of acquiring a re- source if it is available and continuing with something else if it is not. Assume, in the following interface, that the ac- quire method blocks until the resource becomes available: interface Resource Kevlin Henney / Patterns in Java
  • 5. { boolean isAcquired(); void acquire(); void release(); ... } Something like the following usage code has been recom- mended as appropriate for a threaded system6 : class ResourceExample { ... public void example() { boolean acquired = true; synchronized(resource) { if(!resource.isAcquired()) resource.acquire(); else acquired = false; } if(!acquired) ... } private Resource resource; } However, even leaving aside issues of readability and us- ability, this design is an unsuitable application of Command- Query Separation. It fails if we introduce a Proxy arrangement: class ActualResource implements Resource {...} class ResourceProxy implements Resource {...} A Combined Method resolves the issues, making the pres- ence of concurrency and indirection more transparent: interface Resource { ... boolean tryAcquire(); ... } The following is clearly simpler as well as correct (and is arguably, for those reasons alone, the more tasteful design): class ResourceExample { ... public void example() { if(!resource.tryAcquire()) ... } private Resource resource; } A consequence of Combined Method is that it can make some testing and assertion-based programming practices more awkward, where both command and query roles are combined. However, design by contract, in its original form, is not always an appropriate practice when reentrancy, threading, and distribution are also features of the design. Unit-testing approaches can provide the appropriate separa- tion and level of confidence in these situations. Combined Method does not significantly complicate unit testing. If ap- plied without consideration for usage, Combined Method can make a method interface less clear and the user’s code longer and clumsier. In some cases, Execute Around Method9 offers an alternative to Combined Method that can ensure atomicity and flexibility. Conclusion Whether or not a particular practice is appropriate can be heavily dependent on the context and if it is possible or practical to make the forces arising in that context trans- parent. In the case of Java’s threading model, the oft-con- sidered good habit of using Command-Query Separation can become a poor design practice. For this reason, although Command-Query Separation was articulated originally as a principle,7 it is in truth a pattern: A principle is a general or universal truth; a pattern offers specific advice on how to build something, and its applicability is context-dependent. The Combined Method pattern can reinforce Command- Query Separation, but in some cases it is clear that the two patterns are in tension. While both are focused on class in- terface design, the forces at work in each pattern are not the same, nor is their context of applicability. Command-Query Separation is driven by requirements of testability, com- prehensibility, primitiveness, etc. and is applicable with- out risk in local, single-threaded contexts. Combined Method is driven by correctness in concurrent and distrib- uted environments and the desire to encapsulate rather than leak nontransparent details. Does the combination of command methods and query methods produce a less pure design for concurrent and dis- tributed systems than for sequential ones? The answer in part hinges on what you mean by purity. Looked at anoth- er way, a design using method combination resolves more design forces than one not using them, resulting in a design that is fitter for purpose and more encapsulated than the al- ternative. If pure means clean, then this is more—rather than less—pure. Context determines practice. s References 1. Henney, K., “Design: Concepts and Practices,” keynote at JaCC Conference, Sept. 1999, available via www.cur- bralan.com and www.accu.org. 2. Norman, D., The Design of Everyday Things, paperback edition, Basic Books, 1988. 3. Gamma, E. et al., Design Patterns: Elements of Reusable Object-Oriented Software, Addison–Wesley, 1995. 4. Waldo, J. et al., “A Note on Distributed Computing,” Sun Microsystems Laboratories, Nov. 1994, www.sun.com/ research/techrep/1994/abstract-29.html. 5. Adams, D., The Hitchhiker’s Guide to the Galaxy, Pan, 1979. 6. Mannion, M., “Concurrent Contracts: Design by Contract™ and Concurrency in Java,” Java Report, Vol. 4, No. 5, May 1999, pp. 51–66. 7. Meyer, B., Object-Oriented Software Construction, 2nd edi- tion, Prentice Hall, 1997. 8. Fowler, M., Refactoring: Improving the Design of Existing Code, Addison–Wesley, 1999. 9. Beck, K., Smalltalk Best Practice Patterns, Prentice Hall, 1997. 88 Java™ Report | DECEMBER 2000 http://www.javareport.com Patterns in Java / Kevlin Henney