Sie sind auf Seite 1von 550

Martin Fowler: Articles

About Contact
Home Blog Articles Books ThoughtWorks
Me Me

Martin Fowler: Articles


● Popular:
| The New Methodology | Is Design Dead? | Continuous Integration |
● Enterprise Application Architecture:
| Developing Patterns of Enterprise Software | Errant Architectures | Domain Logic and SQL |
Evolutionary Database Design |
● Analysis Patterns:
| New Analysis Patterns | Patterns for things that change with time | Quantity | Range | Accounting
Patterns | Organization Structures (Accountability) | Dealing With Roles | Specification | Recurring
Event in Calendars | Dealing with Properties | Application Facades | UML Diagrams |
● XP and Agile Methods:
| The New Methodology | Using an Agile Software Process with Offshore Development |
Canadian Workshop on Scaling XP/Agile Methods | Evolutionary Database Design | The XP 2002
Conference | The Agile Manifesto: where it came from and where it may go | The Manifesto for
Agile Software Development | Planning and Running an XP Iteration | Variations on a Theme of
XP | | Is Design Dead? | The XP 2000 Conference | Continuous Integration | Continuous Integration
with Visual C++ and COM | Quick Page on XP | Keeping Software Soft | The Almighty Thud |
Keynote at SD East |
● Columns for Distributed Computing:
| Keeping Software Soft | Use and Abuse Cases | Is there such a thing as Object Oriented Analysis?
| Testing Methods: The Ugly Duckling | What's a Model For? | Refactoring: Doing Design After the
Program Runs | The Almighty Thud | How Standard is Standard UML? |
● Refactoring:
| Refactoring Home Page | Crossing Refactoring's Rubicon |
● Supplements for UML Distilled:
| Errata for UML Distilled | Defining the UML Kernel | Changes in UML Versions | Application
Facades |
● Columns for IEEE Software:
| Who Needs an Architect? | The Difference between Marketecture and Tarchitecture |
Components and the World of Chaos | Patterns | When to Make a Type | Using Metadata | How .
NET's Custom Attributes Affect Design | Yet Another Optimization Article | Public versus
Published Interfaces | Avoiding Repetition | Separating User Interface Code | The Importance of
Being Closed | Reducing Coupling | To Be Explicit |

http://www.martinfowler.com/articles.html (1 of 10)05/12/2003 15:35:34


Martin Fowler: Articles

● Others:
| Interview with Artima.com | Reflection vs Code Generation | Enterprise Transforming Projects
That Don't Kill the Enterprise | Writing with XML |

Popular
Some articles keep showing up as regular choices for visitors. So I thought I'd put them first in case you're
looking for them, or if not to see what counts as popular around here.

The New Methodology


In the past few years there's been a rapidly growing interest in agile (aka "lightweight")
methodologies. Alternatively characterized as an antidote to bureaucracy or a license to hack
they've stirred up interest all over the software landscape. In this essay I explore the reasons for
agile methods, focusing not so much on their weight but on their adaptive nature and their people-
first orientation. I also give a summary and references to the processes in this school and consider
the factors that should influence your choice of whether to go down this newly trodden path.
Latest Significant Version: April 2003
Is Design Dead?
For many that come briefly into contact with Extreme Programming, it seems that XP calls for the
death of software design. Not just is much design activity ridiculed as "Big Up Front Design", but
such design techniques as the UML, flexible frameworks, and even patterns are de-emphasized or
downright ignored. In fact XP involves a lot of design, but does it in a different way than
established software processes. XP has rejuvenated the notion of evolutionary design with practices
that allow evolution to become a viable design strategy. It also provides new challenges and skills
as designers need to learn how to do a simple design, how to use refactoring to keep a design clean,
and how to use patterns in an evolutionary style.
Latest Significant Version: February 2001
Continuous Integration (with Matt Foemmel)
An important part of any software development process is getting reliable builds of the software.
Despite it's importance, we are often surprised when this isn't done. Here we discuss the process
that Matt has put into place on a major project at ThoughtWorks, a process that is increasingly used
throughout the company. It stresses a fully automated and reproducible build, including testing, that
runs many times a day. This allows each developer to integrate daily thus reducing integration
problems.

Enterprise Application Architecture


For most of my career I've specialized in enterprise application work. Enterprise applications have their
own particular challanges and techniques that work with them. These articles explore some of the patterns,
principles and practices that I've uncovered in this work.

http://www.martinfowler.com/articles.html (2 of 10)05/12/2003 15:35:34


Martin Fowler: Articles

Developing Patterns of Enterprise Software


A short page on the growing community and body of work in capturing patterns for the
development of enterprise applications.
Latest Significant Version: May 2003
Errant Architectures
Software Development magazine adapted chapter 7 (Distribution Strategies) of my book Patterns
of Enterprise Application Architecture as an article in their magazine. I suspect they liked it due to
its tone and the inclusion of the First Law of Distributed Object Design. (Registration required with
CMP)
Domain Logic and SQL
Over the last couple of decades we've seen a growing gap between database-oriented software
developers and in-memory application software developers. This leads to many disputes about how
to use database features such as SQL and stored procedures. In this article I look at the question of
whether to place business logic in SQL queries or in-memory code, considering primarily
performance and maintainability based on an example of a simple, but rich SQL query.
Latest Significant Version: February 2003
Evolutionary Database Design (by Pramod Sadalage and Martin Fowler)
Over the last few years we've developed a number of techniques that allow a database design to
evolve as an application develops. This is a very important capability for agile methodologies. The
techniques rely on applying continuous integration and automated refactoring to database
development, together with a close collaboration between DBAs and application developers. The
techniques work in both pre-production and released systems.
Latest Significant Version: January 2003

Analysis Patterns
Patterns are important to me, as they are a key technique to discussing and capturing what makes good
design. Analysis Patterns were the subject of my first book, and they continue to be a topic that interests
me deeply.

New Analysis Patterns


I've returned to writing about Analysis Patterns and this will probably lead to a new book in the
hopefully near future. As I work towards it, this is the place where I'll post my work in progress.

Patterns for things that change with time


Summarizes various patterns that you can use to answer questions about the state of an information
in the past. These include questions of the form "what was Martin's address on 1 July 1999" and
"what did we thing Martin's address was on 1 July 1999 when we sent him a bill on 12 August
1999".
Quantity
Handling dimensioned numbers such as: 12 ft and $9.99
Range

http://www.martinfowler.com/articles.html (3 of 10)05/12/2003 15:35:34


Martin Fowler: Articles

Treating a range of values, such as Oct 22-25 as a single object.


Accounting Patterns
In my book I included a chapter of patterns to do with accounting. Here I update and greatly
expand on this topic. The primary pattern here is that of Posting Rule, which takes us from a
passive accounting system to an active one. There's also discussion of entires, accounts,
transactions, and the tricky matter of adjustments.
Organization Structures (Accountability)
This is a rework of the accountability chapter from the original analysis patterns book. It does some
small updates to the patterns, but the main change is a complete rewrite of the chapter to put it into
the new form that I'm now working with.
Dealing With Roles
A range of patterns that look at ways to handle situations where objects of a class can play different
roles in various situations.
Specification
Patterns that describe how you can describe specifications of kinds of objects. Essentially the most
general form allows you to encode predicate expressions as an interpreter of objects. These are
useful for representing object queries, and for defining a requirement that objects need to match.
Recurring Event in Calendars
How to build an object structure that allows you to represent complicated recurring events. Such as
the schedule for street cleaning when I lived in the South End of Boston.
Dealing with Properties
Many things have properties, and there are many ways to model how these properties work. These
range from simple explicit properties to complex property models with an active knowledge level
for validation. These patterns discuss some of the options in handling this.
Application Facades
Analysis Patterns talked about the topic of application facades. This article gives a much more in
depth treatment of this idea, including a lot of sample code to help you implement it. This is also an
extension of the Java example I gave in chapter 11 of UML Distilled.
UML Diagrams
I'd intended to put together UML diagrams for the patterns in the book. As it turned out I've come
the view that other things were more important. Some others did work on diagrams, however, so
here there are some for chapters 2-5

XP and Agile Methods


I've been long interested in the approaches of what are now called agile methods. My New Methodology
article provides a summary of my perspective on them and a survey of the whole field. I've also written
quite a few articles on XP, which I've been involved with ever since working on the C3 project.

The New Methodology


In the past few years there's been a rapidly growing interest in agile (aka "lightweight")
methodologies. Alternatively characterized as an antidote to bureaucracy or a license to hack

http://www.martinfowler.com/articles.html (4 of 10)05/12/2003 15:35:34


Martin Fowler: Articles

they've stirred up interest all over the software landscape. In this essay I explore the reasons for
agile methods, focusing not so much on their weight but on their adaptive nature and their people-
first orientation. I also give a summary and references to the processes in this school and consider
the factors that should influence your choice of whether to go down this newly trodden path.
Latest Significant Version: April 2003
Using an Agile Software Process with Offshore Development
For the last two years ThoughtWorks has operated a lab in Bangalore India to support our software
development projects in North America and Europe. Traditional approaches to offshore
development are based on plan-driven methodologies, but we are very firmly in the agile camp.
Here I discuss our experiences and lessons learned in doing offshore agile development. So far
we've discovered that we can make it work, although the benefits are still open to debate.
Latest Significant Version: September 2003
Canadian Workshop on Scaling XP/Agile Methods (by Jonathan Rasmusson and Jim McDonald)
As XP and other Agile methods gain popularity, questions are beginning to surface regarding how
to scale XP beyond teams of 10-12 people. In mid February 2003 a workshop dedicated to the
subject was held in Banff Alberta Canada. In this article we report on the keynote speeches from
Ken Schwaber, and Martin Fowler, as well as other leading practitioners.
Latest Significant Version: March 2003
Evolutionary Database Design (by Pramod Sadalage and Martin Fowler)
Over the last few years we've developed a number of techniques that allow a database design to
evolve as an application develops. This is a very important capability for agile methodologies. The
techniques rely on applying continuous integration and automated refactoring to database
development, together with a close collaboration between DBAs and application developers. The
techniques work in both pre-production and released systems.
Latest Significant Version: January 2003
The XP 2002 Conference
At the end of May 2002, the XP community once again descended on the Mediterranean island of
Sardinia. In this article I look at the plenary speeches from Ken Schwaber, David Parnas, Enrico
Zaninotto, Bill Wake, and the Standish Group's Jim Johnson. They lead me into some thoughts on
the essence of agile development, the role of mathematical specifications, the complexity of
irreversibility, metaphor, and the best way to drastically cut software costs.
The Agile Manifesto: where it came from and where it may go
In February 2001 a group of seventeen software pundits got together in Snowbird UT to discuss the
growing field of what used to be called lightweight methods. We decide to use the term agile to
describe this new breed of agile methods. We also wrote the Manifesto for Agile Software
Development , setting out the values and principles of these agile processes. I was one of these self-
elected visionaries and have since come across many questions about this group's origins and
future. This essay describes my opinion about the answers.
Latest Significant Version: February 2002
The Manifesto for Agile Software Development
A group of seventeen people got together in Snowbird, UT in February 2001 to talk about new
styles of lightweight methods. One result of this is coining the word agile to represent a new breed
of agile processes for software development. We also put together a Manifesto for Agile Software

http://www.martinfowler.com/articles.html (5 of 10)05/12/2003 15:35:34


Martin Fowler: Articles

Development which describes the values and principles of these agile methods. Jim Highsmith and
I wrote this article for Software Development magazine to further explain the manifesto.
Planning and Running an XP Iteration (with Cara Taber)
Since the begining of the new millenium, we've been running an interesting XP project. It's
interesting not just because it was one of the first XP projects at ThoughtWorks, but also due to its
size: around 50 people are involved. Here we talk about how we run this project by focusing
around the activities that need to be done for a single iteration, and how the various subteams work
around that iteration.
Latest Significant Version: January 2001
Variations on a Theme of XP
One of the attractive things about XP is that it gives quite definite statements about what you
should do to be doing XP. Furthermore that set of practices is carefully designed to fit together.
Taking anything out has serious consequences. Yet one of the principles of XP and other light
methods is that they be self adaptive: that is you should change the process as you are developing
the project. How does this notion fit in with the rigid practices of XP?
Is Design Dead?
For many that come briefly into contact with Extreme Programming, it seems that XP calls for the
death of software design. Not just is much design activity ridiculed as "Big Up Front Design", but
such design techniques as the UML, flexible frameworks, and even patterns are de-emphasized or
downright ignored. In fact XP involves a lot of design, but does it in a different way than
established software processes. XP has rejuvenated the notion of evolutionary design with practices
that allow evolution to become a viable design strategy. It also provides new challenges and skills
as designers need to learn how to do a simple design, how to use refactoring to keep a design clean,
and how to use patterns in an evolutionary style.
Latest Significant Version: February 2001
The XP 2000 Conference (with Jack Bolles)
In late June over a hundred people gathered on the Mediterranean island of Sardinia to take part in
the XP2000 conference to discuss Extreme Programming (XP) and other flexible methodologies.
Continuous Integration (with Matt Foemmel)
An important part of any software development process is getting reliable builds of the software.
Despite it's importance, we are often surprised when this isn't done. Here we discuss the process
that Matt has put into place on a major project at ThoughtWorks, a process that is increasingly used
throughout the company. It stresses a fully automated and reproducible build, including testing, that
runs many times a day. This allows each developer to integrate daily thus reducing integration
problems.
Continuous Integration with Visual C++ and COM (by William E Caputo and Oren Miller)
The Continuous Integration principles are applicable in many different development environments.
While the principles remain largely unchanged from project to project, the implementation of this
practice can vary considerably. Variables such as language, platform, team size & team location
provide unique implementation challenges. Here we will outline how we've implemented CI in a
COM/Windows environment for a project developing primarily in Visual C++.
Quick Page on XP

http://www.martinfowler.com/articles.html (6 of 10)05/12/2003 15:35:34


Martin Fowler: Articles

A short summary of XP with links to where you can find the real meat..
Keeping Software Soft
Why we need methods that assume software should be soft and open to change.
The Almighty Thud
Why you shouldn't write a lot of documentation.
Keynote at SD East
At Software Development East in 2000, I gave a keynote "Keeping Software Soft", which covers
very similar material to my essay The New Methodology. Dr Dobbs magazine made the doubtful
decision to tape this and offer it as a webcast. This way you get to see a very small shaky picture of
me umming and erring. Isn't technology wonderful?

Columns for Distributed Computing


In the late 90's I wrote the "Methods in Practice" column for Distributed Computing Magazine. Consider
whether these are the reasons that the magazine is no longer with us....

Keeping Software Soft


Why we need methods that assume software should be soft and open to change.
Use and Abuse Cases
Ways in which to go badly wrong with Use Cases.
Is there such a thing as Object Oriented Analysis?
My thoughts on the role of analysis in OO projects..
Testing Methods: The Ugly Duckling
Why testing is much more important than most methodologists realize..
What's a Model For?
What is the point of drawing up UML Models?
Refactoring: Doing Design After the Program Runs
A short introduction to Refactoring.
The Almighty Thud
Why you shouldn't write a lot of documentation.
How Standard is Standard UML?
What does it mean to have a standard UML, and why the standard doesn't standardize as many
things as people think it does..

Refactoring
You can find all my material on refactoring on the refactoring home page

Refactoring Home Page


Articles on refactoring, links to more articles (and tools) on refactoring, index of all the

http://www.martinfowler.com/articles.html (7 of 10)05/12/2003 15:35:34


Martin Fowler: Articles

refactorings in the book with additional comments and a few more refactorings..
Crossing Refactoring's Rubicon
In January 2001 two Java tools crossed Refactoring's Rubicon. Refactoring in Java now has serious
tool support
Latest Significant Version: February 2001

Supplements for UML Distilled


Some additional material that builds on what I wrote for UML Distilled

Errata for UML Distilled


Errata for the second edition of UML Distilled
Defining the UML Kernel
At UML World in 2000 we had a panel discussion on whether we should have a kernel for the
UML. SD Magazine turned it into a surprisingly coherent article (there's nothing like a good
editor!) Take a look to see how frighteningly small I would make the kernel.
Changes in UML Versions
Changes in the various versions of the UML
Application Facades
Analysis Patterns talked about the topic of application facades. This article gives a much more in
depth treatment of this idea, including a lot of sample code to help you implement it. This is also an
extension of the Java example I gave in chapter 11 of UML Distilled.

Columns for IEEE Software


At the beginning of 2001 I started to edit a column on design for IEEE Software.

Who Needs an Architect?


What is architecture, and who exactly is an architect? These are questions that seem to get
everyone very heated. So in this IEEE Software column, I let Ralph Johnson explain about
architecture: with a definition that matches all others in a way that nobody agrees with. I also talk
about two sub-species of architect: Architectus Reloadus and Architectus Oryzus.
The Difference between Marketecture and Tarchitecture (by Luke Hohmann)
When we think about software architecture, we usually think about its technical architecture. But
there's also another important architecture - the one we use to communicate with the customers of
the software: the marketing architecture. Neglecting this "marketecture", and its relationship with
the "tarchitecture", can get development projects into a lot of trouble.
Components and the World of Chaos (by Rebecca Parsons)
Why chaos theory suggests that component assembly may not be as easy as it's cracked up to be.
Patterns
My IEEE column on the valuable contributions that patterns can make to understanding software

http://www.martinfowler.com/articles.html (8 of 10)05/12/2003 15:35:34


Martin Fowler: Articles

design.
When to Make a Type
Guidelines on when to make a new user defined type (or class) for values.
Using Metadata
You can use metadata based approaches to remove the pain from tedious data oriented tasks.
How .NET's Custom Attributes Affect Design (by James Newkirk and Alexei Vorontsov)
Jim and Alexei took a leading role in developing a new version of NUnit. From this they reflected
on how design is affected by the new .NET language feature of attributes.
Yet Another Optimization Article
It always surprises me that many well-established principles about performance optimization aren't
very well known. This article is yet another attempt to cover these.
Public versus Published Interfaces
Many modern languages make a distinction between public and private features in a module. A
distinction that doesn't get made so often is between public and published features: and that may be
a more important distinction.
Avoiding Repetition
It's sometimes quite remarkable how the simple rule of avoiding repetition in software can lead into
good design
Separating User Interface Code
One of the first lessons I learned was to always keep user interface code separate from anything
else. Not just is this still good advice, it's surprising how often it's forgotten.
The Importance of Being Closed (by Craig Larman)
Craig's spot in the column looks at the importance of the Open-Closed principle and Protected
Variation, and why Parnas's information hiding is more than encapsulation. He also gives some tips
on ways to implement a protected variation.
Reducing Coupling
Thinking about how to visualize and reduce coupling.
To Be Explicit
Often designs techniques are used to make a system more flexible, but end up being harder to work
with. One of the reasons is that explicitness is a property that often gets forgotten in design.

All these IEEE Software articles are copyright IEEE. Personal use of this material is permitted. However,
permission to reprint/republish this material for advertising or promotional purposes or for creating new
collective works for resale or redistribution to servers or lists, or to reuse any copyrighted component of
this work in other works must be obtained from the IEEE.

Others
The section for papers that don't fit anywhere else.

Interview with Artima.com


I was interviewed by Bill Venners for his artima.com web site. In the interview I touch upon

http://www.martinfowler.com/articles.html (9 of 10)05/12/2003 15:35:34


Martin Fowler: Articles

refactoring, evolutionary design, flexibility, and test driven development. Bill even manages to
make me sound coherent.
Reflection vs Code Generation (by Mike Rettig with Martin Fowler)
Written and thought out very ably by my colleague Mike Rettig. I helped a bit along the way and
he was kind enough to credit me. The article talks about techniques for eliminating repetitive code
using reflection or code generation and talks about the advantages and disadvantages of each
approach.
"Developers try to avoid tedious, redundant programming at all costs. Solid coding principles such
as inheritance, polymorphism, and design patterns help developers avoid code redundancy. But in
the uncertain realm of software development, these principles cannot eliminate the need for code
maintenance and rewrites. To a large extent, maintenance is unavoidable, and attempts to create
software that never requires maintenance only results in software guaranteed never to work.
However, this article shows that you can use the power of Java's Reflection API to reduce tedious
code writing, and use active code generation to overcome reflection limitations."
Enterprise Transforming Projects That Don't Kill the Enterprise
This article is based on a talk I gave at LOMA, an insurance industry conference, in 2001. In it I
examine a few software development projects that ThoughtWorks has done which are, to some
degree "enterprise transforming". The talk (and paper) are aimed at a non-technical audience. From
the projects I draw out some common lessons learned. In essence these are: Deliver Frequently,
Expect Surprises, Get High Level Executive Support, Treat Business and Software Development as
Partners, Choose Technology for the Future, People are The Critical Success Factor, and Keep
Learning. A version of this article was recently published in Resource magazine.
Writing with XML
For quite a while now, I've been doing most of my writing using XML - even to the point of
writing my last book in XML. As I've mentioned this to people they've asked me a number of
questions about my experiences, and that's been enough to prompt this little article on the whole
thing.
Latest Significant Version: January 2003

© Copyright Martin Fowler, all rights reserved

http://www.martinfowler.com/articles.html (10 of 10)05/12/2003 15:35:34


Martin Fowler

About Contact
Home Blog Articles Books ThoughtWorks
Me Me

About Me Martin Fowler


Contact Me
Articles I am an author, speaker, and consultant on
Books the design of enterprise software. On this
site I keep as much information as I can on-
P of EAA line. There are links to my books, various
Refactoring on-line articles, and links to areas relevant
to my work. My primary areas of
UML Distilled
involvement are in object-oriented
Analysis Patterns development, refactoring, patterns, agile
Signature Series methods, enterprise application
architecture, domain modeling, and
Bliki
extreme programming. I work for
EAA Catalog ThoughtWorks, an outstanding application
RSS updates development and consulting company. Upcoming Talks
Blog RSS Nov
Recent Updates
Useful Links TW Agile Seminar: Chennai,
27
India
refactoring.com October: Enterprise Integration
TW Agile Seminar: Bangalore,
Agile Manifesto Patterns now available 29
India
ThoughtWorks For the last year or two, my Dec
colleague Gregor Hohpe and co-
EAI Patterns 1-2 XP Day: London
author Bobby Woolf have been
working on what I think is going to 3 Agile Scotland: Edinburgh
be the foundation book on the 11 NYOUG: New York, NY
design of messaging systems. The Jan
book is the third book in my
19-23 OOP: Munich
signature series and is now wending
its way through the distribution Mar
channels. 28-31 OT: St Neots, England
September: Using an Agile Software June
Process with Offshore Development 6-10 XP 2004: Garmish-P, Germany
For the last two years
ThoughtWorks has operated a lab in
Bangalore India to support our
software development projects in
North America and Europe.
Traditional approaches to offshore

http://www.martinfowler.com/ (1 of 5)05/12/2003 15:35:36


Martin Fowler

development are based on plan-


driven methodologies, but we are
very firmly in the agile camp. Here
I discuss our experiences and
lessons learned in doing offshore
agile development. So far we've
discovered that we can make it
work, although the benefits are still
open to debate.
September: UML Distilled 3rd Edition
now available
The third edition of UML Distilled
is now printed and should be
wending its way through the
distribution channels. The main
point of the new edition is to cover
UML 2, but I've also rewritten
almost all the book to improve the
explanation. In particular you'll find
chapters for the new diagram types
in UML, a much reduced chapter on
process, and I removed the last code
example chapter which didn't seem
to work well. Despite looking
thicker at the bookstore, it is
actually less pages (it's printed on
thicker paper.)
September: Who Needs an Architect?
What is architecture, and who
exactly is an architect? These are
questions that seem to get everyone
very heated. So in this IEEE
Software column, I let Ralph
Johnson explain about architecture:
with a definition that matches all
others in a way that nobody agrees
with. I also talk about two sub-
species of architect: Architectus
Reloadus and Architectus Oryzus.
August: The Difference between
Marketecture and Tarchitecture
(by Luke Hohmann)
When we think about software
architecture, we usually think about
its technical architecture. But there's

http://www.martinfowler.com/ (2 of 5)05/12/2003 15:35:36


Martin Fowler

also another important architecture -


the one we use to communicate
with the customers of the software:
the marketing architecture.
Neglecting this "marketecture", and
its relationship with the
"tarchitecture", can get
development projects into a lot of
trouble.
May: Finally - I have a blog
After much standing on the edge,
wondering about plunging into a
blog, I've now dived in. It's not
quite the normal blog - hence the
name 'bliki' (cross between blog and
wiki).
May: Components and the World of
Chaos
(by Rebecca Parsons)
Why chaos theory suggests that
component assembly may not be as
easy as it's cracked up to be.
May: List of Database Refactorings
Pramod Sadalage has started to
capture the various database
refactorings we use in evolving
databases. This list will grow as
Pramod steadily works through
documenting the refactorings.
May: Developing Patterns of Enterprise
Software
A short page on the growing
community and body of work in
capturing patterns for the
development of enterprise
applications.
May: Patterns
My IEEE column on the valuable
contributions that patterns can make
to understanding software design.
Apr: Errant Architectures
Software Development magazine
adapted chapter 7 (Distribution
Strategies) of my book Patterns of

http://www.martinfowler.com/ (3 of 5)05/12/2003 15:35:36


Martin Fowler

Enterprise Application Architecture


as an article in their magazine. I
suspect they liked it due to its tone
and the inclusion of the First Law of
Distributed Object Design.
(Registration required with CMP)
Apr: Canadian Workshop on Scaling
XP/Agile Methods
(by Jonathan Rasmusson and Jim
McDonald)
As XP and other Agile methods
gain popularity, questions are
beginning to surface regarding how
to scale XP beyond teams of 10-12
people. In mid February 2003 a
workshop dedicated to the subject
was held in Banff Alberta Canada.
In this article we report on the
keynote speeches from Ken
Schwaber, and Martin Fowler, as
well as other leading practitioners.
Apr: Domain Logic and SQL
Over the last couple of decades
we've seen a growing gap between
database-oriented software
developers and in-memory
application software developers.
This leads to many disputes about
how to use database features such
as SQL and stored procedures. In
this article I look at the question of
whether to place business logic in
SQL queries or in-memory code,
considering primarily performance
and maintainability based on an
example of a simple, but rich SQL
query.
Apr: Pramod's Database Refactoring
Slides
My colleague Pramod Sadalage
gave a talk on database refactoring
at SD West. These are a copy of the
slides from that talk (pdf).
Apr: RSS feed for updates
I've created an RSS feed for people

http://www.martinfowler.com/ (4 of 5)05/12/2003 15:35:36


Martin Fowler

who have an aggregator and are


interested in tracking updates to this
site. I'll use this feed for
announcements. At some point in
the future I may start something
that's kind of like a blog - but when
I do this I'm intending to use a
different channel.

http://www.martinfowler.com/ (5 of 5)05/12/2003 15:35:36


Martin Fowler's Bliki

About Contact
Home Blog Articles Books ThoughtWorks
Me Me

Martin Fowler's Bliki Links


home
A cross between a blog and wiki of my partly-formed ideas on software development bliki
rss
Categories
2 December
TestingLanguage agile agile
2003
I'm currently sitting in a session at XP day where design
Owen Rogers and Rob Styles are talking about leisure
the differences between XP's unit and acceptance refactoring
tests. This triggered a thought in my mind - what
should a language for writing acceptance tests be? tools
uml
Commercial tools for UI testing tend to have writing
their own proprietary language. Brett Pettichord,
ThoughtBloggers
amongst others, question this; preferring a
common scripting language such as Ruby or Bill Caputo
Python. Alan Francis
Tim Bacon
But I wonder if a language designed for
programming is really the right language for Mike Mason
writing tests. The point about tests is that they Chris Matts
operate by example. They don't try to cover how Ravi Mohan
to handle any value, instead they describe
specific scenarios and responses. I wonder if this Mike Roberts
implies a different kind of programming Chris Stevenson
language is required. Perhaps this is the truly
Jeremy Stell-
startling innovation in FIT.
Smith
Joe Walnes
2 December Other Bloggers
ProvideServiceStub design
2003 Dave Thomas
Brian Marick
/\ndy Hunt
Keith Ray
Patrick Logan
Robert Martin

http://martinfowler.com/bliki/ (1 of 10)05/12/2003 15:35:40


Martin Fowler's Bliki

An important thought for anyone building services


for a service oriented architecture. When you build
your service, also build a service stub that your
clients can use to test against. Such a stub should
provide canned responses to a fixed set of requests,
simulate error conditions, and be runnable on a
client's machine. You'll need to ensure that the stub
mimics the true systems behavior properly. By
providing a stub for your clients, you make it much
easier for your clients to use your service; which of
course means that your service is more likely to be
used.

2 December
StickyTimeline agile
2003
A project timeline is a valuable thing to
produce during a project retrospective. A
timeline should show the various events that
occurred during the project, and how they
affected the project.

At XPday, Tim Mackinnon showed a quick


and effective way to create a timeline. First
mark out an area on the wall and mark it off
with rough dates (use a whiteboard or paper
attached to the wall). Then each member of the
team puts stickies on the wall to show events.
These events are color coded: green for good
events, orange for problematic events, and
yellow for neutral events. Once everyone has
put events on there you then do a second pass.
With the second pass people put up stickies
that show how they feel: pink for happy
feelings, blue for low and frustrated feelings.

Once you have a timeline you can use the


timeline to trigger discussion about the project
and mine the timeline for lessons learned (good
things to repeat, things to do differently, things
that are puzzles, and actions for the future.) It's
particularly interesting to look at the timelines
for such things as good events with lots of blue
feelings - a surprisingly common case.

http://martinfowler.com/bliki/ (2 of 10)05/12/2003 15:35:40


Martin Fowler's Bliki

25 November
AnemicDomainModel design
2003
This is one of those anti-patterns that's been around for
quite a long time, yet seems to be having a particular
spurt at the moment. I was chatting with Eric Evans on
this, and we've both noticed they seem to be getting
more popular. As great boosters of a proper Domain
Model, this is not a good thing.

The basic symptom of an Anemic Domain Model is


that at first blush it looks like the real thing. There are
objects, many named after the nouns in the domain
space, and these objects are connected with the rich
relationships and structure that true domain models
have. The catch comes when you look at the behavior,
and you realize that there is very little behavior on
these objects. Indeed often these models come with
design rules that say that you are not to put any
domain logic in the the domain objects. Instead there
are a set of service objects which capture all the
domain logic. These services live on top of the domain
model and use the domain model for data.

The fundamental horror of this anti-pattern is that it's


so contrary to the basic idea of object-oriented design;
which is to combine data and process together. The
anemic domain model is really just a procedural style
design, exactly the kind of thing that object bigots like
me (and Eric) have been fighting since our early days
in Smalltalk. What's worse, many people think that
anemic objects are real objects, and thus completely
miss the point of what object-oriented design is all
about.

Now object-oriented purism is all very well, but I


realize that I need more fundamental arguments
against this anemia. In essence the problem with
anemic domain models is that they incur all of the
costs of a domain model, without yielding any of the
benefits. The primary cost is the awkwardness of
mapping to a database, which typically results in a
whole layer of O/R mapping. This is worthwhile iff
you use the powerful OO techniques to organize
complex logic. By pulling all the behavior out into
services, however, you essentially end up with
Transaction Scripts, and thus lose the advantages that

http://martinfowler.com/bliki/ (3 of 10)05/12/2003 15:35:40


Martin Fowler's Bliki

the domain model can bring.

One source of confusion in all this is that many OO


experts do recommend putting a layer of procedural
services on top of a domain model, to form a Service
Layer. But this isn't an argument to make the domain
model void of behavior, indeed service layer advocates
use a service layer in conjunction with a behaviorally
rich domain model.

Eric Evans's excellent book Domain Driven Design


has the following to say about these layers.

Application Layer [his name for Service


Layer]: Defines the jobs the software is
supposed to do and directs the
expressive domain objects to work out
problems. The tasks this layer is
responsible for are meaningful to the
business or necessary for interaction
with the application layers of other
systems. This layer is kept thin. It does
not contain business rules or knowledge,
but only coordinates tasks and delegates
work to collaborations of domain
objects in the next layer down. It does
not have state reflecting the business
situation, but it can have state that
reflects the progress of a task for the
user or the program.

Domain Layer (or Model Layer):


Responsible for representing concepts of
the business, information about the
business situation, and business rules.
State that reflects the business situation
is controlled and used here, even though
the technical details of storing it are
delegated to the infrastructure. This
layer is the heart of business software.

The key point here is that the Service Layer is thin - all
the key logic lies in the domain layer. He reiterates this
point in his service pattern:

Now, the more common mistake is to

http://martinfowler.com/bliki/ (4 of 10)05/12/2003 15:35:40


Martin Fowler's Bliki

give up too easily on fitting the behavior


into an appropriate object, gradually
slipping toward procedural
programming.

I don't know why this anti-pattern is so common. I


suspect it's due to many people who haven't really
worked with a proper domain model, particularly if
they come from a data background. Some technologies
encourage it; such as J2EE's Entity Beans which is one
of the reasons I prefer POJO domain models.

In general, the more behavior you find in the services,


the more likely you are to be robbing yourself of the
benefits of a domain model. If you all your logic is in
services, you've robbed yourself blind.

CommandOrientedInterface design
23 November 2003
The most common style of interface to a module is to use procedures, or object
methods. So if you want a module to calculate a bunch of charges for a contract, you
might have a BillingService class with a method for doing the calculation, calling it like
this

aBillingService.calculateCharges(aContract)

A command oriented interface would have a command class for each operation, and be
called with something like this

CalculateChargeCommand.new(aContract).run()

Essentially you have one command class for each method that you would have in the
method-oriented interface.

A common variation is to have a separate command executor object that actually does
the running of the command.

aCommandExecutor.run(CalculateChargeCommand.new(aContract))

If you've used frameworks like Struts, you'll recognize that the action classes follow this
style of operation.

So why do people like and dislike this approach? First off it's fair to say that a command
oriented interface is rather more involved than a method oriented one. You have
instantiate the command and pass them through for execution. This is more involved

http://martinfowler.com/bliki/ (5 of 10)05/12/2003 15:35:40


Martin Fowler's Bliki

than just calling a method, which is why even fans of this approach only use them for
significant interfaces (service layers, server-side logic, interfaces of major subsystems).

Command oriented interfaces have a number of benefits. One of the primary ones is the
ability to easily add common behavior to commands by decorating the command
executor. This is very handy for handling transactions, logging, and the like. Commands
can be queued for later execution and (if the commands and their data are serializable)
be passed across a network. Command results can be cached by holding results against a
key synthesized from the command name and arguments.

Where I've seen complaints about commands, the biggest issue is due to a lot of
duplicated logic in commands. This tends to happen most when the commands are
Transaction Scripts that contain a lot of logic. This isn't necessarily an issue with using
commands as opposed to methods; this problem is a general issue with Transaction
Scripts. It may that command-oriented structure tends to exaggerate this, if only because
many people feel that a class needs a page or two of code to be worthwhile, and thus
end up putting more code in the command than should be there.

You'll notice I've used the word interface for this page. This reflects that the choice
about using commands is primarily about the interface to clients rather than about the
actual implementation of the command logic. It's perfectly reasonable to have command
classes whose run method is just a single line calling out to another method. Doing this
gives you all the advantages of commands, but allows you to keep the logic out of the
command classes themselves. Such command classes have very few lines of code.

A common question with commands is what to return. Generic run methods need a
general return type, such as Object or CommandResult, but you'll want a more specific
type to get the results from running a command. One route is to define a result class for
each command class and use a naming convention, so that CalculateChargeCommand
would have a return type of CalculateChargeResult. Another route is to make the
command store the results in the same object. In this case you would first run the the
command, and then interrogate the command object for results.

22 November
Saba leisure
2003

http://martinfowler.com/bliki/ (6 of 10)05/12/2003 15:35:40


Martin Fowler's Bliki

One of the reasons my bliki entries


have been quiet recently is that I've
spent a week at one of my favorite
places in the world. Saba is a very
small island in the Caribbean, close
to St Martin. In many ways the best
things about Saba are the things it
doesn't have. There are no beaches,
no golf courses, no casinos. The
mass tourism and resort complexes
that litter so much of the Caribbean
have ignored Saba since it's too
small and too hilly. As a result the
island is wonderfully quiet and
relaxed.

As a result only a few tourists go to


Saba. For those that do the main
activity is diving. Saba is
surrounded by coral reefs in a
marine park, and the resulting
diving is excellent. (However since
the reefs are 30' and deeper, there is
nothing for snorkelers.) Most of the
diving is a short boat ride from the
harbor, so you can take your surface
time on shore and quickly get to the
next dive site when you're ready.
When I go I dive with Saba Deep,
who like to run small group dives.
Often I've dived with them with
only a couple of other divers.

Saba also has nice hiking trials that


can fill a couple of days. The most
popular gives you the irresistible
opportunity to hike to the top of the
tallest mountain in the kingdom of
the Netherlands (around 3000 ft).
My favorite trail is the Sandy Cruz
trail which loops around the rain
forest on the north slopes of Mount
Scenery.

The island's vertical nature yields


quite a few special stories. Such as
the island's road. They got Dutch

http://martinfowler.com/bliki/ (7 of 10)05/12/2003 15:35:40


Martin Fowler's Bliki

civil engineers to survey a road


early this century and were told it
couldn't be built. So one of the
islanders took a correspondence
course in civil engineering and the
islanders built the road themselves.
My wife (a structural engineer)
appreciated both the road and the
Dutch engineer's reaction -
apparently that road would break
just about every building code in
the US. The airstrip is a similar
story, it's the shortest landing strip
you are ever likely to land on. Sit
by right hand window and you'll
swear that that wing will scrape the
mountainside going in. But in 30
years there's never been an accident.

The last couple of times I've gone to


Saba I've stayed at the Gate House.
It's a comfortable B&B with
excellent food and wine. The small
friendly nature of the island was
summed up the first time we went.
The immigration officer at the
airport said - oh yes you'll be
staying at the Gate House, Vincent's
here to take you up in his taxi.

6 November
HistoryOfIterativeDevelopment agile
2003
Most of the clients I run into have not heard of iterative
development, or consider it to be a new and relatively untried
phenomenon. In contrast iterative development has been around
for a long time under various names. A recent article by Craig
Larman and Vic Basili in IEEE Software summarizes an effort to
capture this history and gives you a good idea on the long story
of successful projects that use iterative development approaches.

3 November 2003 UnwantedModelingLanguage


18 October 2003 C-Refactory

http://martinfowler.com/bliki/ (8 of 10)05/12/2003 15:35:40


Martin Fowler's Bliki

9 October 2003 EnterpriseArchitecture


6 October 2003 LocalVariablesInClassDiagrams
6 October 2003 IntelliCsharp
4 October 2003 PrinciplesOfXP
1 October 2003 TechnicalDebt
26 September 2003 MeasuringProductivity
20 September 2003 MovingAwayFromXslt
17 September 2003 DependencyAndAssociation
12 September 2003 PlatformIndependentMalapropism
11 September 2003 Seedwork
10 September 2003 EtymologyOfRefactoring
29 August 2003 CannotMeasureProductivity
26 August 2003 CurrencyAsValue
18 August 2003 UseCasesAndStories
15 August 2003 PleasingTheCustomer
14 August 2003 BuildingArchitect
12 August 2003 MultiplicityNotCardinality
11 August 2003 FixedLengthString
31 July 2003 PatternsAreNothingNew
30 July 2003 SingingDetective
29 July 2003 FixedPrice
21 July 2003 MultipleCanonicalModels
15 July 2003 HistoryIsNotBunk
24 June 2003 Swebok
23 June 2003 Agiledox
17 June 2003 TypedCollection
14 June 2003 SecurityAndDesign
10 June 2003 MakingStubs
8 June 2003 Uml2
5 June 2003 IncludeAndExtend
3 June 2003 RefactoringCringely
28 May 2003 UmlMode
26 May 2003 WhatIsaBliki
23 May 2003 LanguageForLearningObjects
18 May 2003 FrameworkBuilding

http://martinfowler.com/bliki/ (9 of 10)05/12/2003 15:35:40


Martin Fowler's Bliki

18 May 2003 Slimp3


17 May 2003 AggregationAndComposition
15 May 2003 WhatIsFailure
14 May 2003 ProtectedData
13 May 2003 AccessModifier
12 May 2003 CollectionsOnClassDiagrams
10 May 2003 LargeAgileProjects

© Copyright Martin Fowler, all rights reserved

http://martinfowler.com/bliki/ (10 of 10)05/12/2003 15:35:40


Books by Martin Fowler

About Contact
Home Blog Articles Books ThoughtWorks
Me Me

Books
| P of EAA | Refactoring | UML Distilled | Planning XP | Analysis Patterns | Signature Series |

Over the last few years, I've succumbed to an unfortunate addiction - that of writing books. Although after
each book I seriously consider giving it up, I haven't yet succeeded. If you have a similarly uncontrollable
urge to read books (I've got that disease too) then here's a list of the books that I've written, as well as
information on my new signature series.

Patterns of Enterprise Application Architecture


On Amazon

My latest work, and I think the hardest one to write. It all started after
Dave Rice and I gave some talks on J2EE architecture and mulled
over how the concepts we had learned in C++, Forte, CORBA, and
Smalltalk had been crucial to us developing good designs in Java.
With this book I wanted to set many of these patterns down to help
developers whatever their platform. As it's turned out these have been
very valuable as we have started to use .NET in 2002.

The book is in two parts. The first part is a short (100 page) tutorial
on enterprise application architecture. The bulk of the book is the
reference to forty or so patterns. All of these patterns are ones that
I've seen in the field, usually on many different programming
platforms.

Each pattern describes details of how it works and when to use it, together with code examples in Java, C#
or both. (I picked these languages because most software developers can read them, not because of any
particular coupling or opinions about the language).

The main topic areas are: how to layer an enterprise application, how to organize domain logic, how to tie
that logic to a relational database, how to design a web based presentation, some important principles in
distributed design, and handling of what we call "offline concurrency" - concurrency that spans

http://martinfowler.com/books.html (1 of 8)05/12/2003 15:35:44


Books by Martin Fowler

transactions.

I've been fortunate enough to have some excellent contributors to this book, most notably Dave Rice - who
wrote a good tenth of it. Also joining in are Matt Foemmel, Edward Hieatt, Robert Mee, and Randy
Stafford

The book has won two awards: a productivity award from Software Development magazine and a best
java book award from JavaWorld.com.

| Errata |

Translations: German

Further Reading

Catalog of Patterns
Brief summaries of the patterns in the book
Distribution Strategies Chapter
SD Magazine adapted chapter 7 as an article for the magazine (Registration required with CMP)

Refactoring: Improving the Design of Existing Code


On Amazon

Refactoring is a controlled technique for improving the design of an existing code


base. Its essence is applying a series of small behavior-preserving transformations,
each of which "too small to be worth doing". However the cumulative effect of each
of these transformations is quite significant. By doing them in small steps you reduce
the risk of introducing errors. You also avoid having the system broken while you are
carrying out the restructuring - which allows you to gradually refactor a system over
an extended period of time.

My book describes the process of refactoring and spends most of its time explaining how to do the various
refactorings - the behavior preserving transformations. The book opens with a simple example that
describes the whole process. There are then some introductory chapters that discuss broader issues around
refactoring, the "code smells" that suggest refactoring, and the role of testing.

The bulk of the book is around seventy refactorings described in detail: the motivation for doing them,
mechanics of how to do them safely and a simple example.

http://martinfowler.com/books.html (2 of 8)05/12/2003 15:35:44


Books by Martin Fowler

The books finishes with some guest chapters from those whose early work have developed the ideas of
refactoring.

| Errata |

Translations: Japanese, German, Russian, Czech, and Korean

Further Reading

refactoring.com
My original hope was to make this a portal for on-going work on refactoring. I've learned that my
ambitions never quite match up to the time I have available. However here you will find links to
further resources on refactoring, including the mailing list and tools as they become available. I've
also got a catalog that includes summaries of all the refactorings in the book, together with some
new ones.

UML Distilled: A Brief Guide to the Standard Object Modeling


Language
On Amazon

The UML appeared in 1997 to eliminate the bedlam that had


overtaken graphical modeling languages in the object-oriented
world. Before the UML there were a host of such languages,
differing in all sorts of annoying ways. Now the UML is pretty
much the only game in town, which makes life much simpler for
many people involved in OO software development

This book was the first book on the UML, and I wrote it as a short
overview of the language. My aim was to target that fraction of the
UML that was the most useful and explain it briefly. My proudest
thing about this book is that it's under half an inch thick - which was
very unusual for OO modelling books at that time. I was also
pleased when it won a productivity award from Software
Development magazine.

The book has chapters for all the major diagram types in the UML, together with an intro and some
general guidance on software process and how it fits in with the UML. I also put in a lot of tips on how to
use the UML well and introduce a number of principles and techniques for good OO development.

http://martinfowler.com/books.html (3 of 8)05/12/2003 15:35:44


Books by Martin Fowler

In September 2003, the 3rd edition of this book came out. This edition was mainly put together to bring
the book into line with the latest UML 2 standard. I've further taken the opportunity to completely rewrite
most of the book, clarifying explanation from my experiences and from review comments from others. I've
added chapters for the new diagram types that were added in UML 2. However by slimming down the
discussion on process, and removing the final code example chapter, I've actually managed to reduce the
page count of the book. (It looks thicker because AW printed it on thicker paper.)

| Errata |

Translations: Japanese, German, Polish, Russian, Portugese, Korean, French (first edition), Spanish (first
edition), Chinese

Further Reading

Supplementory Articles
Some extra material about the UML on my site, including the summary of the changes in UML 1.x
from the book.

Planning Extreme Programming


On Amazon

In 1996 I was lucky enough to work on the C3 project for a year - this was the project
that gave birth to Extreme Programming. I learned many things by taking part in that
project, but one thing that particularly impressed me was the approach to planning.
Not just was the project run on firmly iterative lines, it included a planning process
that was simple, agile and remarkably effective.

After Kent's seminal "white book" came out, we talked about what kinds of books should follow on.
Somehow Kent and I talked each other into collaborating on a book that focused on the planning side of
Extreme Programming. Although it was based on the C3 experience, it also added lessons both we, and
other early XPers, had learned from the first wave of XP projects.

Now there are quite a few XP books out there, and they are actually a very good bunch. But one valid
complaint is that they are all somewhat similar. As a result, if you already have several XP books I'm not
sure that you'll much that's new in this one. I think the primary value of this book lies in its sole focus on
planning. If you're in a management or customer role on an XP project, then the technical practices don't
matter that much to you. In which case a book that concentrates solely on the planning side is a good one
to pick.

http://martinfowler.com/books.html (4 of 8)05/12/2003 15:35:44


Books by Martin Fowler

I also think that this is a good book even if you aren't into XP itself, but you do want to plan an iterative
and agile project. One of the features of agility is that you recognize that software development is rarely a
predictable process. But often that results in a different problem - where people don't really plan at all, or
do plans that have little relationship with reality. The nice thing about XP's planning scheme is that it
gives you control in a changing environment. So while you lose predictivity you don't lose control - and
control is essential to successfully running an iterative project.

Translations: Japanese, German, Simplified Chinese, Traditional Chinese, Russian

Further Reading

Links
My links page links to various further resources on XP and agile methods
Articles
I've written several articles about agile software development
The New Methodology
An outline article that explains what agile methods are all about
Manifesto for Agile Software Development
I was one of the authors of this surprisingly influential polemic

Analysis Patterns: Reusable Object Models


On Amazon

My first book, and yes I admit it's showing its age. But it's still one of very few books that
have tried to tackle this kind of material. It's about trying to find patterns in domain
models of businesses, and is based on much of the domain modeling work that I did (and
still love doing) in the late 80's and early 90's.

The patterns come from various domains, including health care, financial trading, and accounting. Each of
the patterns is described both textually and in a simple pre-UML notation (this book was written before the
UML had stabilized into a usable form).

There's much I could do to improve the presentation of the patterns in this book with what I've learned
since. The core patterns themselves, have stood up surprisingly well to the test of time. There's very little
here in the core content that I would change, but there's much I could add and I think I could now make
them a lot easier to understand.

Translations: German, Japanese, Chinese

http://martinfowler.com/books.html (5 of 8)05/12/2003 15:35:44


Books by Martin Fowler

Further Reading

Articles
At one point I did embark on reworking some of the patterns and adding new ones. That effort has
stalled for a while, I hope to pick it up someday. Until then, here are some of the more up to date
ideas and presentations of the patterns.

My Signature Series
In 2002 Addison-Wesley launched their signature series. The idea is that their leading authors would host
a small series of books that they felt were particularly special. Kent Beck and I were selected to be the first
"signers". In this series I'm getting involved in, and recommending, books that I wish I could have written.

Beyond Software Architecture: Creating and Sustaining Winning


Solutions

by Luke Hohmann
On Amazon

Architecture has become a very slippery word in the software business. It's hard to
come up with any solid definition of what it means. I see it as a fundamentally
subjective term - when people describe their software architecture they select the
important parts of their systems, how these parts fit together, and the key decisions
they made in designing their systems. Architecture is also seen as a technical issue,
with the implication that the key decisions that need to be made are technical
decisions.

In talking with Luke over the last few years I've really enjoyed the fact that he talks about the kinds of
things that are often sadly omitted from most architectural discussions - yet are every bit as important.
Such things as the marketing view of a system, licensing terms, branding, deployment, billing. All of these
issues have important technical and business implications. Senior technical people need to think about this
stuff, or otherwise a technically capable system could fail to be good business decision.

Many of these issues matter most to people who sell software to other entities. But even if you're an

http://martinfowler.com/books.html (6 of 8)05/12/2003 15:35:44


Books by Martin Fowler

architect of an in-house IS shop these issues are just as likely to trip you up. Licensing agreements with
your vendors can make a big difference to the costs of the software you deploy, billing may become
important if your business decides it wants to introduce a charge-back scheme, branding helps affect your
visibility to the business side of your company.

Luke writes from the perspective of someone who has dealt with both the technical and business sides of
software development. It's a duality I find appealing because it's led him to ponder issues that often don't
get talked about. He shows that it's often the things you don't think to worry about that hurt you the most
and in the process provides the advice you need to deal with them. As a result this book is a much needed
compliment to the technical aspects of software design.

Further Reading

Luke's Home Page


Here you can find more information about the book, as well as other papers that Luke has written.

Enterprise Integration Patterns : Designing, Building, and


Deploying Messaging Solutions
On Amazon

While I was working on P of EAA, I was lucky to get some in-depth review from
Kyle Brown and Rachel Reinitz at some informal workshops at Kyle's office in
Raleigh-Durham. During these sessions, we realized that a big gap in my work
was asynchronous messaging systems.

There are many gaps in my book, and I never intended it to be a complete


collection of patterns for enterprise development. But the gap on asynchronous
messaging is particularly important because we believe that asynchronous
messaging will play an increasingly important role in enterprise software development, particularly in
integration. Integration is important because applications cannot live isolated from each other. We need
techniques that allow us to take applications that were never designed to interoperate and break down the
stovepipes so we can gain a greater benefit than the individual applications can offer us.

Various technologies have been around that promise to solve the integration puzzle. We all concluded that
messaging is the technology that carries the greatest promise. The challenge we faced was to convey how
to do messaging effectively. The biggest challenge in this is that messages are by their nature
asynchronous, and there are significant differences in the design approaches that you use in an
asynchronous world.

http://martinfowler.com/books.html (7 of 8)05/12/2003 15:35:44


Books by Martin Fowler

I didn't have space, energy, or frankly the knowledge to cover this topic properly in P of EAA . But we
came up with a better solution to this gap: find someone else who could. We hunted down Gregor and
Bobby, and they took up the challenge. This book is the result.

I'm delighted with the job that they have done. If you've already worked with messaging systems, this
book will systematize much of the knowledge that you and others have already learned the hard way. If
you are about to work with messaging systems, this book will provide a foundation that will be invaluable
no matter which messaging technology you have to work with.

Further Reading

Enterprise Integration Patterns Web Site


Gregor maintains a site with a lot more information on enterprise integration with messaging.

© Copyright Martin Fowler, all rights reserved

http://martinfowler.com/books.html (8 of 8)05/12/2003 15:35:44


About Martin Fowler

About Contact
Home Blog Articles Books ThoughtWorks
Me Me

About Martin Fowler


Last Significant Update: Apr 03

I'm an author, speaker, consultant and general loud-mouth on software development. I concentrate on
designing enterprise software - looking at what makes a good design and what practices are needed to
come up with good design. I've pioneered object-oriented technology, refactoring, patterns, agile
methodologies, domain modeling, the Unified Modeling Language (UML), and Extreme Programming.

I have the august sounding title of Chief Scientist at ThoughtWorks - a cutting edge system delivery and
consulting firm. I've been here since March 2000 when I gave up my long and successful career as an
independent consultant because I'd found a company that I believed was truly world beating.

I started working with software in the early 80's and in the mid 80's I started getting interested in the then
new world of object-oriented development. I started to specialize in bringing objects to business
information systems, first with a couple of companies and then as an independent consultant. In the early
days this was using Smalltalk and C++, now it's Java, C# and the Internet. Every year I learn something
new, but I also find that many of the lessons from the past still apply. This work has led me into taking a
leading role in OO analysis and design, the UML, patterns, and agile development methodologies.

http://martinfowler.com/aboutMe.html (1 of 3)05/12/2003 15:35:45


About Martin Fowler

I've written five books on software development. Analysis Patterns are those repetitive ideas that I have
come across in the business (domain) modeling that I have done during my career. As such they bring
together the important areas of patterns and business object development. I also wrote UML Distilled a
concise overview (under half an inch!) of the notation, semantics, and an iterative development process. It
won a Software Development Productivity award in 1998 and is now available in a second edition.
Refactoring describes how to alter the design of existing software in a controlled and rapid manner. I
wrote Planning Extreme Programming with Kent Beck - it describes how to do the intensive planning that
XP demands. My latest book is Patterns of Enterprise Application Architecture.

I speak at many international conferences on software development. I've served on program committees
for OOPSLA, Software Development, UML World, XP 2001, and TOOLS. I have been a columnist for
Distributed Computing magazine, now I'm on the advisory board for Software Development magazine and
IEEE Software where I also edit the design column.

Much of my work these days is with clients of ThoughtWorks, but I still do some outside work - including
speaking at corporate events and particularly interesting projects. If you want to find out more about
getting hold of me contact my assistant Cameron Reiss who can fill you in on my availability, and on the
various things I can do with my able colleagues here at ThoughtWorks.

I became an independent consultant in 1991 and since then have seen a lot of companies as a consultant.
While I've enjoyed a lot of this work, I'd never imagined joining any of them. This was partly because of
the fact that I wanted the independence to do the writing that's become an important part of my life, but
also because I hadn't come across an organization that was the sort of company I'd like to work for.

I started working with ThoughtWorks in the spring of 1999 and found a company whose attitude to people
and customers fitted remarkably with my own views. They build the kind of mission critical business
systems that I like to be involved in with the quality that I always aim for. But the key reason I joined
them is because they really do believe that people are their biggest asset. I've seen many companies say
that as a cliche, but not here. And that to me is essential because I believe the biggest impact on successful
software development is motivated, talented developers. If you don't have that all the technology and
methodology in the world can't help you. By hiring and keeping the best people, ThoughtWorks have the
key to succeed in this business - and I do enjoy being around the best.

I live in Melrose, a pleasant suburb of Boston MA with my wife Cindy, a structural engineer, and we like
to get out of doors in our spare time. Summer finds us cycling around New England and hiking wherever
we can get to. Winter finds us cross-country skiing and hiking in New England's sometimes plentiful
snow. I was born in Walsall, England and lived in London for a decade before coming to New England in
1994. I enjoy living in the US even though I miss the beer, the deep pointlessness of Cricket, and the
English countryside.

Contact Information

http://martinfowler.com/aboutMe.html (2 of 3)05/12/2003 15:35:45


About Martin Fowler

Martin Fowler
Chief Scientist, ThoughtWorks
651 W Washington Blvd, Suite 500, Chicago, IL 60661, USA
mailto:fowler@acm.org, http://www.martinfowler.com

I'm afraid that due to the very high volume of email that I receive, I'm no longer able to answer any email
questions.

If you are interested in having me do some consulting or giving a talk, the best person to contact is my
assistant:
Cameron Reiss: (312) 373 8690, mailto:CLReiss@thoughtworks.com.

Cameron can also help direct you to the right people in ThoughtWorks for our consulting work in
application development, enterprise application architecture, agile methods, and EAI. Or take a look at
thoughtworks.com.

Revision History

Here's a list of the major updates to this paper

● Apr 03: First posting

© Copyright Martin Fowler, all rights reserved

http://martinfowler.com/aboutMe.html (3 of 3)05/12/2003 15:35:45


ThoughtWorks Inc. - The Art Of Heavy Lifting

NOVEMBER 26
ThoughtWorks is a systems integrator serving 2003/
Global 1000 companies from offices in the United ThoughtWorks®, Inc.
States, Canada, United Kingdom, Australia, and Holds Open House
India. Our leadership in the application of Agile Events on Dec. 9-10
methods allows us to deliver high-value solutions to to Mark New
clients sooner - and in a way that reduces risk, Columbus-area
accelerates time to market, and ensures system Office Grand
quality. Opening, IT and
ThoughtWorks is widely recognized as the thought Business Leaders
leader in Enterprise Agile: the practical application Invited to Attend
of Agile methods for large enterprises. Our history
of using Agile methods to successfully deliver on NOVEMBER 12
enterprise-class projects has been documented in 2003/
CIO, ComputerWorld, and a host of industry-
Software Pioneer and
specific publications.
ThoughtWorks®, Inc.
With an integrated Global Delivery Model, a depth Chief Scientist Martin
of "heavy lifting" technology skills, and Fowler to Present
acknowledged leadership in the application of Agile Seminar on Agile
methods, ThoughtWorks is well-positioned to bring Methodologies
new power and agility to today's global leaders.

NOVEMBER 11
2003/
ThoughtWorks®, Inc.
Opens New
Columbus-Area
Office

©2003 ThoughtWorks, Inc. info@thoughtworks.com www.martinfowler.com www.eaipatterns.com

http://www.thoughtworks.com/05/12/2003 15:35:58
The New Methodology

About Contact
Home Blog Articles Books ThoughtWorks
Me Me

The New Methodology


Martin Fowler

Last Significant Update: April 2003

In the past few years there's been a rapidly growing interest in agile (aka "lightweight") methodologies.
Alternatively characterized as an antidote to bureaucracy or a license to hack they've stirred up interest
all over the software landscape. In this essay I explore the reasons for agile methods, focusing not so
much on their weight but on their adaptive nature and their people-first orientation. I also give a summary
and references to the processes in this school and consider the factors that should influence your choice of
whether to go down this newly trodden path.

| Japanese | Russian | French | Chinese | Turkish | Indonesian | German | Spanish |

● From Nothing, to Monumental, to Agile


● Predictive versus Adaptive
❍ Separation of Design and Construction

❍ The Unpredictability of Requirements

❍ Is Predictability Impossible?

❍ Controlling an Unpredictable Process - Iterations

❍ The Adaptive Customer

● Putting People First


❍ Plug Compatible Programming Units

❍ Programmers are Responsible Professionals

❍ Managing a People Oriented Process

❍ The Difficulty of Measurement

❍ The Role of Business Leadership

● The Self-Adaptive Process


● The Methodologies
❍ XP (Extreme Programming)

❍ Cockburn's Crystal Family

❍ Open Source

❍ Highsmith's Adaptive Software Development

❍ Scrum

http://www.martinfowler.com/articles/newMethodology.html (1 of 22)05/12/2003 15:36:01


The New Methodology

Feature Driven Development


❍ DSDM (Dynamic System Development Method)

❍ The Manifesto for Agile Software Development

❍ Context Driven Testing

❍ Is RUP an agile method?

❍ Other Sources

● Should you go agile?


● Acknowledgments

From Nothing, to Monumental, to Agile


Most software development is a chaotic activity, often characterized by the phrase "code and fix". The
software is written without much of an underlying plan, and the design of the system is cobbled together
from many short term decisions. This actually works pretty well as the system is small, but as the system
grows it becomes increasingly difficult to add new features to the system. Furthermore bugs become
increasingly prevalent and increasingly difficult to fix. A typical sign of such a system is a long test phase
after the system is "feature complete". Such a long test phase plays havoc with schedules as testing and
debugging is impossible to schedule.

We've lived with this style of development for a long time, but we've also had an alternative for a long
time: Methodology. Methodologies impose a disciplined process upon software development with the aim
of making software development more predictable and more efficient. They do this by developing a
detailed process with a strong emphasis on planning inspired by other engineering disciplines - which is
why I tend to refer to them as engineering methodologies.

Engineering methodologies have been around for a long time. They've not been noticeable for being
terribly successful. They are even less noted for being popular. The most frequent criticism of these
methodologies is that they are bureaucratic. There's so much stuff to do to follow the methodology that the
whole pace of development slows down.

As a reaction to these methodologies, a new group of methodologies have appeared in the last few years.
For a while these were known a lightweight methodologies, but now the accepted term is agile
methodologies. For many people the appeal of these agile methodologies is their reaction to the
bureaucracy of the monumental methodologies. These new methods attempt a useful compromise between
no process and too much process, providing just enough process to gain a reasonable payoff.

The result of all of this is that agile methods have some significant changes in emphasis from engineering
methods. The most immediate difference is that they are less document-oriented, usually emphasizing a
smaller amount of documentation for a given task. In many ways they are rather code-oriented: following
a route that says that the key part of documentation is source code.

However I don't think this is the key point about agile methods. Lack of documentation is a symptom of

http://www.martinfowler.com/articles/newMethodology.html (2 of 22)05/12/2003 15:36:01


The New Methodology

two much deeper differences:

● Agile methods are adaptive rather than predictive. Engineering methods tend to try to plan out a
large part of the software process in great detail for a long span of time, this works well until things
change. So their nature is to resist change. The agile methods, however, welcome change. They try
to be processes that adapt and thrive on change, even to the point of changing themselves.
● Agile methods are people-oriented rather than process-oriented. The goal of engineering methods
is to define a process that will work well whoever happens to be using it. Agile methods assert that
no process will ever make up the the skill of the development team, so the role of a process is to
support the development team in their work.

In the following sections I'll explore these differences in more detail, so that you can understand what an
adaptive and people-centered process is like, its benefits and drawbacks, and whether it's something you
should use: either as a developer or customer of software.

Predictive versus Adaptive

Separation of Design and Construction

The usual inspiration for methodologies is engineering disciplines such as civil or mechanical engineering.
Such disciplines put a lot of emphasis on planning before you build. Such engineers will work on a series
of drawings that precisely indicate what needs to be built and how these things need to be put together.
Many design decisions, such as how to deal with the load on a bridge, are made as the drawings are
produced. The drawings are then handed over to a different group, often a different company, to be built.
It's assumed that the construction process will follow the drawings. In practice the constructors will run
into some problems, but these are usually small.

Since the drawings specify the pieces and how they need to be put together, they act as the foundation for
a detailed construction plan. Such a plan can figure out the tasks that need to be done and what
dependencies exist between these tasks. This allows for a reasonably predictable schedule and budget for
construction. It also says in detail how the people doing the construction work should do their work. This
allows the construction to be less skilled intellectually, although they are often very skilled manually.

So what we see here are two fundamentally different activities. Design which is difficult to predict and
requires expensive and creative people, and construction which is easier to predict. Once we have the
design, we can plan the construction. Once we have the plan for the construction, we can then deal with
construction in a much more predictable way. In civil engineering construction is much bigger in both cost
and time than design and planning.

So the approach for software engineering methodologies looks like this: we want a predictable schedule
that can use people with lower skills. To do this we must separate design from construction. Therefore we
need to figure out how to do the design for software so that the construction can be straightforward once

http://www.martinfowler.com/articles/newMethodology.html (3 of 22)05/12/2003 15:36:01


The New Methodology

the planning is done.

So what form does this plan take? For many, this is the role of design notations such as the UML. If we
can make all the significant decisions using the UML, we can build a construction plan and then hand
these designs off to coders as a construction activity.

But here lies the crucial question. Can you get a design that is capable of turning the coding into a
predictable construction activity? And if so, is cost of doing this sufficiently small to make this approach
worthwhile?

All of this brings a few questions to mind. The first is the matter of how difficult it is to get a UML-like
design into a state that it can be handed over to programmers. The problem with a UML-like design is that
it can look very good on paper, yet be seriously flawed when you actually have to program the thing. The
models that civil engineers use are based on many years of practice that are enshrined in engineering
codes. Furthermore the key issues, such as the way forces play in the design, are amenable to
mathematical analysis. The only checking we can do of UML-like diagrams is peer review. While this is
helpful it leads to errors in the design that are often only uncovered during coding and testing. Even skilled
designers, such as I consider myself to be, are often surprised when we turn such a design into software.

Another issue is that of comparative cost. When you build a bridge, the cost of the design effort is about
10% of the job, with the rest being construction. In software the amount of time spent in coding is much,
much less McConnell suggests that for a large project, only 15% of the project is code and unit test, an
almost perfect reversal of the bridge building ratios. Even if you lump in all testing as part of construction,
then design is still 50% of the work. This raises an important question about the nature of design in
software compared to its role in other branches of engineering.

These kinds of questions led Jack Reeves to suggest that in fact the source code is a design document and
that the construction phase is actually the use of the compiler and linker. Indeed anything that you can
treat as construction can and should be automated.

This thinking leads to some important conclusions:

● In software: construction is so cheap as to be free


● In software all the effort is design, and thus requires creative and talented people
● Creative processes are not easily planned, and so predictability may well be an impossible target.
● We should be very wary of the traditional engineering metaphor for building software. It's a
different kind of activity and requires a different process

The Unpredictability of Requirements

There's a refrain I've heard on every problem project I've run into. The developers come to me and say
"the problem with this project is that the requirements are always changing". The thing I find surprising

http://www.martinfowler.com/articles/newMethodology.html (4 of 22)05/12/2003 15:36:01


The New Methodology

about this situation is that anyone is surprised by it. In building business software requirements changes
are the norm, the question is what we do about it.

One route is to treat changing requirements as the result of poor requirements engineering. The idea
behind requirements engineering is to get a fully understood picture of the requirements before you begin
building the software, get a customer sign-off to these requirements, and then set up procedures that limit
requirements changes after the sign-off.

One problem with this is that just trying to understand the options for requirements is tough. It's even
tougher because the development organization usually doesn't provide cost information on the
requirements. You end up being in the situation where you may have some desire for a sun roof on your
car, but the salesman can't tell you if it adds $10 to the cost of the car, or $10,000. Without much idea of
the cost, how can you figure out whether you want to pay for that sunroof?

Estimation is hard for many reasons. Part of it is that software development is a design activity, and thus
hard to plan and cost. Part of it is that the basic materials keep changing rapidly. Part of it is that so much
depends on which individual people are involved, and individuals are hard to predict and quantify.

Software's intangible nature also cuts in. It's very difficult to see what value a software feature has until
you use it for real. Only when you use an early version of some software do you really begin to understand
what features are valuable and what parts are not.

This leads to the ironic point that people expect that requirements should be changeable. After all software
is supposed to be soft. So not just are requirements changeable, they ought to be changeable. It takes a lot
of energy to get customers of software to fix requirements. It's even worse if they've ever dabbled in
software development themselves, because then they "know" that software is easy to change.

But even if you could settle all that and really could get an accurate and stable set of requirements you're
probably still doomed. In today's economy the fundamental business forces are changing the value of
software features too rapidly. What might be a good set of requirements now, is not a good set in six
months time. Even if the customers can fix their requirements, the business world isn't going to stop for
them. And many changes in the business world are completely unpredictable: anyone who says otherwise
is either lying, or has already made a billion on stock market trading.

Everything else in software development depends on the requirements. If you cannot get stable
requirements you cannot get a predictable plan.

Is Predictability Impossible?

In general, no. There are some software developments where predictability is possible. Organizations such
as NASA's space shuttle software group are a prime example of where software development can be
predictable. It requires a lot of ceremony, plenty of time, a large team, and stable requirements. There are
projects out there that are space shuttles. However I don't think much business software fits into that

http://www.martinfowler.com/articles/newMethodology.html (5 of 22)05/12/2003 15:36:01


The New Methodology

category. For this you need a different kind of process.

One of the big dangers is to pretend that you can follow a predictable process when you can't. People who
work on methodology are not very good at identifying boundary conditions: the places where the
methodology passes from appropriate in inappropriate. Most methodologists want their methodologies to
be usable by everyone, so they don't understand nor publicize their boundary conditions. This leads to
people using a methodology in the wrong circumstances, such as using a predictable methodology in a
unpredictable situation.

There's a strong temptation to do that. Predictability is a very desirable property. However if you believe
you can be predictable when you can't, it leads to situations where people build a plan early on, then don't
properly handle the situation where the plan falls apart. You see the plan and reality slowly drifting apart.
For a long time you can pretend that the plan is still valid. But at some point the drift becomes too much
and the plan falls apart. Usually the fall is painful.

So if you are in a situation that isn't predictable you can't use a predictive methodology. That's a hard
blow. It means that many of the models for controlling projects, many of the models for the whole
customer relationship, just aren't true any more. The benefits of predictability are so great, it's difficult to
let them go. Like so many problems the hardest part is simply realizing that the problem exists.

However letting go of predictability doesn't mean you have to revert to uncontrollable chaos. Instead you
need a process that can give you control over an unpredictability. That's what adaptivity is all about.

Controlling an Unpredictable Process - Iterations

So how do we control ourselves in an unpredictable world? The most important, and still difficult part is to
know accurately where we are. We need an honest feedback mechanism which can accurately tell us what
the situation is at frequent intervals.

The key to this feedback is iterative development. This is not a new idea. Iterative development has been
around for a while under many names: incremental, evolutionary, staged, spiral... lots of names. The key
to iterative development is to frequently produce working versions of the final system that have a subset of
the required features. These working systems are short on functionality, but should otherwise be faithful to
the demands of the final system. They should be fully integrated and as carefully tested as a final delivery.

The point of this is that there is nothing like a tested, integrated system for bringing a forceful dose of
reality into any project. Documents can hide all sorts of flaws. Untested code can hide plenty of flaws. But
when people actually sit in front of a system and work with it, then flaws become truly apparent: both in
terms of bugs and in terms of misunderstood requirements.

Iterative development makes sense in predictable processes as well. But it is essential in adaptive
processes because an adaptive process needs to be able to deal with changes in required features. This
leads to a style of planning where long term plans are very fluid, and the only stable plans are short term

http://www.martinfowler.com/articles/newMethodology.html (6 of 22)05/12/2003 15:36:01


The New Methodology

plans that are made for a single iteration. Iterative development gives you a firm foundation in each
iteration that you can base your later plans around.

A key question for this is how long an iteration should be. Different people give different answers. XP
suggests iterations of between one and three weeks. SCRUM suggests a length of a month. Crystal will
stretch further. The tendency, however, is to make each iteration as short as you can get away with. This
provides more frequent feedback, so you know where you are more often.

The Adaptive Customer

This kind of adaptive process requires a different kind of relationship with a customer than the ones that
are often considered, particularly when development is done by a separate firm. When you hire a separate
firm to do software development, most customers would prefer a fixed-price contract. Tell the developers
what they want, ask for bids, accept a bid, and then the onus is on the development organization to build
the software.

A fixed price contract requires stable requirements and hence a predictive process. Adaptive processes and
unstable requirements imply you cannot work with the usual notion of fixed-price. Trying to fit a fixed
price model to an adaptive process ends up in a very painful explosion. The nasty part of this explosion is
that the customer gets hurt every bit as much as the software development company. After all the customer
wouldn't be wanting some software unless their business needed it. If they don't get it their business
suffers. So even if they pay the development company nothing, they still lose. Indeed they lose more than
they would pay for the software (why would they pay for the software if the business value of that
software were less?)

So there's dangers for both sides in signing a fixed price contract in conditions where a predictive process
cannot be used. This means that the customer has to work differently.

This doesn't mean that you can't fix a budget for software up-front. What it does mean is that you cannot
fix time, price and scope. The usual agile approach is to fix time and price, and to allow the scope to vary
in a controlled manner.

In an adaptive process the customer has much finer-grained control over the software development
process. At every iteration they get both to check progress and to alter the direction of the software
development. This leads to much closer relationship with the software developers, a true business
partnership. This level of engagement is not for every customer organization, nor for every software
developer; but it's essential to make an adaptive process work properly.

All this yields a number of advantages for the customer. For a start they get much more responsive
software development. A usable, although minimal, system can go into production early on. The customer
can then change its capabilities according to changes in the business, and also from learning from how the
system is used in reality.

http://www.martinfowler.com/articles/newMethodology.html (7 of 22)05/12/2003 15:36:01


The New Methodology

Every bit as important as this is greater visibility into the true state of the project. The problem with
predictive processes is that project quality is measured by conformance to plan. This makes it difficult for
people to signal when reality and the plan diverge. The common result is a big slip in the schedule late in
the project. In an agile project there is a constant reworking of the plan with every iteration. If bad news is
lurking it tends to come earlier, when there is still time to do something about it. Indeed this risk control is
a key advantage of iterative development. Agile methods take this further by keeping the iteration lengths
small, but also by seeing these variations as opportunities.

This has an important bearing what constitutes a successful project. A predictive project is often measured
by how well it met its plan. A project that's on-time and on-cost is considered to be a success. This
measurement is nonsense to an agile environment. For agilists the question is business value - did the
customer get software that's more valuable to them them than the cost put into it. A good predictive
project will go according to plan, a good agile project will build something different and better than the
original plan foresaw.

Putting People First


Executing an adaptive process is not easy. In particular it requires a very effective team of developers. The
team needs to be effective both in the quality of the individuals, and in the way the team blends together.
There's also an interesting synergy: not just does adaptivity require a strong team, most good developers
prefer an adaptive process.

Plug Compatible Programming Units

One of the aims of traditional methodologies is to develop a process where the people involved are
replaceable parts. With such a process you can treat people as resources who are available in various
types. You have an analyst, some coders, some testers, a manager. The individuals aren't so important,
only the roles are important. That way if you plan a project it doesn't matter which analyst and which
testers you get, just that you know how many you have so you know how the number of resources affects
your plan.

But this raises a key question: are the people involved in software development replaceable parts? One of
the key features of agile methods is that they reject this assumption.

Perhaps the most explicit rejection of people as resources is Alistair Cockburn. In his paper Characterizing
People as Non-Linear, First-Order Components in Software Development, he makes the point that
predictable processes require components that behave in a predictable way. However people are not
predictable components. Furthermore his studies of software projects have led him to conclude the people
are the most important factor in software development.

In the title, [of his article] I refer to people as "components". That is how people are treated
in the process / methodology design literature. The mistake in this approach is that "people"

http://www.martinfowler.com/articles/newMethodology.html (8 of 22)05/12/2003 15:36:01


The New Methodology

are highly variable and non-linear, with unique success and failure modes. Those factors
are first-order, not negligible factors. Failure of process and methodology designers to
account for them contributes to the sorts of unplanned project trajectories we so often see.
-- [Cockburn non-linear]

One wonders if not the nature of software development works against us here. When we're programming a
computer, we control an inherently predictable device. Since we're in this business because we are good at
doing that, we are ideally suited to messing up when faced with human beings.

Although Cockburn is the most explicit in his people-centric view of software development, the notion of
people first is a common theme with many thinkers in software. The problem, too often, is that
methodology has been opposed to the notion of people as the first-order factor in project success.

This creates a strong positive feedback effect. If you expect all your developers to be plug compatible
programming units, you don't try to treat them as individuals. This lowers morale (and productivity). The
good people look for a better place to be, and you end up with what you desire: plug compatible
programming units.

Deciding that people come first is a big decision, one that requires a lot of determination to push through.
The notion of people as resources is deeply ingrained in business thinking, its roots going back to the
impact of Frederick Taylor's Scientific Management approach. In running a factory, this Taylorist
approach may make sense. But for the highly creative and professional work, which I believe software
development to be, this does not hold. (And in fact modern manufacturing is also moving away from the
Taylorist model.)

Programmers are Responsible Professionals

A key part of the Taylorist notion is that the people doing the work are not the people who can best figure
out how best to do that work. In a factory this may be true for several reasons. Part of this is that many
factory workers are not the most intelligent or creative people, in part this is because there is a tension
between management and workers in that management makes more money when the workers make less.

Recent history increasingly shows us how untrue this is for software development. Increasingly bright and
capable people are attracted to software development, attracted by both its glitz and by potentially large
rewards. (Both of which tempted me away from electronic engineering.) Such schemes as stock options
increasingly align the programmers interests with the company's.

(There may well be a generational effect here. Some anecdotal evidence makes me wonder if more
brighter people have ventured into software engineering in the last ten years or so. If so this would be a
reason for why there is such a cult of youth in the computer business, like most cults there needs to be a
grain of truth in it.)

http://www.martinfowler.com/articles/newMethodology.html (9 of 22)05/12/2003 15:36:01


The New Methodology

When you want to hire and retain good people, you have to recognize that they are competent
professionals. As such they are the best people to decide how to conduct their technical work. The
Taylorist notion of a separate planning department that decides how to do things only works if the
planners understand how to do the job better than those doing it. If you have bright, motivated people
doing the job then this does not hold.

Managing a People Oriented Process

People orientation manifests itself in a number of different ways in agile processes. It leads to different
effects, not all of them are consistent.

One of the key elements is that of accepting the process rather than the imposition of a process. Often
software processes are imposed by management figures. As such they are often resisted, particularly when
the management figures have had a significant amount of time away from active development. Accepting
a process requires commitment, and as such needs the active involvement of all the team.

This ends up with the interesting result that only the developers themselves can choose to follow an
adaptive process. This is particularly true for XP, which requires a lot of discipline to execute. This is
where Crystal is such an effective complement as it aims at being minimally disciplined.

Another point is that the developers must be able to make all technical decisions. XP gets to the heart of
this where in its planning process it states that only developers may make estimates on how much time it
will take to do some work.

Such technical leadership is a big shift for many people in management positions. Such an approach
requires a sharing of responsibility where developers and management have an equal place in the
leadership of the project. Notice that I say equal. Management still plays a role, but recognizes the
expertise of developers.

An important reason for this is the rate of change of technology in our industry. After a few years
technical knowledge becomes obsolete. This half life of technical skills is without parallel in any other
industry. Even technical people have to recognize that entering management means their technical skills
will wither rapidly. Ex-developers need to recognize that their technical skills will rapidly disappear and
they need to trust and rely on current developers.

The Difficulty of Measurement

If you have a process where the people who say how work should be done are different from the people
who actually do it, the leaders need some way of measuring how effective the doers are. In Scientific
Management there was a strong push to develop objective approaches to measuring the output of people.

This is particularly relevant to software because of the difficulty of applying measurement to software.

http://www.martinfowler.com/articles/newMethodology.html (10 of 22)05/12/2003 15:36:01


The New Methodology

Despite our best efforts we are unable to measure the most simple things about software, such as
productivity. Without good measures for these things, any kind of external control is doomed.

Introducing measured management without good measures leads to its own problems. Robert Austin made
an excellent discussion of this. He points out that when measuring performance you have to get all the
important factors under measurement. Anything that's missing has the inevitable result that the doers will
alter what they do to produce the best measures, even if that clearly reduces the true effectiveness of what
they do. This measurement dysfunction is the Achilles heel of measurement-based management.

Austin's conclusion is that you have to choose between measurement-base management and delagatory
management (where the doers decide how to the work). Measurement-based management is best suited to
repetitive simple work, with low knowledge requirements and easily measured outputs - exactly the
opposite of software development.

The point of all this is that traditional methods have operated under the assumption that measurement-
based management is the most efficient way of managing. The agile community recognizes that the
characteristics of software development are such that measurement based management leads to very high
levels of measurement dysfunction. It's actually more efficient to use a delegatory style of management,
which is the kind of approach that is at the center of the agilist viewpoint.

The Role of Business Leadership

But the technical people cannot do the whole process themselves. They need guidance on the business
needs. This leads to another important aspect of adaptive processes: they need very close contact with
business expertise.

This goes beyond most projects involvement of the business role. Agile teams cannot exist with occasional
communication . They need continuous access to business expertise. Furthermore this access is not
something that is handled at a management level, it is something that is present for every developer. Since
developers are capable professionals in their own discipline, they need to be able to work as equals with
other professionals in other disciplines.

A large part of this, of course, is due to the nature of adaptive development. Since the whole premise of
adaptive development is that things change quickly, you need constant contact to advise everybody of the
changes.

There is nothing more frustrating to a developer than seeing their hard work go to waste. So it's important
to ensure that there is good quality business expertise that is both available to the developer and is of
sufficient quality that the developer can trust them.

The Self-Adaptive Process

http://www.martinfowler.com/articles/newMethodology.html (11 of 22)05/12/2003 15:36:01


The New Methodology

So far I've talked about adaptivity in the context of a project adapting its software frequently to meet the
changing requirements of its customers. However there's another angle to adaptivity: that of the process
changing over time. A project that begins using an adaptive process won't have the same process a year
later. Over time, the team will find what works for them, and alter the process to fit.

The first part of self-adaptivity is regular reviews of the process. Usually you do these with every iteration.
At the end of each iteration, have a short meeting and ask yourself the following questions (culled from
Norm Kerth)

● What did we do well?


● What have we learned?
● What can we do better?
● What puzzles us?

These questions will lead you to ideas to change the process for the next iteration. In this way a process
that starts off with problems can improve as the project goes on, adapting better to the team that uses it.

If self-adaptivity occurs within a project, it's even more marked across an organization. To deepen the
process of self-adaptivity I suggest teams do a more formal review and major project milestones following
the project retrospective sessions outlined by Norm Kerth. These retrospectives involve a 2-3 day offsite
meeting and a trained facilitator. Not only do they provide learning for the team, they also provide
learning for the whole organization.

A consequence of self-adaptivity is that you should never expect to find a single corporate methodology.
Instead each team should not just choose their own process, but should also actively tune their process as
they proceed with the project. While both published processes and the experience of other projects can act
as an inspiration and a baseline, the developers professional responsibility is to adapt the process to the
task at hand.

This self-adaptivity is most marked in ASD and Crystal. XP's rigid rules seem to disallow it, but that is
only a surface impression since XP does encourage people to tune the process. The main difference with
XP is that its advocates suggest doing XP by the book for several iterations before adapting it. In addition
reviews are neither emphasized, nor part of the process, although there are suggestions that reviews should
be made one of the XP practices.

The Methodologies
Several methodologies fit under this agile banner. While all of them share many characteristics, there are
also some significant differences. I can't highlight all the points in this brief survey, but at least I can point
you to some places to look. I also can't speak with significant experience about most of these. I've done
quite a lot of work based on XP, and seen RUP around in many guises, but with most of the others my
knowledge is primarily the less adequate book knowledge.

http://www.martinfowler.com/articles/newMethodology.html (12 of 22)05/12/2003 15:36:01


The New Methodology

XP (Extreme Programming)

Of all the agile methodologies, this is the one that has got the most attention. Partly this is because of the
remarkable ability of the leaders of XP, in particular Kent Beck, to get attention. It's also because of the
ability of Kent Beck to attract people to the approach, and to take a leading role in it. In some ways,
however, the popularity of XP has become a problem, as it has rather crowded out the other methodologies
and their valuable ideas.

The roots of XP lie in the Smalltalk community, and in particular the close collaboration of Kent Beck and
Ward Cunningham in the late 1980's. Both of them refined their practices on numerous projects during the
early 90's, extending their ideas of a software development approach that was both adaptive and people-
oriented.

The crucial step from informal practice to a methodology occurred in the spring of 1996. Kent was asked
to review the progress of the C3 payroll project for Chrysler. The project was being carried out in
Smalltalk by a contracting company, and was in trouble. Due to the low quality of the code base, Kent
recommended throwing out the entire code base and starting from scratch. The project then restarted under
his leadership and since became the early flagship and training ground for XP.

The first phase of C3 was very successful and went live in early 1997. The project continued since and ran
into difficulties later, which resulted in the canceling of further development in 1999. (which if nothing
else proves that XP is no guarantee of success.)

XP begins with four values: Communication, Feedback, Simplicity, and Courage. It then builds up to a
dozen practices which XP projects should follow. Many of these practices are old, tried and tested
techniques, yet often forgotten by many, including most planned processes. As well as resurrecting these
techniques, XP weaves them into a synergistic whole where each one is reinforced by the others.

One of the most striking, as well as initially appealing to me, is its strong emphasis on testing. While all
processes mention testing, most do so with a pretty low emphasis. However XP puts testing at the
foundation of development, with every programmer writing tests as they write their production code. The
tests are integrated into a continuous integration and build process which yields a highly stable platform
for future development.

On this platform XP builds an evolutionary design process that relies on refactoring a simple base system
with every iteration. All design is centered around the current iteration with no design done for anticipated
future needs. The result is a design process that is disciplined, yet startling, combining discipline with
adaptivity in a way that arguably makes it the most well developed of all the adaptive methodologies.

XP has developed a wide leadership, many of them springing from the seminal C3 project. As a result
there's a lot of sources for more information. Kent Beck wrote Extreme Programming Explained the key
manifesto of XP, which explains the rationale behind the methodology and enough of an explanation of it

http://www.martinfowler.com/articles/newMethodology.html (13 of 22)05/12/2003 15:36:01


The New Methodology

to tell folks if they are interested in pursuing it further. In the last couple of years there's been an epidemic
of brightly colored XP books, most of which are pretty similar in that they describe the whole process
from the point of view of various early adopters.

As well as books, there are a fair number of web resources. To find a more structured approach to XP, it's
best to start with two sites from C3 alumni: Ron Jeffries's xProgramming.com and Don Wells's
extremeProgramming.org. Much of the early advocacy and development of the XP ideas occurred on
Ward Cunningham's wiki web collaborative writing environment. The wiki remains a fascinating place to
discover, although its rambling nature does lead you into being sucked in. There is an active, and often
interesting xp discussion egroup. One of the more interesting "outside" views of XP is that of Mark Paulk,
who is one of the leaders of the CMM community - his paper looks at XP from a CMM perspective.

Cockburn's Crystal Family

Alistair Cockburn has been working on methodology ever since he was tasked by IBM to write about
methodology in the early 90's. His approach is unlike most methodologists, however. Instead of building
on solely personal experience to build a theory of how things should be done, he supplements his direct
experience with actively seeking to interview projects to see how they work. Furthermore he isn't afraid to
alter his views based on his discoveries: all of which make him my favorite methodologist.

His book, Surviving Object-Oriented Projects, was his first piece of advice on running projects, and
remains my number one book recommendation for running iterative projects. More recently Alistair has
written an overview book on agile software development that looks at the underlying principles of these
kinds of methodologies.

Since that book he's explored agile methods further, coming up with the Crystal family of methodologies.
It's a family because he believes that different kinds of projects require different kinds of methodologies.
He looks into this variation along two axes: the number of people in the project, and the consequences of
errors. Each methodology fits into a different part of the grid, so a 40 person project that can lose
discretionary money has a different methodology than a six person life-critical project.

The Crystals share a human orientation with XP, but this people-centeredness is done in a different way.
Alistair considers that people find it hard to follow a disciplined process, thus rather than follow XP's high
discipline, Alistair explores the least disciplined methodology that could still succeed, consciously trading
off productivity for ease of execution. He thus considers that although Crystal is less productive than XP,
more people will be able to follow it.

Alistair also puts a lot of weight in end of iteration reviews, thus encouraging the process to be self-
improving. His assertion is that iterative development is there to find problems early, and then to enable
people to correct them. This places more emphasis on people monitoring their process and tuning it as
they develop.

http://www.martinfowler.com/articles/newMethodology.html (14 of 22)05/12/2003 15:36:01


The New Methodology

Open Source

You may be surprised by this heading. After all open source is a style of software, not so much a process.
However there is a definite way of doing things in the open source community, and much of their
approach is as applicable to closed source projects as it is to open source. In particular their process is
geared to physically distributed teams, which is important because most adaptive processes stress co-
located teams.

Most open source projects have one or more maintainers. A maintainer is the only person who is allowed
to commit a change into the source code repository. However people other than the maintainer may make
changes to the code base. The key difference is that other folks need to send their change to the
maintainer, who then reviews it and applies it to the code base. Usually these changes are made in the
form of patch files which make this process easier. The maintainer thus is responsible for coordinating the
patches and maintaining the design cohesion of the software.

Different projects handle the maintainer role in different ways. Some have one maintainer for the whole
project, some divide into modules and have a maintainer per module, some rotate the maintainer, some
have multiple maintainers on the same code, others have a combination of these ideas. Most open source
folks are part time, so there is an issue on how well such a team coordinates for a full time project.

A particular feature of open source development is that debugging is highly parallelizable. So many
people can be involved in debugging. When they find a bug they can send the patch to the maintainer. This
is a good role for non-maintainers since most of the time is spent finding the bug. It's also good for folks
without strong design skills.

The process for open-source isn't well written up as yet. The most famous paper is Eric Raymond's The
Cathedral and the Bazar, which while an excellent description is also rather brief. Karl Fogel's book on
the CVS code repository also contains several good chapters on open-source process that would be
interesting even to those who never want to do cvs update.

Highsmith's Adaptive Software Development

Jim Highsmith has spent many years working with predictive methodologies. He developed them,
installed them, taught them, and has concluded that they are profoundly flawed: particularly for modern
businesses.

His recent book focuses on the adaptive nature of new methodologies, with a particular emphasis on
applying ideas that originate in the world of complex adaptive systems (commonly referred to as chaos
theory.) It doesn't provide the kind of detailed practices like the XP work does, but it does provide the
fundamental groundwork for why adaptive development is important and the consequences at the deeper
organizational and management levels.

http://www.martinfowler.com/articles/newMethodology.html (15 of 22)05/12/2003 15:36:01


The New Methodology

At the heart of ASD are three non-linear, overlapping phases: speculation, collaboration, and learning.

Highsmith views planning as a paradox in an adaptive environment, since outcomes are naturally
unpredictable. In traditional planning, deviations from plans are mistakes that should be corrected. In an
adaptive environment, however, deviations guide us towards the correct solution.

In this unpredictable environment you need people to collaborate in a rich way in order to deal with the
uncertainty. Management attention is less about telling people what to do, and more about encouraging
communication so that people can come up with creative answers themselves.

In predictive environments, learning is often discouraged. You lay out things in advance and then follow
that design.

In an adaptive environment, learning challenges all stakeholders - developers and their


customers - to examine their assumptions and to use the results of each development cycle
to adapt the next.
-- [Highsmith]

As such learning is a continuous and important feature, one that assumes that plans and designs must
change as development proceeds.

The overriding, powerful, indivisible, predominant benefit of the Adaptive Development Life
Cycle is that it forces us to confront the mental models that are at the root of our self-
delusion. It forces us to more realistically estimate our ability.
-- [Highsmith]

With this emphasis, Highsmith's work focuses directly on to foster the hard parts of adaptive development,
in particular how to foster collaboration and learning within the project. As such his book helps provide
ideas to foster these "soft" areas which makes a nice complement to the grounded practice based
approaches such as XP, FDD, and Crystal.

Scrum

Scrum has been around for a while in object-oriented circles, although I'll confess I'm not too au fait with
its history or development. Again it focuses on the fact that defined and repeatable processes only work
for tackling defined and repeatable problems with defined and repeatable people in defined and repeatable
environments.

Scrum divides a project into iterations (which they call sprints) of 30 days. Before you begin a sprint you
define the functionality required for that sprint and then leave the team to deliver it. The point is to
stabilize the requirements during the sprint.

http://www.martinfowler.com/articles/newMethodology.html (16 of 22)05/12/2003 15:36:01


The New Methodology

However management does not disengage during the sprint. Every day the team holds a short (fifteen
minute) meeting, called a scrum, where the team runs through what it will do in the next day. In particular
they surface to the management blocks: impediments to progress that are getting in the way that
management needs to resolve. They also report on what's been done so management gets a daily update of
where the project is.

Scrum literature focuses mainly on the iterative planning and tracking process. It's very close to the other
agiles in many respects and should work well with the coding practices from XP.

After a long time without a book, finally Ken Schwaber and Mike Beedle have written the first scrum
book. Ken Schwaber also hosts controlChaos.com[missing reference] which is probably the best overview
of SCRUM. Jeff Sutherland has always has an active web site on object technology issues and includes a
section on SCRUM. There's also a good overview of Scrum practices in the PLoPD 4 book. Scrum has a
yahoo discussion list.

Feature Driven Development

Feature Driven Development (FDD) was developed by Jeff De Luca and long time OO guru Peter Coad.
Like the other adaptive methodologies, it focuses on short iterations that deliver tangible functionality. In
FDD's case the iterations are two weeks long.

FDD has five processes. The first three are done at the beginning of the project.

● Develop an Overall Model


● Build a Features List
● Plan by Feature

The last two are done within each iteration.

● Design by Feature
● Build by Feature

Each process is broken down into tasks and is given verification criteria

The developers come in two kinds: class owners and chief programmers. The chief programmer are the
most experienced developers. They are assigned features to build. However they don't build them alone.
Instead the chief programmer identifies which classes are involved in implementing the feature and
gathers their class owners together to form a feature team for developing that feature. The chief
programmer acts as the coordinator, lead designer, and mentor while the class owners do much of the
coding of the feature.

Until recently, documentation on FDD was very skimpy. Finally there is a full book on FDD. Jeff De

http://www.martinfowler.com/articles/newMethodology.html (17 of 22)05/12/2003 15:36:01


The New Methodology

Luca, the primary inventor. now has an FDD portal with articles, blogs, and discussion boards. The
original description was in Peter Coad et al's UML in Color book. His company, TogetherSoft, also does
consulting and training on FDD.

DSDM (Dynamic System Development Method)

DSDM started in Britain in 1994 as a consortium of UK companies who wanted to build on the RAD and
iterative development. Starting with 17 founders it now boasts over a thousand members and has grown
outside its British roots. Being developed by a consortium, it has a different flavor to many of the other
agile methods. It has a full time organization supporting it with manuals, training courses, accreditation
programs, and the like. It also carries a price tag, which has limited my investigation of the methodology.
However Jennifer Stapleton has written a book which gives an overview of the methodology.

Using the method begins with a feasibility and a business study. The feasibility study considers whether
DSDM is appropriate to the project at hand. The business study is a short series of workshops to
understand the business area where the development takes place. It also comes up with outline system
architectures and project plan.

The rest of the process forms three interwoven cycles : the functional model cycle produces analysis
documentation and prototypes, the design and build cycle engineers the system for operational use, and the
implementation cycle handles the deployment to operational use.

DSDM has underlying principles that include active user interaction, frequent deliveries, empowered
teams, testing throughout the cycle. Like other agile methods they use short timeboxed cycles of between
two and six weeks. There's an emphasis on high quality and adaptivity towards changing requirements.

I haven't seen much evidence of its use outside the UK, but DSDM is notable for having much of the
infrastructure of more mature traditional methodologies, while following the principles of the agile
methods approach. There does seem to be a question on whether its materials encourage more of a process-
orientation and more ceremony than I would like.

The Manifesto for Agile Software Development

With so much similarity between these methods, there was a fair bit of interest in some form of
collaborative work. As such representatives from each of these methodologies were invited to a two day
workshop at Snowbird Utah in February 2001. I tagged along, without much expectations. After all when
you put a bunch of methodologists in room, civility is usually the best you can hope for.

As it turned out I was surprised. Everyone was conscious of the fact that there was a lot of common
ground, and this recognition was much greater than the differences between the processes. So as well as
some useful contact making between the process leaders, there was also the idea to issue a joint statement
- a call to arms in favor of more agile software processes. (We also agreed to use the term "agile" to refer

http://www.martinfowler.com/articles/newMethodology.html (18 of 22)05/12/2003 15:36:01


The New Methodology

to our common ideas.)

The result is a Manifesto for Agile Software Development, a statement of the common values and
principles of agile processes. There's also a desire to collaborate further in the future, to further encourage
both technologists and business people to use and require agile approaches to software development.
There's a software development magazine article that is a commentary and explanation of the manifesto.

The manifesto was just that, a publication which acted as a rallying point for those who shared these basic
ideas. One of the fruits of the effort was to create a longer lived body, the Agile Alliance. The Agile
Alliance is a non-profit organization that seeks to promote knowledge and discussion of all the agile
methods. Many of the agilist leaders that I've mentioned here are members and leaders of the Agile
Alliance.

Context Driven Testing

From the beginning it's been software developers who have been driving the agile community. However
many other people are involved in software development and are affected by this new movement. One
obvious such group is testers, who often live in a world very much contained by waterfall thinking. With
common guidelines that state that the role of testing is to ensure conformance of software to up-front
written specifications, the role of testers in an agile world is far from clear.

As it turns out, several people in the testing community have been questioning much of mainstream testing
thinking for quite a while. This has led to a group known as context-driven testing. The best description of
this is the book Lessons Learned in Software Testing. This community is also very active on the web, take
a look at sites hosted by Brian Marick (one of the authors of the agile manifesto), Brett Pettichord, James
Bach, and Cem Kaner.

Is RUP an agile method?

Whenever we start discussing methods in the OO arena, we inevitably come up with the role of the
Rational Unified Process. The Unified Process was developed by Philippe Kruchten, Ivar Jacobson and
others at Rational as the process complement to the UML. RUP is a process framework and as such can
accommodate a wide variety of processes. Indeed this is my main criticism of RUP - since it can be
anything it ends up being nothing. I prefer a process that tells you what to do rather than provide endless
options.

As a result of this process framework mentality, RUP can be used in a very traditional waterfall style or in
an agile manner. So as a result you can use RUP as a agile process, or as a heavyweight process - it all
depends on how you tailor it in your environment.

Craig Larman is a strong proponent of using the RUP in a agile manner. His excellent introductory book

http://www.martinfowler.com/articles/newMethodology.html (19 of 22)05/12/2003 15:36:01


The New Methodology

on OO development contains a process that's very much based on his light RUP thinking. His view is that
much of the recent push to agile methods is nothing more than accepting mainstream OO development
that's been captured as RUP. One of the things that Craig does is spend the first two or three days of a
month long iteration with the whole team using the UML to outline the design of the work to be done
during the iteration. This is not a blueprint that can't be deviated from, but rather a sketch that gives people
a perspective on how things can be done over the iteration.

Another tack at agile RUP is Robert Martin's dX process. The dx process is a fully compliant instance of
RUP, that just happens to be identical to XP (turn dX upside down to see the joke). dX is designed for
folks that have to use RUP, but want to use XP. As such it is both XP and RUP and thus a good example
of the agile use of RUP.

For me, one of the key things that needs to happen with RUP is that the leaders of RUP in the industry
need to emphasize their approach to software development. More than once I have heard people using
RUP who are using a waterfall style development process. Due to my contacts in the industry I know that
Philippe Kruchten and his team are firm believers in iterative development. Clarifying these principles and
encouraging agile instances of RUP such as Craig's and Robert's work will have an important effect.

Other Sources

Recently we've seen two good books appear which look at the broad topic of agile methods from Alistair
Cockburn and Jim Highsmith.

There are a number of other papers and discussions about this theme of agile methods. While these may
not be full methodologies, they do offer insights into this growing field.

The Patterns Language of Programming conferences has often contained material that touches on this
subject, if only because many of the folks interested in patterns are also interested in more adaptive and
humane methods. A leading early paper was Jim Coplien's paper at PLoP1. Ward Cunningham's Episodes
pattern language appeared in PLoP2. Jim Coplein now hosts the OrgPatterns site, a wiki which collects
together patterns for organizational patterns.

Dirk Riehle sent a paper to XP2000 that compares the value systems of XP and Adaptive Software
Development. The July edition of the Coad letter compares XP to FDD. The July edition of IEEE
Software includes several articles on "process diversity" which touch on these methodologies.

Mary Poppendieck wrote a fascinating article comparing agile methodologies with lean manufacturing.

Should you go agile?


Using a agile method is not for everyone. There are a number of things to bear in mind if you decide to

http://www.martinfowler.com/articles/newMethodology.html (20 of 22)05/12/2003 15:36:01


The New Methodology

follow this path. However I certainly believe that these new methodologies are widely applicable and
should be used by more people than currently consider them.

In today's environment, the most common methodology is code and fix. Applying more discipline than
chaos will almost certainly help, and the agile approach has the advantage that it is much less of a step
than using a heavyweight method. Here much of the advantage of the agile methods is indeed their light
weight. Simpler processes are more likely to be followed when you are used to no process at all.

One of the biggest limitations to these new methodologies is how they handle larger teams. Like many
new approaches they tend to be used first on a small scale rather than a larger scale. Also often they've
been created with an emphasis on small teams. Extreme Programming explicitly says that it is designed for
teams of up to around twenty people. It's worth remembering that many software teams could be reduced
in size without reducing the overall productivity.

Other agile approaches are intended for larger sized teams. FDD was originally designed around a fifty
person project. ThoughtWorks has used XP influenced projects with a team of around a 100 in three
continents. Scrum's been used to handle similar sized product teams.

Hopefully one message that's clear from this article is that adaptive approaches are good when your
requirements are uncertain or volatile. If you don't have stable requirements, then you aren't in the position
to have a stable design and follow a planned process. In these situations an adaptive process may be less
comfortable, but it will be more effective. Often the biggest barrier here is the customer. In my view it's
important for the customer to understand that following a predictive process when requirements change is
risky to them just as much as it is to development.

If you are going to take the adaptive route, you need to trust your developers and involve them in the
decision. Adaptive processes rely on you trusting your developers, so if you consider your developers to
be of low quality and motivation then you should use a predictive approach.

So to summarize. The following factors suggest an adaptive process

● Uncertain or volatile requirements


● Responsible and motivated developers
● Customer who understands and will get involved.

These factors suggest a predictive process

● A team of over a hundred


● Fixed price, or more correctly a fixed scope, contract

Acknowledgments

http://www.martinfowler.com/articles/newMethodology.html (21 of 22)05/12/2003 15:36:01


The New Methodology

I've taken lots of ideas from people for this paper, more than I could possibly list. For concrete suggestions
I'd like to thank Marc Balcer, Kent Beck, Alistair Cockburn, Ward Cunningham, Bill Kimmel, and Frank
Westphal.

Do remember that this is an evolving web paper and likely to change whenever I have the inclination. I'll
add a record of significant changes, however minor changes will occur without comment.

Revision History

Here's a list of the major updates to this paper

● April 2003: Revised several sections. Added section on difficulty of measurement and context
driven testing.
● June 2002: Updated references
● November 2001: Updated some recent references
● March 2001: Updated to reflect the appearance of the Agile Alliance
● November 2000: Updated section on ASD and added sections on DSDM and RUP
● December 2000: Abridged version published in Software Development magazine under the title of
"Put Your Process on a Diet"
● July 2000: Original Publication on martinfowler.com

© Copyright Martin Fowler, all rights reserved

http://www.martinfowler.com/articles/newMethodology.html (22 of 22)05/12/2003 15:36:01


Is Design Dead?

About Contact
Home Blog Articles Books ThoughtWorks
Me Me

Is Design Dead?
Martin Fowler
Chief Scientist, ThoughtWorks

Last Significant Update: February 2001

For many that come briefly into contact with Extreme Programming, it seems that XP calls for the death
of software design. Not just is much design activity ridiculed as "Big Up Front Design", but such design
techniques as the UML, flexible frameworks, and even patterns are de-emphasized or downright ignored.
In fact XP involves a lot of design, but does it in a different way than established software processes. XP
has rejuvenated the notion of evolutionary design with practices that allow evolution to become a viable
design strategy. It also provides new challenges and skills as designers need to learn how to do a simple
design, how to use refactoring to keep a design clean, and how to use patterns in an evolutionary style.

| Japanese | Russian | Chinese | Spanish |

(This paper was written for my keynote at XP 2000 conference and will be published as part of the
proceedings.)

● Planned and Evolutionary Design


● The Enabling Practices of XP
● The Value of Simplicity
● What on Earth is Simplicity Anyway
● Does Refactoring Violate YAGNI?
● Patterns and XP
● Growing an Architecture
● UML and XP
● On Metaphor
● Do you wanna be an Architect when you grow up?
● Things that are difficult to refactor in
● So is Design Dead?
● Acknowledgements
● Revision History

http://www.martinfowler.com/articles/designDead.html (1 of 15)05/12/2003 15:36:03


Is Design Dead?

Extreme Programming (XP) challenges many of the common assumptions about software development.
Of these one of the most controversial is its rejection of significant effort in up-front design, in favor of a
more evolutionary approach. To its detractors this is a return to "code and fix" development - usually
derided as hacking. To its fans it is often seen as a rejection of design techniques (such as the UML),
principles and patterns. Don't worry about design, if you listen to your code a good design will appear.

I find myself at the center of this argument. Much of my career has involved graphical design languages -
the Unified Modeling Language (UML) and its forerunners - and in patterns. Indeed I've written books on
both the UML and patterns. Does my embrace of XP mean I recant all of what I've written on these
subjects, cleansing my mind of all such counter-revolutionary notions?

Well I'm not going to expect that I can leave you dangling on the hook of dramatic tension. The short
answer is no. The long answer is the rest of paper.

Planned and Evolutionary Design


For this paper I'm going to describe two styles how design is done in software development. Perhaps the
most common is evolutionary design. Essentially evolutionary design means that the design of the system
grows as the system is implemented. Design is part of the programming processes and as the program
evolves the design changes.

In its common usage, evolutionary design is a disaster. The design ends up being the aggregation of a
bunch of ad-hoc tactical decisions, each of which makes the code harder to alter. In many ways you might
argue this is no design, certainly it usually leads to a poor design. As Kent puts it, design is there to enable
you to keep changing the software easily in the long term. As design deteriorates, so does your ability to
make changes effectively. You have the state of software entropy, over time the design gets worse and
worse. Not only does this make the software harder to change, it also makes bugs both easier to breed and
harder to find and safely kill. This is the "code and fix" nightmare, where the bugs become exponentially
more expensive to fix as the project goes on.

Planned Design is a counter to this, and contains a notion born from other branches of engineering. If you
want to build a doghouse, you can just get some wood together and get a rough shape. However if you
want to build a skyscraper, you can't work that way - it'll just collapse before you even get half way up. So
you begin with engineering drawings, done in an engineering office like the one my wife works at in
downtown Boston. As she does the design she figures out all the issues, partly by mathematical analysis,
but mostly by using building codes. Building codes are rules about how you design structures based on
experience of what works (and some underlying math). Once the design is done, then her engineering
company can hand the design off to another company that builds it.

Planned design in software should work the same way. Designers think out the big issues in advance. They
don't need to write code because they aren't building the software, they are designing it. So they can use a
design technique like the UML that gets away from some of the details of programming and allows the

http://www.martinfowler.com/articles/designDead.html (2 of 15)05/12/2003 15:36:03


Is Design Dead?

designers to work at a more abstract level. Once the design is done they can hand it off to a separate group
(or even a separate company) to build. Since the designers are thinking on a larger scale, they can avoid
the series of tactical decisions that lead to software entropy. The programmers can follow the direction of
the design and, providing they follow the design, have a well built system

Now the planned design approach has been around since the 70s, and lots of people have used it. It is
better in many ways than code and fix evolutionary design. But it has some faults. The first fault is that it's
impossible to think through all the issues that you need to deal with when you are programming. So it's
inevitable that when programming you will find things that question the design. However if the designers
are done, moved onto another project, what happens? The programmers start coding around the design and
entropy sets in. Even if the designer isn't gone, it takes time to sort out the design issues, change the
drawings, and then alter the code. There's usually a quicker fix and time pressure. Hence entropy (again).

Furthermore there's often a cultural problem. Designers are made designers due to skill and experience,
but they are so busy working on designs they don't get much time to code any more. However the tools
and materials of software development change at a rapid rate. When you no longer code not just can you
miss out on changes that occur with this technological flux, you also lose the respect of those who do
code.

This tension between builders and designers happens in building too, but it's more intense in software. It's
intense because there is a key difference. In building there is a clearer division in skills between those who
design and those who build, but in software that's less the case. Any programmer working in high design
environments needs to be very skilled. Skilled enough to question the designer's designs, especially when
the designer is less knowledgeable about the day to day realities of the development platform.

Now these issues could be fixed. Maybe we can deal with the human tension. Maybe we can get designers
skillful enough to deal with most issues and have a process disciplined enough to change the drawings.
There's still another problem: changing requirements. Changing requirements are the number one big issue
that causes headaches in software projects that I run into.

One way to deal with changing requirements is to build flexibility into the design so that you can easily
change it as the requirements change. However this requires insight into what kind of changes you expect.
A design can be planned to deal with areas of volatility, but while that will help for foreseen requirements
changes, it won't help (and can hurt) for unforeseen changes. So you have to understand the requirements
well enough to separate the volatile areas, and my observation is that this is very hard.

Now some of these requirements problems are due to not understanding requirements clearly enough. So a
lot of people focus on requirements engineering processes to get better requirements in the hope that this
will prevent the need to change the design later on. But even this direction is one that may not lead to a
cure. Many unforeseen requirements changes occur due to changes in the business. Those can't be
prevented, however careful your requirements engineering process.

So all this makes planned design sound impossible. Certainly they are big challenges. But I'm not inclined

http://www.martinfowler.com/articles/designDead.html (3 of 15)05/12/2003 15:36:03


Is Design Dead?

to claim that planned design is worse than evolutionary design as it is most commonly practiced in a "code
and fix" manner. Indeed I prefer planned design to "code and fix". However I'm aware of the problems of
planned design and am seeking a new direction.

The Enabling Practices of XP


XP is controversial for many reasons, but one of the key red flags in XP is that it advocates evolutionary
design rather than planned design. As we know, evolutionary design can't possibly work due to ad hoc
design decisions and software entropy.

At the core of understanding this argument is the software change curve. The change curve says that as the
project runs, it becomes exponentially more expensive to make changes. The change curve is usually
expressed in terms of phases "a change made in analysis for $1 would cost thousands to fix in production".
This is ironic as most projects still work in an ad-hoc process that doesn't have an analysis phase, but the
exponentiations is still there. The exponential change curve means that evolutionary design cannot
possibly work. It also conveys why planned design must be done carefully because any mistakes in
planned design face the same exponentiation.

The fundamental assumption underlying XP is that it is possible to flatten the change curve enough to
make evolutionary design work. This flattening is both enabled by XP and exploited by XP. This is part of
the coupling of the XP practices: specifically you can't do those parts of XP that exploit the flattened curve
without doing those things that enable the flattening. This is a common source of the controversy over XP.
Many people criticize the exploitation without understanding the enabling. Often the criticisms stem from
critics' own experience where they didn't do the enabling practices that allow the exploiting practices to
work. As a result they got burned and when they see XP they remember the fire.

There are many parts to the enabling practices. At the core are the practices of Testing, and Continuous
Integration. Without the safety provided by testing the rest of XP would be impossible. Continuous
Integration is necessary to keep the team in sync, so that you can make a change and not be worried about
integrating it with other people. Together these practices can have a big effect on the change curve. I was
reminded of this again here at ThoughtWorks. Introducing testing and continuous integration had a
marked improvement on the development effort. Certainly enough to seriously question the XP assertion
that you need all the practices to get a big improvement.

Refactoring has a similar effect. People who refactor their code in the disciplined manner suggested by XP
find a significant difference in their effectiveness compared to doing looser, more ad-hoc restructuring.
That was certainly my experience once Kent had taught me to refactor properly. After all, only such a
strong change would have motivated me to write a whole book about it.

Jim Highsmith, in his excellent summary of XP, uses the analogy of a set of scales. In one tray is planned
design, the other is refactoring. In more traditional approaches planned design dominates because the
assumption is that you can't change your mind later. As the cost of change lowers then you can do more of

http://www.martinfowler.com/articles/designDead.html (4 of 15)05/12/2003 15:36:03


Is Design Dead?

your design later as refactoring. Planned design does not go away completely, but there is now a balance
of two design approaches to work with. For me it feels like that before refactoring I was doing all my
design one-handed.

These enabling practices of continuous integration, testing, and refactoring, provide a new environment
that makes evolutionary design plausible. However one thing we haven't yet figured out is where the
balance point is. I'm sure that, despite the outside impression, XP isn't just test, code, and refactor. There is
room for designing before coding. Some of this is before there is any coding, most of it occurs in the
iterations before coding for a particular task. But there is a new balance between up-front design and
refactoring.

The Value of Simplicity


Two of the greatest rallying cries in XP are the slogans "Do the Simplest Thing that Could Possibly Work"
and "You Aren't Going to Need It" (known as YAGNI). Both are manifestations of the XP practice of
Simple Design.

The way YAGNI is usually described, it says that you shouldn't add any code today which will only be
used by feature that is needed tomorrow. On the face of it this sounds simple. The issue comes with such
things as frameworks, reusable components, and flexible design. Such things are complicated to build.
You pay an extra up-front cost to build them, in the expectation that you will gain back that cost later. This
idea of building flexibility up-front is seen as a key part of effective software design.

However XP's advice is that you not build flexible components and frameworks for the first case that
needs that functionality. Let these structures grow as they are needed. If I want a Money class today that
handles addition but not multiplication then I build only addition into the Money class. Even if I'm sure I'll
need multiplication in the next iteration, and understand how to do it easily, and think it'll be really quick
to do, I'll still leave it till that next iteration.

One reason for this is economic. If I have to do any work that's only used for a feature that's needed
tomorrow, that means I lose effort from features that need to be done for this iteration. The release plan
says what needs to be worked on now, working on other things in the future is contrary to the developers
agreement with the customer. There is a risk that this iteration's stories might not get done. Even if this
iteration's stories are not at risk it's up to the customer to decide what extra work should be done - and that
might still not involve multiplication.

This economic disincentive is compounded by the chance that we may not get it right. However certain we
may be about how this function works, we can still get it wrong - especially since we don't have detailed
requirements yet. Working on the wrong solution early is even more wasteful than working on the right
solution early. And the XPerts generally believe that we are much more likely to be wrong than right (and
I agree with that sentiment.)

http://www.martinfowler.com/articles/designDead.html (5 of 15)05/12/2003 15:36:03


Is Design Dead?

The second reason for simple design is that a complex design is more difficult to understand than a simple
design. Therefore any modification of the system is made harder by added complexity. This adds a cost
during the period between when the more complicated design was added and when it was needed.

Now this advice strikes a lot of people as nonsense, and they are right to think that. Right providing that
you imagine the usual development world where the enabling practices of XP aren't in place. However
when the balance between planned and evolutionary design alters, then YAGNI becomes good practice
(and only then).

So to summarize. You don't want to spend effort adding new capability that won't be needed until a future
iteration. And even if the cost is zero, you still don't want to it because it increases the cost of modification
even if it costs nothing to put in. However you can only sensibly behave this way when you are using XP,
or a similar technique that lowers the cost of change.

What on Earth is Simplicity Anyway


So we want our code to be as simple as possible. That doesn't sound like that's too hard to argue for, after
all who wants to be complicated? But of course this begs the question "what is simple?"

In XPE Kent gives four criteria for a simple system. In order (most important first):

● Runs all the Tests


● Reveals all the intention
● No duplication
● Fewest number of classes or methods

Running all the tests is a pretty simple criterion. No duplication is also pretty straightforward, although a
lot of developers need guidance on how to achieve it. The tricky one has to do with revealing the intention.
What exactly does that mean?

The basic value here is clarity of code. XP places a high value on code that is easily read. In XP "clever
code" is a term of abuse. But some people's intention revealing code is another's cleverness.

In his XP 2000 paper, Josh Kerievsky points out a good example of this. He looks at possibly the most
public XP code of all - JUnit. JUnit uses decorators to add optional functionality to test cases, such things
as concurrency synchronization and batch set up code. By separating out this code into decorators it allows
the general code to be clearer than it otherwise would be.

But you have to ask yourself if the resulting code is really simple. For me it is, but then I'm familiar with
the Decorator pattern. But for many that aren't it's quite complicated. Similarly JUnit uses pluggable
methods which I've noticed most people initially find anything but clear. So might we conclude that
JUnit's design is simpler for experienced designers but more complicated for less experienced people?

http://www.martinfowler.com/articles/designDead.html (6 of 15)05/12/2003 15:36:03


Is Design Dead?

I think that the focus on eliminating duplication, both with XP's "Once and Only Once" and the Pragmatic
Programmer's DRY (Don't Repeat Yourself) is one of those obvious and wonderfully powerful pieces of
good advice. Just following that alone can take you a long way. But it isn't everything, and simplicity is
still a complicated thing to find.

Recently I was involved in doing something that may well be over-designed. It got refactored and some of
the flexibility was removed. But as one of the developers said "it's easier to refactor over-design than it is
to refactor no design." It's best to be a little simpler than you need to be, but it isn't a disaster to be a little
more complex.

The best advice I heard on all this came from Uncle Bob (Robert Martin). His advice was not to get too
hung up about what the simplest design is. After all you can, should, and will refactor it later. In the end
the willingness to refactor is much more important than knowing what the simplest thing is right away.

Does Refactoring Violate YAGNI?


This topic came up on the XP mailing list recently, and it's worth bringing out as we look at the role of
design in XP.

Basically the question starts with the point that refactoring takes time but does not add function. Since the
point of YAGNI is that you are supposed to design for the present not for the future, is this a violation?

The point of YAGNI is that you don't add complexity that isn't needed for the current stories. This is part
of the practice of simple design. Refactoring is needed to keep the design as simple as you can, so you
should refactor whenever you realize you can make things simpler.

Simple design both exploits XP practices and is also an enabling practice. Only if you have testing,
continuous integration, and refactoring can you practice simple design effectively. But at the same time
keeping the design simple is essential to keeping the change curve flat. Any unneeded complexity makes a
system harder to change in all directions except the one you anticipate with the complex flexibility you put
in. However people aren't good at anticipating, so it's best to strive for simplicity. However people won't
get the simplest thing first time, so you need to refactor in order get closer to the goal.

Patterns and XP
The JUnit example leads me inevitably into bringing up patterns. The relationship between patterns and
XP is interesting, and it's a common question. Joshua Kerievsky argues that patterns are under-emphasized
in XP and he makes the argument eloquently, so I don't want to repeat that. But it's worth bearing in mind
that for many people patterns seem in conflict to XP.

The essence of this argument is that patterns are often over-used. The world is full of the legendary

http://www.martinfowler.com/articles/designDead.html (7 of 15)05/12/2003 15:36:03


Is Design Dead?

programmer, fresh off his first reading of GOF who includes sixteen patterns in 32 lines of code. I
remember one evening, fueled by a very nice single malt, running through with Kent a paper to be called
"Not Design Patterns: 23 cheap tricks" We were thinking of such things as use an if statement rather than a
strategy. The joke had a point, patterns are often overused, but that doesn't make them a bad idea. The
question is how you use them.

One theory of this is that the forces of simple design will lead you into the patterns. Many refactorings do
this explicitly, but even without them by following the rules of simple design you will come up with the
patterns even if you don't know them already. This may be true, but is it really the best way of doing it?
Surely it's better if you know roughly where you're going and have a book that can help you through the
issues instead of having to invent it all yourself. I certainly still reach for GOF whenever I feel a pattern
coming on. For me effective design argues that we need to know the price of a pattern is worth paying -
that's its own skill. Similarly, as Joshua suggests, we need to be more familiar about how to ease into a
pattern gradually. In this regard XP treats the way we use patterns differently to the way some people use
them, but certainly doesn't remove their value.

But reading some of the mailing lists I get the distinct sense that many people see XP as discouraging
patterns, despite the irony that most of the proponents of XP were leaders of the patterns movement too. Is
this because they have seen beyond patterns, or because patterns are so embedded in their thinking that
they no longer realize it? I don't know the answers for others, but for me patterns are still vitally important.
XP may be a process for development, but patterns are a backbone of design knowledge, knowledge that is
valuable whatever your process may be. Different processes may use patterns in different ways. XP
emphasizes both not using a pattern until it's needed and evolving your way into a pattern via a simple
implementation. But patterns are still a key piece of knowledge to acquire.

My advice to XPers using patterns would be

● Invest time in learning about patterns


● Concentrate on when to apply the pattern (not too early)
● Concentrate on how to implement the pattern in its simplest form first, then add complexity later.
● If you put a pattern in, and later realize that it isn't pulling its weight - don't be afraid to take it out
again.

I think XP should emphasize learning about patterns more. I'm not sure how I would fit that into XP's
practices, but I'm sure Kent can come up with a way.

Growing an Architecture
What do we mean by a software architecture? To me the term architecture conveys a notion of the core
elements of the system, the pieces that are difficult to change. A foundation on which the rest must be
built.

http://www.martinfowler.com/articles/designDead.html (8 of 15)05/12/2003 15:36:03


Is Design Dead?

What role does an architecture play when you are using evolutionary design? Again XPs critics state that
XP ignores architecture, that XP's route is to go to code fast and trust that refactoring that will solve all
design issues. Interestingly they are right, and that may well be weakness. Certainly the most aggressive
XPers - Kent Beck, Ron Jeffries, and Bob Martin - are putting more and more energy into avoiding any up
front architectural design. Don't put in a database until you really know you'll need it. Work with files first
and refactor the database in during a later iteration.

I'm known for being a cowardly XPer, and as such I have to disagree. I think there is a role for a broad
starting point architecture. Such things as stating early on how to layer the application, how you'll interact
with the database (if you need one), what approach to use to handle the web server.

Essentially I think many of these areas are patterns that we've learned over the years. As your knowledge
of patterns grows, you should have a reasonable first take at how to use them. However the key difference
is that these early architectural decisions aren't expected to be set in stone, or rather the team knows that
they may err in their early decisions, and should have the courage to fix them. Others have told the story
of one project that, close to deployment, decided it didn't need EJB anymore and removed it from their
system. It was a sizeable refactoring, it was done late, but the enabling practices made it not just possible,
but worthwhile.

How would this have worked the other way round. If you decided not to use EJB, would it be harder to
add it later? Should you thus never start with EJB until you have tried things without and found it lacking?
That's a question that involves many factors. Certainly working without a complex component increases
simplicity and makes things go faster. However sometimes it's easier to rip out something like that than it
is to put it in.

So my advice is to begin by assessing what the likely architecture is. If you see a large amount of data
with multiple users, go ahead and use a database from day 1. If you see complex business logic, put in a
domain model. However in deference to the gods of YAGNI, when in doubt err on the side of simplicity.
Also be ready to simplify your architecture as soon as you see that part of the architecture isn't adding
anything.

UML and XP
Of all the questions I get about my involvement with XP one of the biggest revolves around my
association with the UML. Aren't the two incompatible?

There are a number of points of incompatibility. Certainly XP de-emphasizes diagrams to a great extent.
Although the official position is along the lines of "use them if they are useful", there is a strong subtext of
"real XPers don't do diagrams". This is reinforced by the fact that people like Kent aren't at all comfortable
with diagrams, indeed I've never seen Kent voluntarily draw a software diagram in any fixed notation

I think the issue comes from two separate causes. One is the fact that some people find software diagrams

http://www.martinfowler.com/articles/designDead.html (9 of 15)05/12/2003 15:36:03


Is Design Dead?

helpful and some people don't. The danger is that those who do think that those who don't should do and
vice-versa. Instead we should just accept that some people will use diagrams and some won't.

The other issue is that software diagrams tend to get associated with a heavyweight process. Such
processes spend a lot of time drawing diagrams that don't help and can actually cause harm. So I think that
people should be advised how to use diagrams well and avoid the traps, rather than the "only if you must
(wimp)" message that usually comes out of the XPerts.

So here's my advice for using diagrams well.

First keep in mind what you're drawing the diagrams for. The primary value is communication. Effective
communication means selecting important things and neglecting the less important. This selectivity is the
key to using the UML well. Don't draw every class - only the important ones. For each class, don't show
every attribute and operation - only the important ones. Don't draw sequence diagrams for all use cases
and scenarios - only... you get the picture. A common problem with the common use of diagrams is that
people try to make them comprehensive. The code is the best source of comprehensive information, as the
code is the easiest thing to keep in sync with the code. For diagrams comprehensiveness is the enemy of
comprehensibility.

A common use of diagrams is to explore a design before you start coding it. Often you get the impression
that such activity is illegal in XP, but that's not true. Many people say that when you have a sticky task it's
worth getting together to have a quick design session first. However when you do such sessions:

● keep them short


● don't try to address all the details (just the important ones)
● treat the resulting design as a sketch, not as a final design

The last point is worth expanding. When you do some up-front design, you'll inevitably find that some
aspects of the design are wrong, and you only discover this when coding. That's not a problem providing
that you then change the design. The trouble comes when people think the design is done, and then don't
take the knowledge they gained through the coding and run it back into the design.

Changing the design doesn't necessarily mean changing the diagrams. It's perfectly reasonable to draw
diagrams that help you understand the design and then throw the diagrams away. Drawing them helped,
and that is enough to make them worthwhile. They don't have to become permanent artifacts. The best
UML diagrams are not artifacts.

A lot of XPers use CRC cards. That's not in conflict with UML. I use a mix of CRC and UML all the time,
using whichever technique is most useful for the job at hand.

Another use of UML diagrams is on-going documentation. In its usual form this is a model residing on a
case tool. The idea is that keeping this documentation helps people work on the system. In practice it often
doesn't help at all.

http://www.martinfowler.com/articles/designDead.html (10 of 15)05/12/2003 15:36:03


Is Design Dead?

● it takes too long to keep the diagrams up to date, so they fall out of sync with the code
● they are hidden in a CASE tool or a thick binder, so nobody looks at them

So the advice for on-going documentation runs from these observed problems:

● Only use diagrams that you can keep up to date without noticeable pain
● Put the diagrams where everyone can easily see them. I like to post them on a wall. Encourage
people to edit the wall copy with a pen for simple changes.
● Pay attention to whether people are using them, if not throw them away.

The last aspect of using UML is for documentation in a handover situation, such as when one group hands
over to another. Here the XP point is that producing documentation is a story like any other, and thus its
business value is determined by the customer. Again the UML is useful here, providing the diagrams are
selective to help communication. Remember that the code is the repository of detailed information, the
diagrams act to summarize and highlight important issues.

On Metaphor
Okay I might as well say it publicly - I still haven't got the hang of this metaphor thing. I saw it work, and
work well on the C3 project, but it doesn't mean I have any idea how to do it, let alone how to explain how
to do it.

The XP practice of Metaphor is built on Ward Cunninghams's approach of a system of names. The point is
that you come up with a well known set of names that acts as a vocabulary to talk about the domain. This
system of names plays into the way you name the classes and methods in the system

I've built a system of names by building a conceptual model of the domain. I've done this with the domain
experts using UML or its predecessors. I've found you have to be careful doing this. You need to keep to a
minimal simple set of notation, and you have to guard against letting any technical issues creeping into the
model. But if you do this I've found that you can use this to build a vocabulary of the domain that the
domain experts can understand and use to communicate with developers. The model doesn't match the
class designs perfectly, but it's enough to give a common vocabulary to the whole domain.

Now I don't see any reason why this vocabulary can't be a metaphorical one, such as the C3 metaphor that
turned payroll into a factory assembly line. But I also don't see why basing your system of names on the
vocabulary of the domain is such a bad idea either. Nor am I inclined to abandon a technique that works
well for me in getting the system of names.

Often people criticize XP on the basis that you do need at least some outline design of a system. XPers
often respond with the answer "that's the metaphor". But I still don't think I've seen metaphor explained in
a convincing manner. This is a real gap in XP, and one that the XPers need to sort out.

http://www.martinfowler.com/articles/designDead.html (11 of 15)05/12/2003 15:36:03


Is Design Dead?

Do you wanna be an Architect when you grow up?


For much of the last decade, the term "software architect" has become popular. It's a term that is difficult
personally for me to use. My wife is a structural engineer. The relationship between engineers and
architects is ... interesting. My favorite was "architects are good for the three B's: bulbs, bushes, birds".
The notion is that architects come up with all these pretty drawings, but it's the engineers who have to
ensure that they actually can stand up. As a result I've avoided the term software architect, after all if my
own wife can't treat me with professional respect what chance do I stand with anyone else?

In software, the term architect means many things. (In software any term means many things.) In general,
however it conveys a certain gravitas, as in "I'm not just a mere programmer - I'm an architect". This may
translate into "I'm an architect now - I'm too important to do any programming". The question then
becomes one of whether separating yourself from the mundane programming effort is something you
should do when you want to exercise technical leadership.

This question generates an enormous amount of emotion. I've seen people get very angry at the thought
that they don't have a role any more as architects. "There is no place in XP for experienced architects" is
often the cry I hear.

Much as in the role of design itself, I don't think it's the case that XP does not value experience or good
design skills. Indeed many of the proponents of XP - Kent Beck, Bob Martin, and of course Ward
Cunningham - are those from whom I have learned much about what design is about. However it does
mean that their role changes from what a lot of people see as a role of technical leadership.

As an example, I'll cite one of our technical leaders at ThoughtWorks: Dave Rice. Dave has been through
a few life-cycles and has assumed the unofficial mantle of technical lead on a fifty person project. His role
as leader means spending a lot of time with all the programmers. He'll work with a programmer when they
need help, he looks around to see who needs help. A significant sign is where he sits. As a long term
ThoughtWorker, he could pretty well have any office he liked. He shared one for a while with Cara, the
release manager. However in the last few months he moved out into the open bays where the programmers
work (using the open "war room" style that XP favors.) This is important to him because this way he sees
what's going on, and is available to lend a hand wherever it's needed.

Those who know XP will realize that I'm describing the explicit XP role of Coach. Indeed one of the
several games with words that XP makes is that it calls the leading technical figure the "Coach". The
meaning is clear: in XP technical leadership is shown by teaching the programmers and helping them
make decisions. It's one that requires good people skills as well as good technical skills. Jack Bolles at XP
2000 commented that there is little room now for the lone master. Collaboration and teaching are keys to
success.

At a conference dinner, Dave and I talked with a vocal opponent of XP. As we discussed what we did, the
similarities in our approach were quite marked. We all liked adaptive, iterative development. Testing was

http://www.martinfowler.com/articles/designDead.html (12 of 15)05/12/2003 15:36:03


Is Design Dead?

important. So we were puzzled at the vehemence of his opposition. Then came his statement, along the
lines of "the last thing I want is my programmers refactoring and monkeying around with the design".
Now all was clear. The conceptual gulf was further explicated by Dave saying to me afterwards "if he
doesn't trust his programmers why does he hire them?". In XP the most important thing the experienced
developer can do is pass on as many skills as he can to the more junior developers. Instead of an architect
who makes all the important decisions, you have a coach that teaches developers to make important
decisions. As Ward Cunningham pointed out, by that he amplifies his skills, and adds more to a project
than any lone hero can.

Things that are difficult to refactor in


Can we use refactoring to deal with all design decisions, or are there some issues that are so pervasive that
they are difficult to add in later? At the moment, the XP orthodoxy is that all things are easy to add when
you need them, so YAGNI always applies. I wonder if there are exceptions. A good example of something
that is controversial to add later is internationalization. Is this something which is such a pain to add later
that you should start with it right away?

I could readily imagine that there are some things that would fall into this category. However the reality is
that we still have very little data. If you have to add something, like internationalization, in later you're
very conscious of the effort it takes to do so. You're less conscious of the effort it would actually have
taken, week after week, to put it in and maintain it before it was actually needed. Also you 're less
conscious of the fact that you may well have got it wrong, and thus needed to do some refactoring anyway.

Part of the justification of YAGNI is that many of these potential needs end up not being needed, or at
least not in the way you'd expect. The effort you'll save by not doing any of them is less than the effort
required to refactor into the ones you do actually need.

Another issue to bear in mind in this is whether you really know how to do it. If you've done
internationalization several times, then you'll know the patterns you need to employ. As such you're more
likely to get it right. Adding anticipatory structures is probably better if you're in that position, than if
you're new to the problem. So my advice would be that if you do know how to do it, you're in a position to
judge the costs of doing it now to doing it later. However if you've not done it before, not just are you not
able to assess the costs well enough, you're also less likely to do it well. In which case you should add it
later. If you do add it then, and find it painful, you'll probably be better off than you would have been had
you added it early. Your team is more experienced, you know the domain better, and you understand the
requirements better. Often in this position you look back at how easy it would have been with 20/20
hindsight. It may have been much harder to add it earlier than you think.

This also ties into the question about the ordering of stories. In Planning XP, Kent and I openly indicated
our disagreement. Kent is in favor of letting business value be the only factor in driving the ordering of the
stories. After initial disagreement Ron Jeffries now agrees with this. I'm still unsure. I believe it is a
balance between business value and technical risk. This would drive me to provide at least some
internationalization early to mitigate this risk. However this is only true if internationalization was needed

http://www.martinfowler.com/articles/designDead.html (13 of 15)05/12/2003 15:36:03


Is Design Dead?

for the first release. Getting to a release as fast as possible is vitally important. Any additional complexity
is worth doing after that first release if it isn't needed for the first release. The power of shipped, running
code is enormous. It focuses customer attention, grows credibility, and is a massive source of learning. Do
everything you can to bring that date closer. Even if it is more effort to add something after the first
release, it is better to release sooner.

So is Design Dead?
Not by any means, but the nature of design has changed. XP design looks for the following skills

● A constant desire to keep code as clear and simple as possible


● Refactoring skills so you can confidently make improvements whenever you see the need.
● A good knowledge of patterns: not just the solutions but also appreciating when to use them and
how to evolve into them.
● Knowing how to communicate the design to the people who need to understand it, using code,
diagrams and above all: conversation.

That's a fearsome selection of skills, but then being a good designer has always been tough. XP doesn't
really make it any easier, at least not for me. But I think XP does give us a new way to think about
effective design because it has made evolutionary design a plausible strategy again. And I'm a big fan of
evolution - otherwise who knows what I might be?

Acknowledgements
Over the last couple of years I've picked up and stolen many good ideas from many good people. Most of
these are lost in the dimness of my memory. But I do remember pinching good ideas from Joshua
Kerievski. I also remember many helpful comments from Fred George and Ron Jeffries. I also cannot
forget how many good ideas keep coming from Ward and Kent.

I'm always grateful for those that ask questions and spot typos. I've been lax about keeping a list of these
to acknowledge, but they do include Craig Jones, Nigel Thorne, Sven Gorts, Hilary Nelson, Terry
Camerlengo.

Revision History

Revision History

Here's a list of the major updates to this paper

● February 2001: Article updated with sections on growing an architecture, the role of an architect,
and where things that are difficult to add with refactoring.

http://www.martinfowler.com/articles/designDead.html (14 of 15)05/12/2003 15:36:03


Is Design Dead?

● July 2000: Original article submitted to XP 2000 and posted to martinfowler.com

© Copyright Martin Fowler, all rights reserved

http://www.martinfowler.com/articles/designDead.html (15 of 15)05/12/2003 15:36:03


Continuous Integration

Home Blog Articles Books About Me Contact Me ThoughtWorks

Continuous Integration
Martin Fowler
Chief Scientist, ThoughtWorks

Matthew Foemmel
ThoughtWorks

Last Significant Update:

An important part of any software development process is getting reliable builds of the software. Despite it's importance, we are often
surprised when this isn't done. Here we discuss the process that Matt has put into place on a major project at ThoughtWorks, a process that
is increasingly used throughout the company. It stresses a fully automated and reproducible build, including testing, that runs many times a
day. This allows each developer to integrate daily thus reducing integration problems.

| Chinese | Traditional Chinese | Turkish | Italian |

ThoughtWorks have opensourced the CruiseControl software for automating continuous integration. We also offer consulting on using
CruiseControl, Ant, and getting C.I. going. You might also be interested in Bill Caputo and Oren Miller's article on Continuous Integration
with C++.

● The Benefits of Continuous Integration


● The More Often the Better
● What Is a Successful Build?
● Single Source Point
● Automated Build Scripts
● Self-Testing Code
● The Master Build
● Checking in
● Summing up

Software development is full of best practices which are often talked about but seem to be rarely done. One of the most basic, and valuable,
of these is a fully automated build and test process that allows a team to build and test their software many times a day. The idea of a daily
build has been talked about a lot. McConnnell recommends it as a best practice and it's been long known as a feature of the Microsoft
development approach. We agree with the XP community, however, in saying that daily builds are a minimum. A fully automated process
that allows you to build several times a day is both achievable and well worth the effort.

We are using the term Continuous Integration, a term used as one of the practices of XP (Extreme Programming). However we recognize that
the practice has been around for a long time and is used by plenty of folks that would never consider XP for their work. We've been using XP
as a touchstone in our software development process and that influences a lot of our terminology and practices. However you can use
continuous integration without using any other parts of XP - indeed we think it's an essential part of any competent software development
activity.

There are several parts to making an automated daily build work.

● Keep a single place where all the source code lives and where anyone can obtain the current sources from (and previous versions)
● Automate the build process so that anyone can use a single command to build the system from the sources

http://www.martinfowler.com/articles/continuousIntegration.html (1 of 7)05/12/2003 15:36:06


Continuous Integration

● Automate the testing so that you can run a good suite of tests on the system at any time with a single command
● Make sure anyone can get a current executable which you are confident is the best executable so far.

All of this takes a certain amount of discipline. We've found that it takes a lot of energy to introduce it into a project. We've also found that
once installed, it doesn't take too much effort to keep it up.

The Benefits of Continuous Integration


One of the hardest things to express about continuous integration is that makes a fundamental shift to the whole development pattern, one that
isn't easy to see if you've never worked in an environment that practices it. In fact most people do see this atmosphere if they are working solo
- because then they only integrate with themself. For many people team development just comes with certain problems that are part of the
territory. Continuous integration reduces these problems, in exchange for a certain amount of discipline.

The fundamental benefit of continuous integration is that it removes sessions where people spend time hunting bugs where one person's work
has stepped on someone else's work without either person realizing what happened. These bugs are hard to find because the problem isn't in
one person's area, it is in the interaction between two pieces of work. This problem is exacerbated by time. Often integration bugs can be
inserted weeks or months before they first manifest themselves. As a result they take a lot of finding.

With continuous integration the vast majority of such bugs manifest themselves the same day they were introduced. Furthermore it's
immediately obvious where at least half of the interaction lies. This greatly reduces the scope of the search for the bug. And if you can't find
the bug, you can avoid putting the offending code into the product, so the worst that happens is that you don't add the feature that also adds
the bug. (Of course you may want the feature more than you hate the bug, but at least this way it's an informed choice.)

Now there's no guarantee that you get all the integration bugs. The technique relies on testing, and as we all know testing does not prove the
absence of errors. The key point is that continuous integration catches enough bugs to be worth the cost.

The net result of all this is increased productivity by reducing the time spent chasing down integration bugs. While we don't know of anyone
who's given this anything approaching a scientific study the anecdotal evidence is pretty strong. Continuous Integration can slash the amount
of time spent in integration hell, in fact it can turn hell into a non-event.

The More Often the Better


There's a fundamental counter-intuitive effect at the center of continuous integration. It is that it is better to integrate often than to integrate
rarely. For those that do it, this is obvious; but for those that haven't this seems like a contradiction to direct experience.

If you integrate only occasionally, such as less than daily, then integration is a painful exercise, one that takes a lot of time and energy. Indeed
it's sufficiently awkward that the last thing you want to do is do it more frequently. The comment we often hear is "on a project this big, you
can't do a daily build."

Yet there are projects that do. We build a couple of dozen times a day on a code base around two hundred thousand lines of code worked on
by a team of fifty people. Microsoft does daily builds on projects with tens of millions of lines of code.

The reason that this is possible is that the effort of integration is exponentially proportional to the amount of time between integrations.
Although we're not aware of any measurements for this, this means that integrating once a week does not take five times as long as
integrating once a day, but more like twenty-five times as long. So if your integration is painful, you shouldn't take this as a sign that you
can't integrate more frequently. Done well, more frequent integration should be painless and you end up spending much less time carrying out
the integration.

A key for this is automation. Most of integration can, and should, be done automatically. Getting the sources, compiling, linking, and
significant testing can all be done automatically. At end you should be left with a simple indication of whether the build worked: yes or no. If
yes you ignore it, if no you should be able to easily undo the last change to the configuration and be certain the build will work this time. No
thought should be required to get a working build.

With an automated process like this, you can build as frequently as you like. The only limitation is the amount of time it takes to do the build.

http://www.martinfowler.com/articles/continuousIntegration.html (2 of 7)05/12/2003 15:36:06


Continuous Integration

What Is a Successful Build?


An important thing to decide is what makes a successful build. It may seem obvious, but it's remarkable how this can get muddy. Martin once
reviewed a project. He asked if the project did a daily build and was answered in the affirmative. Fortunately Ron Jeffries was there to probe
further. He asked the question "what do you do with build errors?" The response was "we send an e-mail to the relevant person". In fact the
project hadn't succeeded in a build for months. That's not a daily build, that's a daily build attempt.

We are pretty aggressive about what we mean by a successful build.

● All the latest sources are checked out of the configuration management system
● Every file is compiled from scratch
● The resulting object files (Java classes in our case) and linked and deployed for execution (put into jars).
● The system is started and suite of tests (in our case, around 150 test classes) is run against the system.
● If all of these steps execute without error or human intervention and every test passes, then we have a successful build

Most people consider a compile and link to be a build. At the least we think a build should include starting the application and running some
simple tests against it (McConnnell used the term "smoke test": switch it on and see if smoke comes out). Running a more exhaustive set of
tests greatly improves the value of continuous integration, so we prefer to do that as well.

Single Source Point


In order to integrate easily, any developer needs to be able to get a full set of current sources easily. There's nothing worse than having to go
around to different developers to ask for the latest bits and then having to copy them over, figure out where to put them, all this before you
can begin the build.

The standard is simple. Anyone should be able to bring a clean machine, connect it to the network, and with a single command bring down
every source file that's needed to build the system under development.

The obvious (we hope) solution is to use a configuration management (source control) system as the source of all code. Configuration
management systems are usually designed to be used over a network and have the tools that allow people to easily get hold of sources.
Furthermore they also include version management so you can easily find previous versions of various files. Cost shouldn't be an issue as
CVS is an excellent open-source configuration management tool.

For this to work all source files should be kept in the configuration management system. All is often more than people think. It also includes
build scripts, properties files, database schema DDLs, install scripts, and anything else that's needed to build on a clean machine. Too often
we've seen code controlled, but not some other vital file that has to be found.

Try to ensure everything is under a single source tree in the configuration management system. Sometimes people use separate projects in the
configuration management system for different components. The trouble with this is then people have to remember which versions of which
components work with which versions of other components. For some situations you have to separate the sources, however these situations
are much rarer than you think. You can build multiple components from a single tree of sources, such issues should be handled by the build
scripts, not by the storage structure.

Automated Build Scripts


If you're writing a small program with a dozen or so files, then building the application may be just a matter of a single command to a
compiler: javac *.java. Bigger projects need rather more. In these cases you have files in many directories. You need to ensure the
resulting object code is in the proper place. As well as compilations there may be link steps. You have code generated from other files that
needs to be generated before you can compile. Tests need to be run automatically.

A big build often takes time, you don't want to do all of these steps if you've only made a small change. So a good build tool analyzes what
needs to be changed as part of the process. The common way to do this is to check the dates of the source and object files and only compile if
the source date is later. Dependencies then get tricky: if one object file changes those that depend on it may also need to be rebuilt. Compilers
may handle this kind of thing, or they may not.

http://www.martinfowler.com/articles/continuousIntegration.html (3 of 7)05/12/2003 15:36:06


Continuous Integration

Depending on what you need, you may need different kinds of things to be built. You can build a system with or without test code, or with
different sets of tests. Some components can be built stand-alone. A build script should allow you to build alternative targets for different
cases.

Once you get past a simple command line, scripts often handle the load. These might be shell scripts or use a more sophisticated scripting
language such as perl or python. But soon it makes sense to use an environment designed for this kind of thing, such as the make tools in
Unix.

In our Java development we quickly discovered we needed a more serious solution. Indeed Matt put a good bit of time into developing a
build tool called Jinx which was designed for Enterprise Java work. Recently, however, we have switched over to the open-source build tool
Ant. Ant has a very similar design to Jinx, allowing us to compile Java files and package them into Jars. It also makes it easy for us to write
our own extensions to Ant to allow us to do other tasks within the build.

Many of us use IDEs, and most IDEs have some kind of build management process within them. However these files are always proprietary
to the IDE and often fragile. Furthermore they need the IDE to work. IDE users set up their own project files and use them for individual
development. However we rely on Ant for main builds and the master build is run on a server using Ant.

Self-Testing Code
Just getting a program to compile is not enough. While compilers in strongly typed languages can spot many problems, there are too many
errors that even a successful compile lets through. To help track these down we put a lot of emphasis on an automated testing discipline -
another practice that's advocated by XP.

XP divides tests into two categories: unit tests and acceptance (also called functional) tests. Unit tests are written by developers and typically
test an individual class or small group of classes. Acceptance tests are usually written by customers or an outside test group (with the help of
developers) and test the whole system end-to-end. We use both kinds of test, and automate both kinds of test as much as possible.

As part of the build we run a suite of tests that we call the "BVT" (Build Verification Tests). All the tests in the BVT must pass in order for us
to have a successful build. All of the XP-style unit tests are in the BVT. As this article is about the build process, we'll mostly talk about the
BVT here, just bear in mind that there is a second line of testing in addition to what's in the BVT, so don't judge the whole testing and QA
effort by the BVT alone. Indeed our QA group doesn't ever see code unless it's passed the BVT since they only work on working builds.

The basic principle is that when developers are writing code they also write tests for that code. When they complete a task, not just do they
check in the production code, they also check in the tests for that code. Those that follow XP closely use the test first style of programming:
you shouldn't write any code until you have a failing test. So if you want to add a new feature to the system, you first write a test that will
only work if the feature is there, then you make that test work.

We write the tests in Java, the same language that we're developing in. This makes writing tests just the same as writing code. We use JUnit
as the framework for organizing and writing tests. JUnit is a simple framework that allows you to quickly write tests, organize them into
suites, and run suites interactively or in batch mode. (JUnit is the Java member of the xUnit family - for which there are versions for almost
every language.)

Developers typically run some subset of the unit tests with every compile as they are writing the software. This actually speeds up the
development work since the tests help to find any logic errors in the code you're working on. Then, rather than debugging, you can look at the
changes since you last ran the tests. Those changes should be small and thus it's a lot easier to find the bug.

Not everyone works strictly in the XP test-first style, but the key benefit comes from writing the tests at the same time. As well as making an
individual task go faster, it also builds up the BVT making it more likely to catch errors. Since the BVT runs several times a day, this means
that any problems that the BVT detects are easier to find for the same reason: we can look at a small amount of changed code in order to find
the bug. This debugging by looking at the changed code is often much more effective than debugging by stepping though running code.

Of course you can't count on tests to find everything. As it's often been said: tests don't prove the absence of bugs. However perfection isn't
the only point at which you get payback for a good BVT. Imperfect tests, run frequently, are much better than perfect tests that are never
written at all.

A related question is the issue of developers writing tests on their own code. It's often been said that people should not test their own code,

http://www.martinfowler.com/articles/continuousIntegration.html (4 of 7)05/12/2003 15:36:06


Continuous Integration

because it's too easy to overlook errors in your own work. While this is true, the self-testing process requires a rapid turn-around of tests into
the code base. The value of that fast turn-around is greater than the value of separate testers. So for the BVTs we rely on developer-written
tests, but there are separate acceptance tests which are written independently.

Another important part of self-testing is to improve the quality of tests with feedback - a key value of XP. Feedback here comes in the form
of bugs that escaped the BVT. The rule here is that you aren't allowed to fix a bug until you have a failing unit test in the BVT. This way
every time you fix a bug, you also add a test to ensure it doesn't slip past you again. Furthermore this test should lead you to think of other
tests that need to be written to strengthen the BVT.

The Master Build


Build automation makes a lot of sense for individual developers, but where it really shines is in producing a master build for the whole team.
We've found that having a master build procedure brings the team together and makes it easier to find integration problems early.

The first step is to choose a machine to run the master builds. We use Trebuchet (we played Age of Empires a lot) a four processor server
which is pretty much dedicated to the build process. (In the early days when builds took a long time this horse-power was essential.)

The build process is in a Java class that's always running. If there's no build going on the build process sits in a while loop checking the
repository every few minutes. If nobody's checked in any code since the last build, it continues to wait. If there's new code in the repository,
then it starts building.

The first stage of the build is to do a full check out from the repository. Starteam provides a pretty good API for Java, so it was
straightforward to hook into the repository. The build daemon looks at the repository at five minutes before the current time and sees if
anyone checked in during that last five minutes. If so it considers it safe to check out the code as of five minutes ago (this prevents checking
out in the middle of someone checking in, without locking the repository.)

The daemon checks out to a directory on Trebuchet. Once all is checked out the daemon then invokes the ant script in the directory. Ant then
takes over to do a full build. We do a full build from all the sources. The ant script goes as far as compiling and dividing the resulting class
files into half a dozen jars for deploying into the EJB server.

Once Ant has done the compiling and deployment, the build daemon starts the EJB server with new jars and executes the BVT test suite. The
tests run, if all pass then we have a successful build. The build daemon then goes back into Starteam and labels the sources that were checked
out with a build number. It then looks to see if anyone's checked in while it was building, if so it starts another build. If not the daemon goes
back into its while loop and waits for the next check in.

At the end of the build, the build daemon sends an e-mail to all developers that had newly checked in code with that build. The e-mail
summarizes the status of that build. It's considered bad form to leave the building after checking in code until you've got that e-mail.

The daemon writes a log of all its steps to an XML log file. A servlet runs on Trebuchet which allows anyone to see the state of the build by
inspecting the log.

http://www.martinfowler.com/articles/continuousIntegration.html (5 of 7)05/12/2003 15:36:06


Continuous Integration

Figure 1: The build servlet

The screen shows if there's a build currently running and if so when it started. Down the left there is a history of all the builds, whether
successful or not. Clicking on a build shows the details of that build: whether it compiled, status of tests, what changes were made, etc.

We've found that many developers keep a regular eye on this web page. It gives them a sense of what's going on in the project and on what's
getting altered as people check in. At some point we may put other project news on that page, but we don't want it to lose its relevance.

It's important that any developer can simulate the master build locally on their own machine. That way if an integration error does occur, a
developer can investigate and debug the problem on their own machine without tying up the master build process. Furthermore the developer
can run the build locally before checking in to reduce the chances of the master build failing.

There's a reasonable question here about whether the master build should be a clean build, i.e. all from sources only, or an incremental build.
Incremental builds can be a lot faster, but they also introduce the risk of a problem sneaking because something didn't get compiled. It also
has the risk of us not being able to recreate a build. Our builds are pretty quick (about 15 minutes for ~200KLOC) so we're happy with doing
a clean build each time. However some shops like to do incremental builds most of the time, but a regular clean build (at least daily) in case
those odd errors crop up.

Checking in
Using an automated build means that the developers follow a certain kind of rhythm as they develop software. The most important part of that
rhythm is that they integrate regularly. We've run across organizations where they do a daily build, but people don't check in frequently. If

http://www.martinfowler.com/articles/continuousIntegration.html (6 of 7)05/12/2003 15:36:06


Continuous Integration

developers only check in every few weeks, then a daily build doesn't do much for you. We follow a general principle that every developer
checks code in roughly once a day.

Before starting on a new task, developers should first sync with the configuration management system. This will mean that their local copies
of the sources are up to date. Writing code on top of out-of-date sources only leads to trouble and confusion.

The developer then works on the task updating whichever files need changing. A developer may integrate when a task is done, or part way
through a task, but all tests need to run fine in order to integrate.

The first part of integration is to resync the developers working copies with the repository. Any files changed on the repository are copied
into the working directory and the configuration management system warns the developer of any conflicts. The developer then needs to build
to the synchronized working set and run the BVT successfully on those files.

Now the developer can commit the new files to the repository. Once that's done the developer needs to wait for the master build. If the master
build succeeds, then the check in succeeded. If not the developer can fix the problem and commit the fix if it's straightforward. If it's more
complicated then the developer needs to back out the changes, resync his working directory and get things working locally before committing
again.

Some check-in processes force a serialization of the check-in process. In this situation there is a build token which only one developer can
take. The developer will take the build token, resync the working copy, commit the changes, and release the token. This stops more than one
developer updating the repository between builds. We've found that we rarely run into trouble without the build token, so we don't use one.
Frequently more than one person commits into the same master build, but only rarely does that cause a build failure: and then it's usually easy
to fix.

We also leave to the developer's judgement how careful they should be before checking in. It's up to developer how likely they think it is that
there will be an integration error. If she thinks it is likely, then she does a local build first before checking in, if she thinks an integration error
is unlikely then she will just check in. If she's wrong she'll find out once the master build runs and then she'll have to back out her changes
and figure out what went wrong. You can tolerate errors providing they are quick to find and easy to remove.

Summing up
Developing a disciplined and automated build process is essential to a controlled project. Many software gurus say that, but we've found that
it's still a rarity in the field.

The key is to automate absolutely everything and run the process so often that integration errors are found quickly. As a result everyone is
more prepared to change things when they need to, because they know that if they do cause an integration error, it's easy to find and fix. Once
you have these benefits, you'll find they are such that you'll kick and scream before you give them up.

© Copyright Martin Fowler, all rights reserved

http://www.martinfowler.com/articles/continuousIntegration.html (7 of 7)05/12/2003 15:36:06


Developing Patterns of Enterprise Software

About Contact
Home Blog Articles Books ThoughtWorks
Me Me

Developing Patterns of Enterprise Software


Last Significant Update: May 2003

A short page on the growing community and body of work in capturing patterns for the development of
enterprise applications.

Patterns, a writing style to describe recurring solutions in software, have been with us for about ten years.
Many people, including myself, have been active in this field. Our aim is to try and capture effective and
common solutions and describe them so they become more widely known among software developers.

One of the problems with general software patterns is that there is a limited range of patterns that truly
apply across all software systems. In the last couple of years there's been a burst of activity developing
patterns for the particular domain of enterprise software.

Enterprise applications have a number of particular characteristics: large amounts of complex data, many
simultaneous users often needing a lot of support from user interfaces, complex and irrational business
logic, and many points of integration with other technologies. These particular problems tend to lead to a
particular set of recurring solutions.

Patterns Work in Progress


After the first rush of patterns books in the mid 90's, I think we saw a slump in good patterns writing. A
lack of particular focus in a domain was part of this problem. I think there are now signs of a second wave
of patterns writing, and the enterprise software world is a happy beneficiary.

The first breaking of this second wave was the CoreJ2EE Patterns book, developed by a Deepak Alur,
John Crupi, and Dan Malks from Sun Professional Services. Not just did they create a fine set of patterns
to guide people to use J2EE effectively, they also helped demonstrate that well-written patterns could be
effective. Despite being linked to the J2EE platform, many of their patterns are equally applicable to other
technologies, which has been demonstrated by the fact that other patterns authors have used their ideas in
other contexts.

I've also been a member of this second wave, with my own book Patterns of Enterprise Application
Architecture. My book aims at patterns that cross over different technologies, but my work also builds on
the CoreJ2EE work.

http://www.martinfowler.com/articles/enterprisePatterns.html (1 of 3)05/12/2003 15:36:07


Developing Patterns of Enterprise Software

The most recent addition to enterprise application patterns has come from Microsoft, with their work on
architectural patterns for .NET, led by David Trowbridge. Currently the patterns are available at MSDN,
they'll also be released in a book from Microsoft Press later in 2003.As well as patters around enterprise
application architecture, a related team led by Philip Teale has worked on patterns around data
management, their first release has published a set of patterns on data movement.

The material so far is primarily work that I characterize as patterns of enterprise application architecture -
how to put together a single application. But enterprises developers also have to deal with integrating
applications that weren't originally designed to work together. While working with Kyle Brown on my P
of EAA book we realized that there was an important field that needed work, particularly in the growing
area of integration via messaging.

We managed to do some nudging and encourage Gregor Hohpe and Bobby Woolf to start capturing their
expertise in this field. So far they've developed a strong body of patterns on Gregor's website, and they
intend to publish a book of these in late 2003.

Experienced OO developers know that the key to handling complex domain logic is a well formed
Domain Model. The catch is that developing a good domain model is neither easy to do, nor easy to teach.
I ran into Eric Evans a few years ago and discovered he was a one of that rare breed of excellent domain
modelers. He's also been working on a book of patterns which has been taking shape on his website, and
should be published in mid 2003.

Building a Community
All of the work that I've discussed here has been helped a great deal by collaboration with each other,
allowing us to share ideas and grow our work.

A lot of this collaboration has been done in conjunction with the conferences hosted by the patterns
community, often in the form of focused workshops which allow us to work over our ideas. Such get-
togethers have occurred at PLoP in 2002, which Kyle Brown chaired, and at ChiliPLoP in early 2003.
Many of us will attending the enterprise patterns focus group at PLoP 2003 hosted by Randy Stafford - a
contributor to my P of EAA book - and Bobby Woolf. If you are interested in helping grow the world of
patterns, I'd suggest that you take a serious look at getting involved in that, or other workshops. I'll try to
ensure that I let you know about these through this website.

Revision History

Here's a list of the major updates to this paper

● May 2003:

http://www.martinfowler.com/articles/enterprisePatterns.html (2 of 3)05/12/2003 15:36:07


Developing Patterns of Enterprise Software

© Copyright Martin Fowler, all rights reserved

http://www.martinfowler.com/articles/enterprisePatterns.html (3 of 3)05/12/2003 15:36:07


Software Development Online

HOMEPAGE
SITE CONTENTS BY YEAR
SEND US FEEDBACK
SUBSCRIBE TO SD
ADVERTISE WITH SD

By registering, you will be able to access participating CMP web sites with a single account.

STEP ONE: Set up a username and password to access our sites.

If you have already registered with any of the sites listed above, please use that username and
password to log in below.

Otherwise, you may create a new account by clicking here.

If you have forgotten your username or password, click here.

Existing Users, Log In below:

https://www.sdmediagroup.com/registration/?url=http%3A%2F%2Fwww.sdmagazine.com%2Fdocuments%2Fs%3D7897%2Fsdm0304a%2Fsdm0304a.htm (1 of 2)05/12/2003 15:36:11


Software Development Online

username:
password:

Submit

If you are using Opera for Windows or Safari, you will experience difficulties accepting
Cookies. Until a suitable solution can be found please, register with Mozilla, Netscape or
Internet Explorer. Sorry for the inconvenience.

CMP Media, LLC f.a.q. contact us privacy policy

Copyright © 2003 CMP Media LLC, SD Magazine's Privacy Policy, Comments: webmaster@sdmagazine.com
SDMG Websites: BYTE.com, C/C++ Users Journal, Dr. Dobb's Journal, MSDN Magazine, Sys Admin, SD Expo, SD
Magazine, Unixreview, Windows Developer Network, New Architect

https://www.sdmediagroup.com/registration/?url=http%3A%2F%2Fwww.sdmagazine.com%2Fdocuments%2Fs%3D7897%2Fsdm0304a%2Fsdm0304a.htm (2 of 2)05/12/2003 15:36:11


Domain Logic and SQL

Home Blog Articles Books About Me Contact Me ThoughtWorks

Domain Logic and SQL


Last Significant Update: February 2003

Over the last couple of decades we've seen a growing gap between database-oriented software developers and in-
memory application software developers. This leads to many disputes about how to use database features such as SQL
and stored procedures. In this article I look at the question of whether to place business logic in SQL queries or in-
memory code, considering primarily performance and maintainability based on an example of a simple, but rich SQL
query.

Look at any recent book on building enterprise applications (such as my recent P of EAA) and you'll find a breakdown
of logic into multiple layers which separate out different parts of an enterprise application. Different authors use
different layers, but a common theme is a separation between domain logic (business rules) and data source logic (where
data comes from). Since a large part of enterprise application data is stored on relational databases, this layering scheme
seeks to separate business logic from the relational database

Many application developers, particularly strong OO developers like myself, tend to treat relational databases as a
storage mechanism that is best hidden away. Frameworks exist who tout the advantages of shielding application
developers from the complexities of SQL.

Yet SQL is much more than a simple data update and retrieval mechanism. SQL's query processing can perform many
tasks. By hiding SQL, application developers are excluding a powerful tool.

In this article I want to explore the pros and cons of using rich SQL queries that may contain domain logic. I have to
declare that I bring a OO bias to the discussion, but I've lived on the other side too. (One former client's OO expert
group ran me out of the company because I was a "data modeler".)

Complex Queries
Relational databases all support a standard query language - SQL. Fundamentally I believe that SQL is the primary
reason why relational databases have succeeded to the extent they have. A standard way of interacting with databases
has provided a strong degree of vendor independence, which both helped the rise of relational databases, and helped see
off the OO challenge.

SQL has many strengths, but a particular one is extremely powerful capabilities for querying the database, allowing
clients to filter and summarize large amounts of data with very few lines of SQL code. Yet using powerful SQL queries
often embed domain logic, which goes against the basic principles of a layered enterprise application architecture.

To explore this topic further, let's play with a simple example. We'll begin with a data model along the lines of Figure 1.
Imagine our company has a special discount, which we'll call the Cuillen. Customers qualify for the Cuillen discount if
they make at least one order in the month which includes more than $5000 worth of Talisker. Note that two orders in the
same month of $3000 each doesn't count, there must be a single order for more than $5000. Let's imagine a you want to

http://www.martinfowler.com/articles/dblogic.html (1 of 15)05/12/2003 15:36:13


Domain Logic and SQL

look at a particular customer and determine which months in the last year they qualified for a Cuillen discount. I'll
ignore the user interface and just assume that what we want is a list of numbers corresponding to their qualifying months.

Figure 1: The database schema for the example (UML notation)

There are many ways we can answer this question. I'll begin with three crude alternatives: transaction script, domain
model, and complex SQL.

For all these examples, I'm going to illustrate them using the Ruby programming language. I'm going out on a bit of a
limb here: usually I use Java and/or C# to illustrate these things as most application developers can read C-based
languages. I'm picking Ruby somewhat as an experiment. I like the language because it encourages compact yet well-
structured code and makes it easy to write in an OO style. It's my language of choice for scripting. I've added a quick
ruby syntax guide based on the ruby I'm using here.

Transaction Script

Transaction script is the pattern name I coined for a procedural style of handling a request in P of EAA. In this case the
procedure reads in all the data it might need and then does the selection and manipulation in-memory to figure out which
months are needed.

def cuillen_months name


customerID = find_customerID_named(name)
result = []
find_orders(customerID).each do |row|
result << row['date'].month if cuillen?(row['orderID'])
end
return result.uniq
end

def cuillen? orderID


talisker_total = 0.dollars
find_line_items_for_orderID(orderID).each do |row|
talisker_total += row['cost'].dollars if 'Talisker' == row['product']
end
return (talisker_total > 5000.dollars)
end

The two methods, cuillen_months and cuillen?, contain the domain logic. They use a number of "finder" methods that

http://www.martinfowler.com/articles/dblogic.html (2 of 15)05/12/2003 15:36:13


Domain Logic and SQL

issue queries to the database.

def find_customerID_named name


sql = 'SELECT * from customers where name = ?'
return $dbh.select_one(sql, name)['customerID']
end

def find_orders customerID


result = []
sql = 'SELECT * FROM orders WHERE customerID = ?'
$dbh.execute(sql, customerID) do |sth|
result = sth.collect{|row| row.dup}
end
return result
end

def find_line_items_for_orderID orderID


result = []
sql = 'SELECT * FROM lineItems l WHERE orderID = ?'
$dbh.execute(sql, orderID) do |sth|
result = sth.collect{|row| row.dup}
end
return result
end

In many ways this is a very simple minded approach, in particular it's very inefficient in its use of SQL - requiring
multiple queries to pull back the data (2 + N where N is the number of orders). Don't worry about that too much at the
moment, I'll talk about how to improve that later. Concentrate instead on essence of the approach: read in all the data
you have to consider, then loop through and select what you need.

(As an aside, the domain logic above is done that way to make it easy to read - but it isn't what I feel is idiomatic Ruby.
I'd prefer the method below which makes more use of Ruby's powerful blocks and collection methods. This code will
look odd to many people, but Smalltalkers should enjoy it.)

def cuillen_months2 name


customerID = find_customerID_named(name)
qualifying_orders = find_orders(customerID).select {|row| cuillen?(row
['orderID'])}
return (qualifying_orders.collect {|row| row['date'].month}).uniq
end

Domain Model

For the second starting point, we'll consider a classical object-oriented domain model. In this case we create in-memory
objects, which in this case mirror the database tables (in real systems they usually aren't exact mirrors.) A set of finder
objects loads these objects from the database, once we have the objects in memory, we then run the logic on them.

We'll start with the finders. They slam queries against the database and create the objects.

http://www.martinfowler.com/articles/dblogic.html (3 of 15)05/12/2003 15:36:13


Domain Logic and SQL

class CustomerMapper
def find name
result = nil
sql = 'SELECT * FROM customers WHERE name = ?'
return load($dbh.select_one(sql, name))
end
def load row
result = Customer.new(row['customerID'], row['NAME'])
result.orders = OrderMapper.new.find_for_customer result
return result
end
end

class OrderMapper
def find_for_customer aCustomer
result = []
sql = "SELECT * FROM orders WHERE customerID = ?"
$dbh.select_all(sql, aCustomer.db_id) {|row| result << load(row)}
load_line_items result
return result
end
def load row
result = Order.new(row['orderID'], row['date'])
return result
end
def load_line_items orders
#Cannot load with load(row) as connection gets busy
orders.each do
|anOrder| anOrder.line_items = LineItemMapper.new.find_for_order anOrder
end
end
end

class LineItemMapper
def find_for_order order
result = []
sql = "select * from lineItems where orderID = ?"
$dbh.select_all(sql, order.db_id) {|row| result << load(row)}
return result
end
def load row
return LineItem.new(row['lineNumber'], row['product'], row['cost'].to_i.
dollars)
end
end

These load methods load the following classes

http://www.martinfowler.com/articles/dblogic.html (4 of 15)05/12/2003 15:36:13


Domain Logic and SQL

class Customer...
attr_accessor :name, :db_id, :orders
def initialize db_id, name
@db_id, @name = db_id, name
end

class Order...
attr_accessor :date, :db_id, :line_items
def initialize (id, date)
@db_id, @date, @line_items = id, date, []
end

class LineItem...
attr_reader :line_number, :product, :cost
def initialize line_number, product, cost
@line_number, @product, @cost = line_number, product, cost
end

The logic of determining the cuillen months can be described in a couple of methods.

class Customer...
def cuillenMonths
result = []
orders.each do |o|
result << o.date.month if o.cuillen?
end
return result.uniq
end

class Order...
def cuillen?
discountableAmount = 0.dollars
line_items.each do |line|
discountableAmount += line.cost if 'Talisker' == line.product
end
return discountableAmount > 5000.dollars
end

This solution is longer than the transaction script version. However it's worth pointing out that the logic to load the
objects and the actual domain logic are more separated. Any other processing on this set of domain objects would use
the same load logic. So if we were doing a lot of different bits of domain logic the effort of the load logic would be
amortized across all the domain logic, which would make it less of an issue. That cost can be even further reduced by
techniques such as Metadata Mapping.

Again there's a lot of SQL queries (2 + number of orders).

http://www.martinfowler.com/articles/dblogic.html (5 of 15)05/12/2003 15:36:13


Domain Logic and SQL

Logic in SQL

With both of the first two, the database is used pretty much as a storage mechanism. All we've done is asked for all the
records from a particular table with some very simple filtering. SQL is a very powerful query language and can do much
more than the simple filtering that these examples use.

Using SQL to its full extent we can do all the work in SQL

def discount_months customerID


sql = <<-END_SQL
SELECT DISTINCT MONTH(o.date) AS month
FROM lineItems l
INNER JOIN orders o ON l.orderID = o.orderID
INNER JOIN customers c ON o.customerID = c.customerID
WHERE (c.name = ?) AND (l.product = 'Talisker')
GROUP BY o.orderID, o.date, c.NAME
HAVING (SUM(l.cost) > 5000)
END_SQL
result = []
$dbh.select_all(sql, customerID) {|row| result << row['month']}
return result
end

Although I've referred to this as a complex query, it's only complex in comparison to the simple select and where clause
queries of the earlier examples. SQL queries can get far more complicated than this one, although many application
developers would shy away from even a query as minimally complex as this.

Looking at Performance
One of the first questions people consider with this kind of thing is performance. Personally I don't think performance
should be the first question. My philosophy is that most of the time you should focus on writing maintainable code.
Then use a profiler to identify hot spots and then replace only those hot spots with faster but less clear code. The main
reason I do this is because in most systems only a very small proportion of the code is actually performance critical, and
it's much easier to improve the performance of well factored maintainable code.

But in any case, let's consider the performance trade-offs first. On my little laptop the complex SQL query performs
twenty times faster than the other two approaches. Now you cannot form any conclusions about the the performance of a
data center server from an svelte but elderly laptop, but I would be surprised if the complex query would be less than an
order of magnitude faster than the in memory approaches.

Part of the reason for this is that the in-memory approaches are written in a way that is very inefficient in terms of SQL
queries. As I've pointed out in their descriptions, each one issues a SQL query for every order that a customer has - and
my test database has a thousand orders for each customer.

We can reduce this load considerably by rewriting the in-memory programs to use a single SQL query. I'll start with the
transaction script.

SQL = <<-END_SQL

http://www.martinfowler.com/articles/dblogic.html (6 of 15)05/12/2003 15:36:13


Domain Logic and SQL

SELECT * from orders o


INNER JOIN lineItems li ON li.orderID = o.orderID
INNER JOIN customers c ON c.customerID = o.customerID
WHERE c.name = ?
END_SQL

def cuillen_months customer_name


orders = {}
$dbh.select_all(SQL, customer_name) do |row|
process_row(row, orders)
end
result = []
orders.each_value do |o|
result << o.date.month if o.talisker_cost > 5000.dollars
end
return result.uniq
end

def process_row row, orders


orderID = row['orderID']
orders[orderID] = Order.new(row['date']) unless orders[orderID]
if 'Talisker' == row['product']
orders[orderID].talisker_cost += row['cost'].dollars
end
end

class Order
attr_accessor :date, :talisker_cost
def initialize date
@date, @talisker_cost = date, 0.dollars
end
end

This is a pretty big change to the transaction script, but it speeds things up by a factor of three.

I can do a similar trick with the domain model. Here we see an advantage of the domain model's more complex
structure. I only need to modify the loading method, the business logic in the domain objects themselves does not need
to change.

class CustomerMapper
SQL = <<-END_SQL
SELECT c.customerID,
c.NAME as NAME,
o.orderID,
o.date as date,
li.lineNumber as lineNumber,
li.product as product,
li.cost as cost

http://www.martinfowler.com/articles/dblogic.html (7 of 15)05/12/2003 15:36:13


Domain Logic and SQL

FROM customers c
INNER JOIN orders o ON o.customerID = c.customerID
INNER JOIN lineItems li ON o.orderID = li.orderID
WHERE c.name = ?
END_SQL

def find name


result = nil
om = OrderMapper.new
lm = LineItemMapper.new
$dbh.execute (SQL, name) do |sth|
sth.each do |row|
result = load(row) if result == nil
unless result.order(row['orderID'])
result.add_order(om.load(row))
end
result.order(row['orderID']).add_line_item(lm.load(row))
end
end
return result
end

(I'm telling a little lie when I say that I don't need to modify the domain objects. In order to get decent performance I
needed to change the data structure of customer so that the orders were held in a hash rather than an array. But again, it
was a very self-contained change, and didn't impact the code for determining the discount.)

There's a few points here. Firstly it's worth remembering that in-memory code can often by boosted by more intelligent
queries. It's always worth looking to see if you are calling the database multiple times, and if there's a way to do it with a
single call instead. This is particularly easy to overlook when you have a domain model because people usually think of
class at a time access. (I've even seen cases where people load a single row at a time, but that pathological behavior is
relatively rare.)

One of the biggest differences between the transaction script and the domain model is the impact of changing the query
structure. For the transaction script, it pretty much means altering the entire script. Furthermore if there were many
domain logic scripts using similar data, each one would have to be changed. With the domain model you alter a nicely
separated section of the code and the domain logic itself doesn't have to change. This is a big deal if you have a lot of
domain logic. This is the general trade off between transaction scripts and domain logic - there's an initial cost in
complexity of database access for a domain logic which pays off iff you have a lot of domain logic.

But even with the multi-table query, the in-memory approaches are still not as fast as the complex SQL - by a factor of 6
in my case. This makes sense: the complex SQL does the selection and summing of costs in the database and only has to
schlep a handful of values back to the client, while the in-memory approach needs to schlep five thousand rows of data
back to the client.

Performance isn't the only factor in deciding what route to go, but it's often a concluding one. If you have a hot spot that
you absolutely need to improve, then other factors come second. As a result many fans of domain models follow the
system of doing things in-memory as a default, and using things like complex queries for hot spots only when they have
to.

http://www.martinfowler.com/articles/dblogic.html (8 of 15)05/12/2003 15:36:13


Domain Logic and SQL

It's also worth pointing out that this example is one that plays to a database's strengths. Many queries don't have the
strong elements of selection and aggregation that this one does, and won't show such a performance change. In addition
multi-user scenarios often cause surprising changes to the way queries behave, so real profiling has to be done under a
realistic multi-user load. You may find that locking issues outweigh anything you can get by faster individual queries.

Modifiability
For any long-lived enterprise application, you can be sure of one thing - it's going to change a lot. As a result you have
to ensure that the system is organized in such a way that's easy to change. Modifiability is probably the main reason why
people put business logic in memory.

SQL can do many things, but there limits to its capabilities. Some things that it can do require quite clever coding, as a
browse of algorithms for the median of a dataset displays. Others are impossible to make without resorting to non-
standard extensions, which is a problem if you want portability.

Often you want to run business logic before you write data into the database, particularly if you working on some
pending information. Loading into a database can be problematic because often you want pending session data to be
isolated from fully accepted data. This session data often shouldn't be subject to the same validation rules as fully
accepted data.

Understandability

SQL is often seen as a special language, one that's not something that application developers should need to deal with.
Indeed many database frameworks like to say how by using them you avoid needing to deal with SQL. I've always
found that a somewhat strange argument, since I've always been fairly comfortable with moderately complex SQL.
However many developers find SQL harder to deal with than traditional languages, and a number of SQL idioms are
hard to fathom to all but SQL experts.

A good test for you is to look at the three solutions, and see which makes the domain logic easiest to follow and thus
modify. I find the domain model version, which is just a couple of methods, the easiest to follow; in large part because
the data access is separated out. Next I prefer the SQL version over the in-memory transaction script. But I'm sure other
readers would have other preferences.

If most of a team is less comfortable with SQL, then that's a reason to keep domain logic away from SQL. (It's also a
reason to consider training more people in SQL - at least to an intermediate level.) This is one of those situations where
you have to take into account the make up of your team - people do affect architectural decisions.

Avoiding Duplication

One of the simplest, yet most powerful, design principles I've come across is avoiding duplication - formulated by the
Pragmatic Programmers as the DRY (Don't Repeat Yourself) principle.

To think about the DRY principle for this case, let's consider another requirement for this application - a list of orders
for a customer on a particular month showing the orderID, date, total cost and whether this order is a qualifying order
for the Cuillen plan. All of this sorted by the total cost.

Using the domain object approach to handling this query we need to add a method to the order to calculate the total cost.

http://www.martinfowler.com/articles/dblogic.html (9 of 15)05/12/2003 15:36:13


Domain Logic and SQL

class Order...
def total_cost
result = 0.dollars
line_items.each {|line| result += line.cost}
return result
end

With that in place then it's easy to print the order list

class Customer
def order_list month
result = ''
selected_orders = orders.select {|o| month == o.date.month}
selected_orders.sort! {|o1, o2| o2.total_cost <=> o1.total_cost}
selected_orders.each do |o|
result << sprintf("%10d %20s %10s %3s\n",
o.db_id, o.date, o.total_cost, o.discount?)
end
return result
end

Defining the same query using a single SQL statement requires a correlated sub-query - which some people find
daunting.

def order_list customerName, month


sql = <<-END_SQL
SELECT o.orderID, o.date, sum(li.cost) as totalCost,
CASE WHEN
(SELECT SUM(li.cost)
FROM lineitems li
WHERE li.product = 'Talisker'
AND o.orderID = li.orderID) > 5000
THEN 'Y'
ELSE 'N'
END AS isCuillen
FROM dbo.CUSTOMERS c
INNER JOIN dbo.orders o ON c.customerID = o.customerID
INNER JOIN lineItems li ON o.orderID = li.orderID
WHERE (c.name = ?)
AND (MONTH(o.date) = ?)
GROUP by o.orderID, o.date
ORDER BY totalCost desc
END_SQL
result = ""
$dbh.select_all(sql, customerName, month) do |row|
result << sprintf("%10d %20s %10s %3s\n",

http://www.martinfowler.com/articles/dblogic.html (10 of 15)05/12/2003 15:36:13


Domain Logic and SQL

row['orderID'],
row['date'],
row['totalCost'],
row['isCuillen'])
end
return result
end

Different people will differ about which of these two is the easiest to understand. But the issue I'm chewing on here is
that of duplication. This query duplicates logic from the original query that just gives the months. The domain object
approach does not have this duplication - should I wish to change the definition for the cuillen plan, all I have to do is to
alter the definition of cuillen? and all uses are updated.

Now it isn't fair to trash SQL on the duplication issue - because you can avoid duplication in the rich SQL approach as
well. The trick, as database aficionados must be gasping to point out, is to use a view.

I can define a view, for simplicity called Orders2 based on the following query.

SELECT TOP 100 PERCENT


o.orderID, c.name, c.customerID, o.date,
SUM(li.cost) AS totalCost,
CASE WHEN
(SELECT SUM(li2.cost)
FROM lineitems li2
WHERE li2.product = 'Talisker'
AND o.orderID = li2.orderID) > 5000
THEN 'Y'
ELSE 'N'
END AS isCuillen
FROM dbo.orders o
INNER JOIN dbo.lineItems li ON o.orderID = li.orderID
INNER JOIN dbo.CUSTOMERS c ON o.customerID = c.customerID
GROUP BY o.orderID, c.name, c.customerID, o.date
ORDER BY totalCost DESC

I can now use this view for both getting the months and for producing the order list

def cuillen_months_view customerID


sql = "SELECT DISTINCT month(date) FROM orders2 WHERE name = ? AND isCuillen =
'Y'"
result = []
$dbh.select_all(sql, customerID) {|row| result << row[0]}
return result
end

def order_list_from_view customerName, month


result = ''
sql = "SELECT * FROM Orders2 WHERE name = ? AND month(date) = ?"
$dbh.select_all(SQL, customerName, month) do |row|

http://www.martinfowler.com/articles/dblogic.html (11 of 15)05/12/2003 15:36:13


Domain Logic and SQL

result << sprintf("%10d %10s %10s\n",


row['orderID'],
row['date'],
row['isCuillen'])
end
return result
end

The view simplifies both the queries and puts the key business logic into a single place.

It seems that people rarely discuss using views like this to avoid duplication. Books I've seen on SQL don't seem to
discuss doing this kind of thing. In some environments this is difficult because of the organizational and cultural splits
between database and application developers. Often application developers aren't allowed to define views and database
developers form a bottleneck that discourages application developers from getting views like this done. DBAs may even
refuse to build views that are only needed by a single application. But my opinion is that SQL deserves as much care to
design as anything else.

Encapsulation

Encapsulation is a well known principle of object-oriented design, and it's one that I think applies well to general
software design. Essentially it says that a program should be divided into modules that hide data structures behind an
interface of procedure calls. The purpose of this is to allow you to change the underlying data structure without causing
a large ripple effect across the system.

In this case, the question is how can we encapsulate the database? A good encapsulation scheme would allow us to alter
the database schema without causing a painful round of editing across an application.

For enterprise applications, a common form of encapsulation is a layering, where we strive to separate domain logic
from data source logic. That way the code that works on business logic isn't affected when we alter the database design.

The domain model version is a good example of this kind of encapsulation. The business logic works only on in-
memory objects. How the data gets there is completely separated. The transaction script approach has some database
encapsulation through the find methods, although the database structure is more revealed through the returning result
sets.

In an application world, you achieve encapsulation through an API of procedures and objects. The SQL equivalent is to
use views. If you change a table you can create a view which supports the old table. The biggest issue here is with
updates, which often can't be done properly with views. This is why many shops wrap all DML with stored procedures.

Encapsulation is about more than just supporting changes to views. It's also about the difference between accessing data
and defining business logic. With SQL the two can easily be blurred, yet you can still make some form of separation.

For an example, consider the view I defined above to avoid duplication in queries. That view is a single view which
could be split along the lines of a data source and business logic separation. A data source view would look something
like this

SELECT o.orderID, o.date, c.customerID, c.name,


SUM(li.cost) AS total_cost,

http://www.martinfowler.com/articles/dblogic.html (12 of 15)05/12/2003 15:36:13


Domain Logic and SQL

(SELECT SUM(li2.cost)
FROM lineitems li2
WHERE li2.product = 'Talisker' AND o.orderID =li2.orderID
) AS taliskerCost
FROM dbo.CUSTOMERS c
INNER JOIN dbo.orders o ON c.customerID = o.customerID
INNER JOIN dbo.lineItems li ON li.orderID = o.orderID
GROUP BY o.orderID, o.date, c.customerID, c.name

We can then use this view in other views that focus more on domain logic. Here's one that indicates the Cuillen
eligibility

SELECT orderID, date, customerID, name, total_cost,


CASE WHEN taliskerCost > 5000 THEN 'Y' ELSE 'N' END AS isCuillen
FROM dbo.OrdersTal

This kind of thinking can also be applied to cases where we're loading data into a domain model. Earlier on I talked
about how performance issues with a domain model could be dealt with by taking the entire query for cuillen months
and substituting it with a single SQL query. Another approach would be to use the above data source view. This would
allow us to keep a higher performance while still keeping the domain logic in a domain model. The line items would
only be loaded in if necessary using a Lazy Load, but suitable summary information could be brought in via the view.

Using views, or indeed stored procedures, provides encapsulation only up to a point. In many enterprise applications
data comes from multiple sources, not just multiple relational databases, but also legacy systems, other applications, and
files. Indeed the growth of XML will probably see more data coming from flat files shared via networks. In this case full
encapsulation really can only be done by a layer within the application code, which further implies that domain logic
should also sit in memory.

Database Portability

One reason why many developers shy away from complex SQL is the issue of database portability. After all the promise
of SQL is that it allows you to use the same standard SQL on a bevy of database platforms, allowing to change database
vendors easily

In reality that's always been a bit of a fudge. In practice SQL is mostly standard but with all sort of little places to trip
you up. With care, however, you can create SQL that isn't too painful to shift between database servers. But to do this
you lose a lot of capabilities.

The decision about database portability ends up being particular to your project. These days it's much less of an issue
than it used to be. The database market has shaken out so most places fall into one of the three major camps.
Corporations often have strong commitments to whichever camp they are in. If you consider that changing databases is
very unlikely due to this kind of investment, you might as well start taking advantage of the special features your
database provides.

Some people still need portability, such as people who provide products that can be installed and interfaced with
multiple databases. In this case there is a stronger argument against putting logic into SQL since you have to be so
careful about which parts of SQL you can safely use.

http://www.martinfowler.com/articles/dblogic.html (13 of 15)05/12/2003 15:36:13


Domain Logic and SQL

Testability

Testability isn't a topic that's tended to come up enough in discussions about design. One of the benefits of Test Driven
Development (TDD) is that it's rekindled the notion that testability is a vital part of design.

Common practice in SQL seems to not test. Indeed it's not uncommon to find essential views and stored procedures not
even held in configuration management tools. Yet it's certainly possible to have testable SQL. The popular xunit family
has a number of tools that can be used for testing within a database environment. Evolutionary database techniques such
as test databases can be used to provide a testable environment very similar to what TDD programmers enjoy.

The main area that can make a difference is performance. While direct SQL is often faster in production, it can be much
faster to run tests on business logic in memory if the database interface is designed in such a way that you can replace
the actual database connection with a Service Stub.

Summing Up
So far I've talked about the issues. Now it's time to draw conclusions. Fundamentally what you have to do is to consider
the various issues I've talked about here, judge them by your biases, and decide which policy to take to using rich
queries and putting domain logic in there.

The way I look at the picture, one of the most critical elements is whether your data comes from a single logical
relational database, or is scattered across a mass of different, often non-SQL, sources. If it's scattered then you should
build a data source layer in memory to encapsulate your data sources and keep your domain logic in memory. In this
case the strengths of SQL as a language isn't an issue, because not all of your data is in SQL.

The situation becomes interesting when the vast majority of your data sits in a single logical database. In this case you
have two primary issues to consider. One is the choice of programming language: SQL versus your application
language. The other is where the code runs, SQL at the database, or in memory.

SQL makes some things easy, but other things more difficult. Some people find SQL easy to work with, others find it
horribly cryptic. The teams personal comfort is a big issue here. I would suggest that if you go the route of putting a lot
of logic in SQL, don't expect to be portable - use all of your vendors extensions and cheerfully bind yourself to their
technology. If you want portability keep logic out of SQL.

So far I've talked about modifiability issues. I think these concerns should come first, but be trumped by any critical
performance issues. If you use an in-memory approach and have hot-spots that can be solved by more powerful queries,
then do that. I would suggest looking to see how much you can organize performance enhancing queries as data source
queries, as I outlined above. That way you can minimize putting domain logic into the SQL.

Revision History

Here's a list of the major updates to this paper

● February 2003:

http://www.martinfowler.com/articles/dblogic.html (14 of 15)05/12/2003 15:36:13


Domain Logic and SQL

© Copyright Martin Fowler, all rights reserved

http://www.martinfowler.com/articles/dblogic.html (15 of 15)05/12/2003 15:36:13


Evolutionary Database Design

About Contact
Home Blog Articles Books ThoughtWorks
Me Me

Evolutionary Database Design


Martin Fowler

Pramod Sadalage

Last Significant Update: January 2003

Over the last few years we've developed a number of techniques that allow a database design to evolve as
an application develops. This is a very important capability for agile methodologies. The techniques rely
on applying continuous integration and automated refactoring to database development, together with a
close collaboration between DBAs and application developers. The techniques work in both pre-
production and released systems.

| Japanese |

● Dealing with Change


❍ Limitations

● The Practices
❍ DBAs collaborate closely with developers

❍ Everybody gets their own database instance

❍ Developers frequently integrate into a shared master

❍ A database consists of schema and test data

❍ All changes are database refactorings

❍ Automate the refactorings

❍ Automatically Update all Database Developers

❍ Clearly separate all database access code

● Variations
❍ Keeping multiple database lineages

❍ You don't need a DBA

● Tools to Help
● Further Steps and Further Information

In the last few years, we've seen the rise of a new breed of software methodologies, the agile
methodologies. These make some new and significant demands on database design. One of the most

http://www.martinfowler.com/articles/evodb.html (1 of 11)05/12/2003 15:36:15


Evolutionary Database Design

central of these demands is the idea of evolutionary design. On an agile project you assume that you
cannot fix the requirements of the system up-front. As a result having a detailed design phase at the
beginning of a project becomes impractical. The design of the system has to evolve through the various
iterations of the software. Agile methods, in particular extreme programming (XP), have a number of
practices that make this evolutionary design practical.

Many people have questioned whether evolutionary design can be applied to a system with a large
database component. Indeed many people told us that it was impossible - a troubling thought as
ThoughtWorks embarked on a large database-oriented project using many agile and XP techniques.

This article describes the practices that we've used to allow us to do this impossible thing. We won't say
that we've completely solved the database evolution problem, but we do think we've demonstrated a set of
techniques that many people will find useful.

Dealing with Change


One of the primary features of agile methods is their attitude towards change. Most of the thinking about
software process is about understanding requirements early, signing off on these requirements, using the
requirements as a basis for design, signing off on that, and then proceeding with construction. This is a
plan-driven cycle, often referred to (usually with derision) as the waterfall approach

Such approaches look to minimize changes by doing extensive up-front work. Once the early work is
done, changes cause significant problems. As a result such approaches run into trouble if requirements are
changing, and requirements churn is a big problem for such processes.

Agile processes approach change differently. They seek to embrace change, allowing changes to occur
even late in a development project. Changes are controlled, but the attitude of the process is to enable
change as much as possible. Partly this is in response to the inherent instability of requirements in many
projects, partly it is to better support dynamic business environments by helping them change with the
competitive pressures.

In order to make this work, you need a different attitude to design. Instead of thinking of design as a
phase, which is mostly completed before you begin construction, you look at design as an on-going
process that is interleaved with construction, testing, and even delivery. This is the contrast between
planned and evolutionary design. One of the vital contributions of agile methods is that they have come up
with practices that allow evolutionary design to work in a controlled manner. So instead of the common
chaos that often happens when design isn't planned up-front, these methods provide techniques to control
evolutionary design and make them practical.

An important part of this approach is iterative development, where you run the entire software life-cycle
many times during the life of a project. Agile processes run complete life cycles in each iteration,
completing the iteration with working, tested, integrated code for a small subset of the requirements of the

http://www.martinfowler.com/articles/evodb.html (2 of 11)05/12/2003 15:36:15


Evolutionary Database Design

final product. These iterations are short, usually running between a week and a couple of months, with a
preference towards shorter iterations.

While these techniques have grown in use and interest, one of the biggest questions is how to make
evolutionary design work for databases. Most people consider that database design is something that
absolutely needs up-front planning. Changing the database schema late in the development tends to cause
wide-spread breakages in application software. Furthermore changing a schema after deployment result in
painful data migration problems.

Over the course of the last three years we've been involved in a large project (called Atlas) that has used
evolutionary database design and made it work. The project involved almost 100 people in multiple sites
world-wide (US, Australia, and India). It is around half a million lines of code and has over 200 tables.
The database evolved during a year and a half of initial development and continues to evolve even though
it's in production for multiple customers. During this project we started with iterations of a month, but
after a few months changed to two week iterations which worked better. The techniques we describe here
are the ones that we (or more accurately Pramod) used to make this work.

Since that project got going we've spread these techniques over more of our projects, gaining more
experience from more cases. We've also found inspiration, ideas, and experience from other agile projects.

Limitations

Before we dive into the techniques, it's important to state that we haven't solved all the problems of
evolutionary database design. In particular:

● We developed an application database for a single application rather than an integration database
that tries to integrate multiple databases.
● We don't have to keep the production databases up 24/7

We don't consider these problems to be inherently unsolvable, after all many people believed we couldn't
solve this one. But until we do, we won't claim we can solve them either.

The Practices
Our approach to evolutionary database design depends on a handful of important practices.

DBAs collaborate closely with developers

One of the tenets of agile methods is that people with different skills and backgrounds need to collaborate
very closely together. They can't communicate mainly through formal meetings and documents. Instead
they need to be out talking with each other and working with each other all the time.Everybody is affected
by this: analysts, PMs, domain experts, developers... and DBAs.

http://www.martinfowler.com/articles/evodb.html (3 of 11)05/12/2003 15:36:15


Evolutionary Database Design

Every task that a developer works on potentially needs a DBA's help. Both the developers and the DBA
need to consider whether a development task is going to make a significant change to the database
schema. If so the developer needs to consult with the DBA to decide how to make the change. The
developer knows what new functionality is needed, and the DBA has a global view of the data in the
application.

To make this happen the DBA has to make himself approachable and available. Make it easy for a
developer to just pop over for a few minutes and ask some questions. Make sure the DBAs and developers
sit close to each other so they can easily get together. Ensure that application design sessions are known
about so the DBA can pop in easily. In many environments we see people erecting barriers between the
DBA and application development functions. These barriers must come down for an evolutionary database
design process to work.

Everybody gets their own database instance

Evolutionary design recognizes that people learn by trying things out. In programming terms developers
experiment with how to implement a certain feature and may make a few attempts before settling down to
a preferred alternative. Database design can be like that too. As a result it's important for each developer to
have their own sandbox where they can experiment, and not have their changes affect anyone else.

Many DBA experts see multiple databases as anathema, too difficult to work in practice, but we've found
that you can easily manage a hundred or so database instances. The vital thing is to have to tools to allow
you to manipulate databases much as you would manipulate files.

Developers frequently integrate into a shared master

Although developers can experiment frequently in their own area, it's important to bring the different
approaches back together again frequently. An application needs a shared master database that all work
flows from. When a developer begins a task they copy the master into their own workspace, manipulate,
and then integrate their changes back into the master. As a rule of thumb each developer should integrate
once a day.

Let's take an example where Mike starts a development task at 10am (assuming he actually comes in that
early). As part of this task he needs to change the database schema. If the change is easy, like adding a
column, he just decides how to make the change himself, Mike also makes sure the column he wants to
add does not already exist in the database, with the help of the data dictionary (discussed later). If it's more
complicated then he grabs the DBA and talks over the likely changes with him.

Once he's ready to begin he takes a copy of the database master and can modify both the database schema
and code freely. As he's in a sandbox any changes he makes don't impact anyone else's. At some point, say
around 3pm, he's pretty comfortable that he knows what the database change needs to be, even though he's
not completely done with his programming task. At that point he grabs the DBA, and tells him about the

http://www.martinfowler.com/articles/evodb.html (4 of 11)05/12/2003 15:36:15


Evolutionary Database Design

change. At this point the DBA can raise any issues that Mike hasn't considered. Most of the time all is well
and the DBA goes off and makes the change (by applying one or more database refactorings, which we'll
come to below). The DBA makes the changes right away (unless they are destructive changes - again
more on that below). Mike can continue to work on his task and commit his code any time he likes once
the DBA has applied these changes to the master.

You may well recognize this principle as similar to the practice of Continuous Integration, which is
applied to source code management. Indeed this is really about treating the database as another piece of
source code. As such the master database is kept under configuration management in much the same way
as the source code. Whenever we have a successful build, the database is checked into the configuration
management system together with the code, so that we have a complete and synchronized version history
of both.

With source code, much of the pain of integration is handled by source code control systems. For
databases there's a bit more effort involved. Any changes to the database need to done properly, as
automated database refactorings, which we'll discuss shortly. In addition the DBA needs to look at any
database changes and ensure that it fits within the overall scheme of the database schema. For this to work
smoothly, big changes shouldn't come as surprises at integration time - hence the need for the DBA to
collaborate closely with the developers.

We emphasize integrating frequently because we've found that it's much easier to do frequent small
integrations rather than infrequent large integrations. It seems that the pain of integration increases
exponentially with the size of the integration. As such doing many small changes is much easier in
practice, even though it often seems counter-intuitive to many. This same effect's been noticed by people
in the Software Configuration Management community for source code.

A database consists of schema and test data

When we talk about a database here, we mean not just the schema of the database, but also a fair amount
of data. This data consists of common standing data for the application, such as the inevitable list of all the
states in the US, and also sample test data such as a few sample customers.

The data is there for a number of reasons. The main reason is to enable testing. We are great believers in
using a large body of automated tests to help stabilize the development of an application. Such a body of
tests is a common approach in agile methods. For these tests to work efficiently, it makes sense to work on
a database that is seeded with some sample test data, which all tests can assume is in place before they run.

As well as helping test the code, this sample test data also allows to test our migrations as we alter the
schema of the database. By having sample data, we are forced to ensure that any schema changes also
handle sample data.

In most projects we've seen this sample data be fictional. However in a few projects we've seen people use

http://www.martinfowler.com/articles/evodb.html (5 of 11)05/12/2003 15:36:15


Evolutionary Database Design

real data for the samples. In these cases this data's been extracted from prior legacy systems with
automated data migration scripts. Obviously you can't migrate all the data right away, as in early iterations
only a small part of the database is actually built. But the idea is to iteratively develop the migration
scripts just as the application and the database are developed iteratively. Not just does this help flush out
migration problems early, it makes it much easier for domain experts to work with the growing system as
they are familiar with the data they are looking at and can often help to identify problem cases that may
cause problems for the database and application design. As a result we are now of the view that you
should try to introduce real data from the very first iteration of your project.

All changes are database refactorings

The technique of refactoring is all about applying disciplined and controlled techniques to changing an
existing code base. Similarly we've identified several database refactorings that provide similar control
and discipline to changing a database.

One of the big differences about database refactorings is that they involve three different changes that
have to be done together

● Changing the database schema


● Migrating the data in the database
● Changing the database access code

Thus whenever we describe a database refactoring, we have to describe all three aspects of the change and
ensure that all three are applied before we apply any other refactorings.

We are still in the process of documenting the various database refactorings, so we aren't able to go into
detail on them yet. However there are a few things we can point out. Like code refactorings, database
refactorings are very small. The concept of chaining together a sequence of very small changes is much
the same for databases as it is for code. The triple nature of the change makes it all the more important to
keep to small changes.

Many database refactorings, such as adding a column, can be done without having to update all the code
that accesses the system. If code uses the new schema without being aware of it, the column will just go
unused. Many changes, however don't have this property. We call these destructive changes, an example
of which is making an existing nullable column not null.

Destructive changes need a bit more care, the degree of which depends on the degree of destruction
involved. An example of a minor destructive change is that of changing a column from nullable to not
null. In this case you can probably just go ahead and do it. The refactoring will take care of any data in the
database that's null. Usually the only developer who cares about this property is the one who requested the
change, and that developer will update the database mapping code. As a result the update won't break
anyone else's code and if by some strange chance it does, they find out as soon as they run a build and use
their tests. (On our large project we gave ourselves some extra breathing space by waiting a week before

http://www.martinfowler.com/articles/evodb.html (6 of 11)05/12/2003 15:36:15


Evolutionary Database Design

making the database change.)

Splitting a heavily used table into two however is a rather more complicated case. In this case it's
important to let everyone know that the change is coming up so they can prepare themselves for it. In
addition it's worth waiting for a safer moment to make the change. (These kinds of changes we would
defer until the start of a new iteration - we like to use iterations of two weeks or less).

The important thing here is to choose a procedure that's appropriate for the kind of change that you're
making. If in doubt try to err on the side of making changes easier. Our experience is that we got burned
much less frequently than many people would think, and with a strong configuration control of the entire
system it's not difficult to revert should the worst happen.

Automate the refactorings

In the world of code we are seeing tools for some languages to automate many of the identified
refactorings. Such automation is essential for databases; at least in the areas of schema changes and data
migration.

As a result every database refactoring is automated by writing it in the form of SQL DDL (for the schema
change) and DML (for the data migration). These changes are never applied manually, instead they are
applied to the master by running a small SQL script to perform the changes.

Once done, we keep hold of these script files to produce a complete change log of all the alterations done
to the database as a result of database refactorings. We can then update any database instance to the latest
master by running the change log of all the changes since we copied the master to produce the older
database instance.

This ability to sequence automated changes is an essential tool both for the continuous integration process
in development, and for migrating production databases to a new release.

For production databases we don't make changes during the usual iteration cycles. Once we do a release,
which may occur at the end of any iteration, we apply the full change log of database refactorings since
the previous release. This is a big change, and one that so far we've only done by taking the application
offline. (We have some ideas for doing this in a 24/7 environment, but we haven't actually had to do it
yet.) It's also wise to test this migration schema before applying it to the live database. So far, we've found
that this technique has worked remarkably well. By breaking down all the database changes into a
sequence of small, simple changes; we've been able to make quite large changes to production data
without getting ourselves in trouble.

As well as automating the forward changes, you can consider automating reverse changes for each
refactoring. If you do this you'll be able to back out changes to a database in the same automated way. We
haven't done this yet, as we've not had a much demand for it, but it's the same basic principle.

http://www.martinfowler.com/articles/evodb.html (7 of 11)05/12/2003 15:36:15


Evolutionary Database Design

(A similar thing that we have done is to support an old version of an application with an updated version
of the database. This involved writing a compatibility layer that allowed the application to think it was
talking to the older version of the database even though it was actually talking to the newer one.)

Automatically Update all Database Developers

It's all very well for people to make changes and update the master, but how do they find out the master
has changed? In a traditional continuous integration environment with source code, developers update to
the master before doing a commit. That way they can resolve any build issues on their own machine
before committing their changes to the shared master. There's no reason you can't do that with the
database, but we found a better way.

We automatically update everyone on the project whenever a change is made to the database master. The
same refactoring script that updates the master automatically updates everyone's databases. When we've
described this, people are usually concerned that automatically updating developers databases underneath
them will cause a problem, but we found it worked just fine.

This only worked when people were connected to the network. If they worked offline, such as on an
airplane, then they had to resync with the master manually once they got back to the office.

Clearly separate all database access code

To understand the consequences of database refactorings, it's important to be able to see how the database
is used by the application. If SQL is scattered willy-nilly around the code base, this is very hard to do. As
a result it's important to have a clear database access layer to show where the database is being used and
how. To do this we suggest following one of the data source architectural patterns from P of EAA.

Having a clear database layer has a number of valuable side benefits. It minimizes the areas of the system
where developers need SQL knowledge to manipulate the database, which makes life easier to developers
who often are not particularly skilled with SQL. For the DBA it provides a clear section of the code that he
can look at to see how the database is being used. This helps in preparing indexes, database optimization,
and also looking at the SQL to see how it could be reformulated to perform better. This allows the DBA to
get a better understanding of how the database is used.

Variations
Like any set of practices, these should be varied depending on your specific circumstances. These
practices are still pretty new, so we haven't come across that many variations, but here are some we have.

Keeping multiple database lineages

http://www.martinfowler.com/articles/evodb.html (8 of 11)05/12/2003 15:36:15


Evolutionary Database Design

A simple project can survive with just a single database master in the repository. With more complex
projects there's a need to support multiple varieties of the project database, which we refer to as database
linages. We may create a new lineage if we have to branch an application that's put into production. In
essence creating a new database lineage is much the same as branching the source code on the application,
with the added twist that you also make a lineage when you need a different set of sample data, such as if
you need a lot of data for performance testing.

When a developer takes a copy of a master they need to register which lineage they are modifying. As the
DBA applies updates to a master for a particular lineage the updates propagate to all the developers who
are registered for that lineage.

You don't need a DBA

All of this sounds like it would be a lot of work, but in fact it doesn't require a huge amount of manpower.
On the Atlas project we had thirty-odd developers and a team size (including, QA, analysts and
management) of close to a hundred. On any given day we would have a hundred or so copies of various
lineages out on people's workstations. Yet all this activity needed only one full time DBA (Pramod) with a
couple of developers doing some part-time assistance and cover.

On smaller projects even that isn't needed. We've been using these techniques on a number of smaller
projects (about a dozen people) and we find these projects don't need a full time DBA. Instead we rely on
a couple of developers with an interest in DB issues who handle the DBA tasks part-time.

The reason for this is automation. If you are determined to automate every task, you can handle a lot work
with much less people.

Tools to Help
Doing this kind of thing requires a lot of repetitive tasks. The good news is that whenever you run into run
into repetitive tasks in software development you are ideally placed to automate them. As a result we've
developed a fair amount of often simple tools to help us.

One of the most valuable pieces of automation is a simple set of scripts for common database tasks.

● Bring a user up to date with the current master.


● Create a new user
● Copy a database schema, for example Sue finds a bug with her database, now Mike can copy Sue's
database and try to debug the application
● Move a database, for example from a workstation to a different workstation, this is essentially
Copy database and Delete database combined as one
● Drop a user
● Export a user so team members can make offine backups of the database that they are working

http://www.martinfowler.com/articles/evodb.html (9 of 11)05/12/2003 15:36:15


Evolutionary Database Design

with.
● Import a user, so if the team members have a backup copy of the database, they can import the
backup and create a new schema.
● Export a baseline - make a backup copy of the master database. This is a specialized case of Export
a User
● Create a difference report of any number of schemas, so that Mike can find out what is different
structurally between his database and Sue's.
● Diff a schema against the master, so that developers can compare their local copy against the
master.
● List all the users

Analysts and QA folks often need to look at the test data in the database and to be able to easily change it.
For that we created an Excel application with VBA scripts to pull data down from the database into an
excel file, allow people to edit the file, and send the data back up to the database. Although other tools
exist for viewing and editing the contents of a database, excel works well because so many people are
familiar with it.

Everybody on the project needs to be able to explore the database design easily, that way they can find out
what tables are available and how they are used. We built an HTML based tool to do this that used servlets
to query database metadata. So Mike before adding the column to a table, could go lookup if the column
he is adding already exists, by searching the metadata of the tables and columns. We did the data modeling
using ERwin and pulled data from ERwin into our own metadata tables.

Further Steps and Further Information


This is by no means the last word on the subject of evolutionary database design. We certainly want to see
if and how we can extend these techniques to integration databases, 24/7 operation, and other problem
areas that we haven't run into yet.

If you'd like to find out more about this, or talk about your own experiences, Pramod has started a yahoo
egroup for agile databases. Pramod is also starting to talk about these techniques at various conferences, so
you may get a chance to talk to him directly. Naturally we also do consulting on this stuff too.

Revision History

Here's a list of the major updates to this paper

● January 2003: First publication

http://www.martinfowler.com/articles/evodb.html (10 of 11)05/12/2003 15:36:15


Evolutionary Database Design

© Copyright Martin Fowler, all rights reserved

http://www.martinfowler.com/articles/evodb.html (11 of 11)05/12/2003 15:36:15


Analysis Patterns 2 - Work in Progress

Analysis Patterns 2 - Work in Progress

● Temporal Patterns
● Quantity and Range
● Accounting patterns: a (considerable) update of the material in the Analysis Patterns book.
● Accountability narrative and patterns

For a while now, I've been working on analysis patterns again. Currently my plans are not to write a
second edition of analysis patterns, but rather to work on writing patterns that I think are particularly
important to write. This includes some material from the original analysis patterns book, but also some
new material. In my current thinking I'll produce a new analysis patterns book at some point, but this
will only partially replace the exisiting book. Exactly how much I haven't decided yet.

Here, I intend to put the material on analysis patterns as I come up with it. This way I get the maximum
amount of information out to people who might use it, and I also hope to get feedback on the patterns so
far. I'm very interested in your experiences with these patterns. Have you used these patterns? Were they
useful or not? Have you come across interesting variations? Please let me know and I'll feed comments
back into the material on this site.

Patterns So Far
The first set of patterns I made available were the accountability patterns, which essentially reworks the
patterns from chapter 2 of analysis patterns into the new form that I'm now using. These patterns come
in two pdf files: a narrative and a collection of patterns. I'm moving away from using pdf and will use
html for future patterns - but it will probably be a while before I move these ones over to the new
physical format.

Two small, but very common patterns are Quantity and Range. These a small fundamental patterns, yet
ones that are used pretty widely. If you write OO systems they should be an ever-present part of your
toolkit.

Accounting, of one form or another, seems to be a never ending theme in my professional life. Analysis
patterns contained a chapter on accounting patterns, and I've had more ideas since, which are the

http://www.martinfowler.com/ap2/index.html (1 of 3)05/12/2003 15:36:16


Analysis Patterns 2 - Work in Progress

accounting pdf file. The paper includes an opening narrative followed by several patterns. As with the
other patterns, read the narrative first to get an overview of the patterns. You can then use the patterns to
dig into the details. Those who've seen my half-day analysis patterns tutorial over the last year or so will
find the details on the patterns I talk about there in here.

My most recent set of patterns is a set of patterns to do with historic information. Capturing history
usually adds an enormous amount of complexity to models, these patterns help factor the historic issues
out, allowing you to deal with them separately. At the same time the patterns suggest some common
implementation techniques.

The New Form


One of the biggest things I've been experimenting with since the publication of analysis patterns is the
form for patterns. In analysis patterns I used straight narrative. I realized that this made it harder to use
the patterns for reference, but I felt that the narrative form made it easier to discuss the trade offs and
relationships between patterns that, for me, are the heart of what patterns are about. Wrestling between
narrative and reference forms has been a common theme for me ever since

My solution, for the moment, is to divide the writing into two sections. A short narrative section
introduces the patterns, gives an overview of what they are about, and discusses the trade-offs between
them. A longer catalog section takes each pattern in turn, going into all the details. Not just do I feel this
split allows me to have the best of both worlds, it also allows the reader to read just the narratives to
understand what patterns are present and roughly what they mean. That way you don't have to read the
whole book to get a good view of what the patterns are about - you can just read the narratives.

The catalog item details the pattern in the following form.

● the Name
● the Intent
● a Sketch
● How it Works
● When to use it:
● Some code samples showing an example implementation

This format for the patterns is fairly loose, yet I hope shows up the main sections of the patterns.

One item that several people have commented on is the use of code samples. These comments have
varied from the delighted to the horrified. The main reason I use them is to better communicate with
programmers, who after all understand programs. Many programmers had difficulty in understanding
how patterns work just from diagrams and textual descriptions, code samples help sharpen the ideas.

http://www.martinfowler.com/ap2/index.html (2 of 3)05/12/2003 15:36:16


Analysis Patterns 2 - Work in Progress

The first thing to remember is that these are example implementations only. Hardly anyone will be able
to just use them - they will need to adapt them to suit the problem they are working on. They are there to
help explain the ideas, nothing more.

Also the code samples are not essential to understanding the patterns. My aim is that if you can read
UML diagrams reasonably, you should be able to understand the patterns without digging through the
code. So if you don't like reading code, you should just ignore it, and if I'm successful the patterns
should still make sense.

Thanks to those who've commented and pointed out errors. [Ismet Kahraman]

© Copyright Martin Fowler, all rights reserved

http://www.martinfowler.com/ap2/index.html (3 of 3)05/12/2003 15:36:16


Patterns for things that change with time

Patterns for things that change with time

Summarizes various patterns that you can use to answer questions about the state of an information in the past. These include questions
of the form "what was Martin's address on 1 Jul 1999" and "what did we thing Martin's address was on 1 Jul 1999 when we sent him a
bill on 12 Aug 1999".

Things change. If we store information about the world this may not be a problem. After all when something changes one of the great
values of a computerized record system is that it allows us to easily update a record without resorting to liquid paper or retyping pages
of information.

Things get interesting, however, when we need to record the history of the changes. Not just do we want to know the state of the world,
we want to know the state of the world six months ago. Even worse we may want to know what two months ago we thought the state of
the world six months ago was. These questions lead us into a fascinating ground of temporal patterns, which are all to do with
organizing objects that allow us to find answers to these questions easily, without completely tangling up our domain model. Of all the
challenges of object modeling, this is both one of the most common and most complicated.

The simplest way to solve this problem is to use an Audit Log. Here you are concerned with keeping a record of changes, but you don't
expect to go back and use it very often. Therefore you want it to be easy to create and be minimally intrusive upon your work. When
someone needs to look at it, then you expect they will have to do a lot of work to dig out the information. If they don't need to do it very
often, and don't need the resulting information quickly, then this is fine. Indeed if you're using a database, it's free.

When the information has to be more accessible, then you need to work a little more at it. The most common pattern that people use in
this situation is Effectivity. This simply marks an object with the time period that it is considered valid ( Figure 1). Then as you
manipulate your objects you use this time period to get the right object at the right time.

Figure 1: Using an explicit date range to show effectivity.

The problem with Effectivity is that it is obvious and explicit. Everyone using the object in all contexts has to be aware of the temporal
aspect. This can complicate a model considerably. So if temporal issues are pervasive then it often makes sense to hide them when you
don't need them, and make them more convenient to work with when you do.

If you have just a few properties of objects that need easily accessible temporal information, then you can use Temporal Property on
those objects. The essential point of Temporal Property is that you remove the obvious effectivity date, instead you use what looks like
a regular property, but with an accessor that takes a date as an argument. This allows you to ask "what is the value of this property at
April 1st 2000".

http://www.martinfowler.com/ap2/timeNarrative.html (1 of 6)05/12/2003 15:36:18


Patterns for things that change with time

Figure 2: Using a temporal property for the address..

The essence of Temporal Property is this notion of having an accessor that is parameterized by date that frees the users of this property
from having to navigate through a bunch of objects with Effectivity. Therefore Temporal Property and Effectivity are not mutually
exclusive patterns. You might use address usage objects (using Effectivity) to implement a Temporal Property interface. If the address
usage objects carry other responsibilities you may provide methods that access the address usages for those clients that need those other
responsibilities and a Temporal Property interface for those who find that more convenient.

Temporal Property introduces the notion of referring to things with a time-based index, but takes it only so far as a single property. If
you have many temporal properties on an object, things can become clumsy. There are two ways of dealing with this. The first is to use
Snapshot, which gives you an object that refers to the state of the real object as at a point in time. Thus if you want to ask a lot of
questions of a customer as at April 1st 2000 you ask for a Snapshot of that customer for April 1st 2000 and then ask for values of
properties without having to keep repeating the date.

Figure 3: A snapshot shows a view of an object as at some date.

Snapshot allows you to have a view of an object at a date, but sometimes you really want to think of an object going through explicit
versions as changes are made through time. This desire leads to Temporal Object. Temporal Object comes in many forms, but the most
straightforward form has two classes as in Figure 4. The contract class is the one that is usually referred to by other objects as it
represents the contract through time. It contains a collection of versions which record the state of the contract at each change. This
allows people to refer to either the unchanging notion of a contact, or a specific version at a particular point in time.

Figure 4: Temporal Objects have an explicit history of versions, so that each change leads to a new version.

In practice I see Effectivity used widely, but often that is because people aren't familiar enough with Temporal Property and the other
more sophisticated patterns. Patterns like Temporal Property and Temporal Object work well because they hide much of the mechanics

http://www.martinfowler.com/ap2/timeNarrative.html (2 of 6)05/12/2003 15:36:18


Patterns for things that change with time

of temporal behavior. However Effectivity still is important: it is the right choice when people want an explicit object that is only valid
for a particular time period.

Dimensions of Time
Just as I've described above, time is a pretty challenging notion in modeling. However I've skipped over the most awkward aspect of
temporal models. We've all learned, if only from bad Science Fiction books, that time is the fourth dimension. The trouble is that this is
wrong.

I find the best way to describe this problem is with an example. Imagine we have a payroll system that knows that en employee has a
rate of $100/day starting on January 1. On February 25 we run the payroll with this rate. On March 15 we learn that, effective on
February 15, the employee's rate changed to $211/day. What should we answer when we are asked what the rate was for February 25?

In one sense we should answer $211, since now we know that that was the rate. But often we cannot ignore that on Feb 25 we thought
the rate was $100, after all that's when we ran payroll. We printed a check, sent to him, and he cashed it. These all occurred based on
the amount that his rate was. If the tax authorities asked us for his rate on Feb 25, this becomes important.

In fact we can think that there are indeed two histories of Dinsdale's pay rate that are important to us. The history that we know now,
and the history we knew on February 25. Indeed in general we can say that not just is there a history of dinsdale's pay rate for every day
in the past, but there is a history of histories of Dinsdale's pay rates. Time isn't the fourth dimension, it's the fourth and fifth dimensions!

I think of the first dimension as actual time: the time something happened. The second dimension is record time, the time we knew
about it. Whenever something happens, there are always these two times that come with it. Dinsdale's pay raise had a actual date of Feb
15 and a record date of March 15. Similarly when we ask what Dinsdale's pay rate was, we really need to provide two dates: a record
date and an actual date.

record date actual date Dinsdale's rate


Jan 1 Jan 1 $100/day
Feb 15 Feb 15 $100/day
Feb 25 Feb 15 $100/day
Feb 25 Feb 25 $100/day
Mar 14 Feb 15 $100/day
Mar 15 Jan 1 $100/day
Mar 15 Feb 15 $211/day
Mar 15 Feb 25 $211/day

We can think of the two dimensions like this. The actual history is looking back in actual time. If I look at my current actual history,
then I see that Dinsdale's pay was $100 up to Feb 15, at which point it increased to $211. However that is the actual history for today in
record time. If I look at the actual history for Feb 25, then Dinsdale was paid at $100 from Jan 1 onwards, and the $211 never came into
it. Every day (strictly every Time Point) in record time has an actual history. These histories are different as we find out that things we
used to think were true are no longer true.

From another angle we can say that each day in actual history has a record history. The record history tells us how our knowledge of
that day changed over time. So Feb 25 in actual time has a record history that says that up to March 15, Dinsdale's pay was $100 at
which point it reaches $211.

Let's take this example a step further Assume we make the corresponding adjustments in a payroll run on March 26. On April 4 we are
told that the employee's our previous information was wrong and that the rate was actually changed to $255 on February 15. Now how
do we answer the question "what was the employee's rate on February 25?".

I've seen grown developers bite their own heads off when faced with this kind of stuff. But once you realize that everything comes
down to this notion of two dimensions, then things start getting a lot simpler. One way of visualizing this to extend the earlier table

http://www.martinfowler.com/ap2/timeNarrative.html (3 of 6)05/12/2003 15:36:18


Patterns for things that change with time

record date actual date employee's rate


Jan 1 Jan 1 $100/day
Feb 15 Feb 15 $100/day
Feb 25 Feb 15 $100/day
Feb 25 Feb 25 $100/day
Mar 14 Feb 25 $100/day
Mar 15 Jan 1 $100/day
Mar 15 Feb 15 $211/day
Mar 15 Feb 25 $211/day
Mar 26 Feb 25 $211/day
Apr 4 Jan 1 $100/day
Apr 4 Feb 14 $100/day
Apr 4 Feb 15 $255/day
Apr 4 Feb 25 $255/day

If we look at our current actual history (that is the actual history whose record date is today) then we would say that Dinsdale's pay was
$100 from Jan 1 and went up to $255 on Feb 15. For the current actual history the $211 rate doesn't occur at all because it was never
true. If we look at the actual history for March 26 we would see Dinsdale's pay at $100 up to Feb 15 where it went up to $211. In the
actual history for March 26 the $255 rate never happened because we didn't know of it yet.

We can also think about the record history for Feb 25. Now this record history says that the rate was $100 (on that day) until March 15
when it changed to $211. Then on April 4 it changed again to $255.

Once you realize about the two dimensions then it becomes much easier to think about the problem, but scary to think that you have to
implement this kind of stuff. Fortunately there are a number things you can do that simplifies matters when it comes to implementation.

The first simplification is that it isn't difficult to use Audit Log to cope with these changes. All you need to do is record both the record
date and the actual date in the log with each entry. This simple exercise is enough to keep any log effective over both dimensions, and I
belive is worth doing even if you are only bothered about one of them.

The second simplification is that you often don't want your model to handle both dimensions. The important thing here is to know
which you have in your model and which one you are leaving to Audit Log.

If we want to keep a history of things where we want to know how things changed over time, but didn't care about when we learned of
changes, we would say that was actual-temporal. So if I keep a record of an employee's address I might choose to keep that as a actual-
temporal property. For information systems that are there to help on-line query this works well because when you are accessing a
database you usually want to know about actual-history.

Record-temporal facts appear when you have a system that does things like producing bills based on the state of objects. These things
lead to questions about how the bill was calculated, which leads you to need to know what thought the state of and object was when the
bill was calculated. Record-temporal facts can often be compared to a version control system in software where you can go back and
say 'what was this file like on April 1?'

Of course there are times when you need both dimensions at once - these are called bi-temporal facts. Essentially bi-temporal
information always needs both dates.

Bi-temporality is the full solution, but it's always worth thinking of ways around it. An example comes from bill calculation. If you
want to find out why a bill came out to what it was one possibility is to have a fully bi-temporal database. However it's often better to
store a detailed trace of the calculations when you calculate the bill. That satisfies the requirement in a much simpler way than a bi-
temporal object model.

http://www.martinfowler.com/ap2/timeNarrative.html (4 of 6)05/12/2003 15:36:18


Patterns for things that change with time

Updating a Temporal Record


So far I've only talked about temporal information in terms of accessing information, not in terms of updating it. How you allow your
updates leads to more decisions, but many of these involve useful simplifications.

In general changing the time record is quite messy. If we have an employee whose rate was $211 from Feb 15 to Apr 15, a fully general
update will allow to change any combination of start date, end date, and value. Providing an interface for this is awkward since it
requires the client to know a lot about how temporal information works.

The first simplification is that you may have only additive changes. An additive change always goes onto the end of the record. An
example of an additive change is "make the employees rate $211 effective Feb 15". Although at first blush this looks like you are only
removing one piece of data from the mix, the consequences actually work out so that it greatly simplifies the update. Most of the
updates that happen in practice are additive, so that can greatly simplify clients. Furthermore you can make any change with some
combination of additive updates. While this would get horribly messy on an object with a complicated history, this property can
simplify objects with a simple history by allowing you to only support an additive interface.

The second simplification is allowing only current updates. A current update allows changes in the record only with an effective date of
today. In general even additive changes can occur at any date in the past or future. A current change requires no date information at all,
allowing you to have an interface for updates that is completely non-temporal.

Current updates seem too good to be true, why have temporal information if you only update it with current updates? The good news
here is that record-temporal information can only be updated with current updates. Not just would a retroactive change to record-
temporal information break the integrity of the record, there's no situation that requires a retroactive change that can't be handled by the
actual-time dimension (unless fraud is one of your requirements). This is a big step as it means that one whole dimension has invisible
updates - you only have to worry about record time when querying, not when updating.

Other Readings
Since this is a complicated area, it has generated some other writings as people have explored these problems. The most comprehensive
treatment of this area is Snodgrass. His work is based on relational databases and most of the book is based on how to handle these
issues in SQL. The problem, however, is the same. Furthermore much of the comments he makes and terminology he uses is the same
as the forthcoming SQL standard's material on temporal databases.

The matter of terminology is one that I'm still not completely happy with. He uses the same two dimensions that I do, but his terms are
different. What I call actual time he calls valid time, what I call record time he calls transaction time. In earlier versions of these
patterns I followed his terms, but many people said they found these terms very difficult to follow. As a result I decided to use different
terms. Another difference is that he refers to a table that changes over time as sequenced. Of course, objects use sequences all the time,
not just for temporal purposes, so I've called things that change over time temporal.

[Anderson] is one of the best collections of temporal patterns. Again I've plundered ideas, but changed some terminology. I've used the
term version rather than edition to mean a value for a property or object during some time period. His Change Log and History on
Association patterns are the same as Temporal Property. I see the difference between the two Anderson patterns as more a matter of
implementation. His History on Self pattern is the same as Temporal Object.

Also in the same PLoPD 4book, you'll find a paper [Carlson et al]written by Andy Carlson in collaboration with myself and Sharon
Estepp. This gives earlier descriptions of Temporal Property and Snapshot. It also mentions a pattern Temporal Association which I
now look at as a use of Effectivity.

Also submitted to PLoP, but not available publicly at the moment is [Arnoldi et al]. This introduces a number of interesting ideas that I
haven't fully explored in the patterns here (at least not yet).

Both [Anderson] and [Arnoldi et al] consider using objects other than Time Point to act as indexes into the temporal record. [Anderson]

http://www.martinfowler.com/ap2/timeNarrative.html (5 of 6)05/12/2003 15:36:18


Patterns for things that change with time

uses a (single-temporal) event, and [Arnoldi et al] use a perspective: essentially two timepoints combined into a single object. Although
there are things to be said for both of these approaches, I haven't used them here as I feel that using time points does most of what you
need, and is simpler to explain.

List of Patterns
Audit Log
A simple log of changes, intended to be easily written and non-intrusive.
Effectivity
Add a time period to an object to show when it is effective.
Snapshot
A view of an object at a point in time
Temporal Object
An object that changes over time
Temporal Property
A property that changes over time
Time Point
Represents a point in time to some granularity

References

"Snodgrass"
Snodgrass, Developing Time-oriented Database Applications in SQL, Morgan-Kaufmann, ISBN: 1558604367 (1999)
[Anderson]
Anderson, "A Collection of History Patterns", in Harrison, Foote, and Rohnert (eds), Pattern Languages of Program Design 4,
Addison-Wesley, ISBN: 0201433044 (1999) , pages 263-297
"PLoPD 4"
Harrison, Foote, and Rohnert (eds), Pattern Languages of Program Design 4, Addison-Wesley, ISBN: 0201433044 (1999)
[Carlson et al]
Carlson, Estepp, and Fowler, "Temporal Patterns", in Harrison, Foote, and Rohnert (eds), Pattern Languages of Program Design
4, Addison-Wesley, ISBN: 0201433044 (1999) , pages 241-262
[Arnoldi et al]
Arnoldi, Beck, Bieri, and Lange, Time Travel: A Pattern Language for Values that Change,

© Copyright Martin Fowler, all rights reserved

http://www.martinfowler.com/ap2/timeNarrative.html (6 of 6)05/12/2003 15:36:18


Analysis Pattern: Quantity

Quantity

Represent dimensioned values with both their amount and their unit

There are many cases where we want computers to represent dimensioned quantities: values such as six
feet, or thirty kilograms. Usually these are represented as bare numbers, mainly because that is the best
we can do in the limited type systems that languages give us.

But using objects invites us to add new fundamental types whenever they add value, and having a
specific type for dimensioned quantities adds quite a lot of value. This is particularly true when the
dimensioned value is that of Money. Money is a special case of Quantity, but also one that perhaps the
most widely used, as plenty of people are prepared to spend money to watch money.

How it Works
The basic idea of Quantity is a class that combines the amount with the unit. In saying that a quantity is
a simple representation. However the real fun with Quantity comes with the behavior that you can apply
to it.

The first kind of behavior is arithmetic. You should be able to add two quantities together just as easily
as you can add two numbers. Furthermore more the quantities should be intelligent about addition and
subtraction: at the least preventing you from adding 6 feet to 180 pounds.

More complicated issues with addition arise where you are trying to add similar units, such as adding
500 meters to 3 kilometers. The simplest approach is to deny that addition, forcing the client to make the
conversion. A more sophisticated approach is to see if you can convert one argument to the other, if so
you can perform the addition. How well you can do this depends on the sophistication of your

http://www.martinfowler.com/ap2/quantity.html (1 of 7)05/12/2003 15:36:19


Analysis Pattern: Quantity

Convertor.

Multiplication has similar variations in sophistication. The simplest approach is to only permit
multiplication and division by scalar numbers. A more sophisticated approach is to allow multiplication
by other quantities, but then you have to work out the units of the result. So if you divide 150 miles by 2
hours you get 75 miles/hour.

Comparison operations are needed so you can find out if six feet is more than five feet. The issues here
are much the same as those for addition - you have to choose how much conversion you do.

It's useful to provide a simple interface to allow conversion on a quantity directly, although the
conversion work is usually best left using Convertor. If you only have a few units, however, it's easier to
embed them directly in quantity classes.

One of the most useful behaviors you can give to quantities is to provide printing and parsing methods
that allow you easily produce strings and to produce a quantity from a string. This simple pattern can do
much to simplify a lot of input and output behavior, either to files or in GUI interfaces.

For simple printing you can have a default, such as first printing the amount and then the unit. That
breaks down when in some cases you want to print the unit before the number and other cases
afterwards. Usually this kind of variation will depend on the unit, so in these cases you can put the
printing and parsing behavior on the unit and delegate to that.

Money

I use Quantity on almost every system I work with, but I rarely use it to represent physical units. Most of
the time I use it to represent money. Much of the comments for physical units are the same, but money
does have its own spin to bear in mind when you're working with it.

The biggest change surrounds the whole area of conversion. While physical units' forms of conversion
don't change over time, exchange rates for money are always changing. Obviously this affects
conversion operations, but the effect ripples into the addition, subtraction, and comparison operations as
well.

When you convert money, at the least you need to provide some kind of time reference, whose
granularity will depend on the application. But in many cases you may have separate conversions in
different contexts - all of which I explore in Convertor

The upshot of all this is that you need to be much more careful about automatic conversion inside
arithmetic or comparison operations with money. So often you'll find they are not allowed. However
there is an ingenious solution to addition operations with money that you'll find in Money Bag.

http://www.martinfowler.com/ap2/quantity.html (2 of 7)05/12/2003 15:36:19


Analysis Pattern: Quantity

A particularly useful feature with Money in addition to those for Quantity is the handling of rounding.
Money is often expressed with a decimal part, yet you should never use real numbers for handling
Money. The reason for this is that the rounding behavior of real numbers almost never corresponds to
what's needed for money, and ignoring this fact can easily lead to intermittent bugs which are small in
denomination and high in frustration.

A money object, however, can encode its own rules for rounding, which means that most of the time you
don't have to be aware of the rounding rules while you are working with money.

Connected to this is the knotty matter of division. If you divide $100 by three, what do you get? Usually
the answer is not as simple $33.33. The problem is that if you multiply $33.33 you get $99.99 - meaning
that a penny goes missing. Accountants don't like pennies to go missing. So you'll have to find out what
policy applies to the situation you're looking at. Often the rule is that someone should get extra penny,
although it doesn't matter who. So you can put a method in the money object to return a collection of the
monies that you need to hand out from the division.

Relational Databases

A common question with Quantity is how to use it for relational databases and other systems without the
ability to create new lightweight types. Do you store an amount and a currency code with every
monetary value?

The issue here comes when there is a constraint in place that forces all monies to be of the same
currency in a certain context. So consider the case where you have an account with many entries. Each
entry has a money attribute to show the amount of the entry, yet all the entries on an account have the
same currency. Is it reasonable to store the currency once on the account and not duplicate the currency
across the entries?

I'm inclined to punt on this question, and leave it to the specifics of your database design. I would still
urge you to use money objects in your code: it's up to you whether how you store those in the database.
After all the database doesn't give you any behavioral advantages from Quantity. You only get those in
the code.

When to Use it
As you've gathered I use Quantity, at least in the money variation, a lot. Indeed with an object-oriented
environment there's little reason not use it. Often I've noted that people are scared about using small
objects like this mostly due to unfamiliarity. Performance is an oft-cited concern, although I've not seen
or heard of Quantity being a really problem for performance.

There's an argument that says that using Quantity isn't worth it when there's only one unit, so you

http://www.martinfowler.com/ap2/quantity.html (3 of 7)05/12/2003 15:36:19


Analysis Pattern: Quantity

shouldn't use money when you only have one currency. But much of the value of money comes from its
behavior, not its multi-unit capabilities, so I would use it even then.

Example: Money
Money is my most common use of Quantity, so it makes a good place for an example. First the basic
representation:

class Money...
public class Money implements Comparable{
private BigInteger amount;
private Currency currency;

Notice that I use a BigInteger. In Java I could equally well use a BigDecimal, but in many languages an
integer is the only decent option, so using an integer seems the best for explanation. Don't be afraid to
choose your representation of the amount part of a quantity based on performance factors. The beauty of
objects is that you can choose any data structure you like on the inside, providing you hide it on the
outside.

So moving to the interface. You'll probably want the obvious getting methods.

class Money...
public double amount() {
return amount.doubleValue() / 100;
}
public Currency currency() {
return currency;
}

Although you shouldn't find yourself using them very much. Usually other methods will be better for
your purpose. Indeed using the getters on quantity should always spark a thought in your mind as to
whether there is a better way. Usually there is.

You'll notice there are no setters. Money is a Value Object and is thus immutable.

It helps to have a variety of constructors to make it easy to make monies. Constructors that convert from
basic numeric types are always useful.

class Money...
public Money (double amount, Currency currency) {
this.amount = BigInteger.valueOf(Math.round (amount *

http://www.martinfowler.com/ap2/quantity.html (4 of 7)05/12/2003 15:36:19


Analysis Pattern: Quantity

100));
this.currency = currency;
}
public Money (long amount, Currency currency) {
this.amount = BigInteger.valueOf(amount * 100);
this.currency = currency;
}

If you use one currency a lot, you may want a special constructor for that currency.

class Money...
public static Money dollars(double amount) {
return new Money (amount, Currency.USD);
}

For addition and subtraction I'm not trying to do any fancy conversion. Notice that I'm using a special
constructor with a marker argument.

class Money...
public Money add (Money arg) {
assertSameCurrencyAs(arg);
return new Money (amount.add(arg.amount), currency,
true);
}
public Money subtract (Money arg) {
return this.add(arg.negate());
}
void assertSameCurrencyAs(Money arg) {
Assert.equals("money math mismatch", currency, arg.
currency);
}
private Money (BigInteger amountInPennies, Currency currency,
boolean privacyMarker) {
Assert.notNull(amountInPennies);
Assert.notNull(currency);
this.amount = amountInPennies;
this.currency = currency;
}
public Money negate() {
return new Money (amount.negate(), currency, true);
}

http://www.martinfowler.com/ap2/quantity.html (5 of 7)05/12/2003 15:36:19


Analysis Pattern: Quantity

Multiplication is very straightforward.

class Money...
public Money multiply (double arg) {
return new Money (amount() * arg, currency);
}

But division is not, as we have to take care of errant pennies. We'll do that by returning an array of
monies, such that the sum of the array is equal to the original amount, and the original amount is
distributed fairly between the elements of the array. Fairly in this sense means those at the begriming get
the extra pennies.

class Money...
public Money[] divide(int denominator) {
BigInteger bigDenominator = BigInteger.valueOf
(denominator);
Money[] result = new Money[denominator];
BigInteger simpleResult = amount.divide
(bigDenominator);
for (int i = 0; i < denominator ; i++) {
result[i] = new Money(simpleResult, currency,
true);
}
int remainder = amount.subtract(simpleResult.multiply
(bigDenominator)).intValue();
for (int i=0; i < remainder; i++) {
result[i] = result[i].add(new Money
(BigInteger.valueOf(1), currency, true));
}
return result;
}

Next we'll look at comparing monies, in Java the approach is to implement comparable.

class Money...
public int compareTo (Object arg) {
Money moneyArg = (Money) arg;
assertSameCurrencyAs(moneyArg);
return amount.compareTo(moneyArg.amount);
}

It's also useful to provide some better named operations such as:

http://www.martinfowler.com/ap2/quantity.html (6 of 7)05/12/2003 15:36:19


Analysis Pattern: Quantity

class Money...
public boolean greaterThan(Money arg) {
return (this.compareTo(arg) == 1);
}
public boolean lessThan(Money arg) {
return (this.compareTo(arg) == -1);
}

That makes methods that need the comparison much easier to read.

Since money is a value, it should override equals.

class Money...
public boolean equals(Object arg) {
if (!(arg instanceof Money)) return false;
Money other = (Money) arg;
return (currency.equals(other.currency) && (amount.
equals(other.amount)));
}

Since you override equals, don't forget to also override hash (here's a simple suggestion for that).

class Money...
public int hashCode() {
return amount.hashCode();
}

© Copyright Martin Fowler, all rights reserved

http://www.martinfowler.com/ap2/quantity.html (7 of 7)05/12/2003 15:36:19


Analysis Pattern: Range

Range

Represent a range of values

It's quite common to see comparisons where a value is checked against a range of values. Ranges are
usually handled by a pair of values and you check against them both. Range instead uses a single object
to represent the range as a whole, and then provides the relevant operations to test to see if values fall in
the range and to compare ranges.

How it Works
The basic class is very simple. You have a class with two fields that represent the start and end of the
range. You also provide an includes method that tests to see if the supplied value falls within the range.

You can use Range with any type that supports comparison operations, that is the moral equivalent of <,
>, =, <=, and >=. Depending on the language and the type you may or may not get these exact operators,
but you need the equivalent relationships on the types, that is you need to have some default sort criteria
that allows you to rank the values.

Figure 1: Showing ranges in UML with parameterized type notation

Range is an obvious choice for a parameterized class Figure 1, if your language supports this. In UML

http://www.martinfowler.com/ap2/range.html (1 of 6)05/12/2003 15:36:21


Analysis Pattern: Range

terms you can show ranges of different kinds by using classes with types Range<number> and
Range<date>. This is really just modeling shorthand for Range of Numbers and Range of Dates.
Therefore many people, including myself, prefer to avoid the strange names and just use terms like
Number Range and Data Range.

A more sophisticated Range can be set with a sort criteria. In general this can be any function that's
capable of ranking instances of the type that's being used in the range. The sort criteria is essentially a
function, or an object that wraps a function.

You'll probably have some open ended ranges (eg greater than six). You can handle this a couple of
ways. One is to treat a null value as meaning unlimited. Your range checking code will get a bit more
complicated, but pretty much you can hide this from your users. Another alternative is to make a Special
Case for the extremes (e.g. positive infinity). Whichever choice you make you can hide from users of
the class by having creation methods of the form Range.greaterThan(6).

If the type you are ranging over is continuous (eg a real number) as opposed to discrete (like an integer
or date) you'll need other information to tell if the upper or lower are within the range. With integers you
can choose a range greater than six by setting the lower to seven. However with a real number you don't
want to be using a lower of 6.0000000000001. Use a couple of boolean markers instead.

As well as operations that test if a value is in a range, you can also include operations that compare
ranges: these can tell if one range overlaps another, if one range touches another, or one range includes
another. These can be very helpful when you need to do things like check that some subset of ranges
includes all values in another range.

Range classes obviously suit themselves to parameterized classes, if your language uses them. If not you
are faced with either building them based on an abstract class or creating specialized subtypes for
specific cases. If you are likely to be getting the upper and lower values for other purposes, then the pain
of downcasting will be enough that you'd be better off making a concrete range class.

When thinking about ranges, I find the most common approach is to have a start and an end. However
it's equally useful to have a start and a length, or even an end and length. You can also have all three:
start, end, and length with the obvious constraint between the values.

When to Use it
Range is a pattern I use all the time. Coding an appropriate range class is easy, and once you've done
that it's easier to use a range than to use pairs of values. When modeling it's more explicit to use ranges
than to use pairs - and just as intuitive.

Example: Date Range

http://www.martinfowler.com/ap2/range.html (2 of 6)05/12/2003 15:36:21


Analysis Pattern: Range

For an example I'll use a date range. It's a common range to need to use, and allows me to neatly dodge
the extra complexities of a continuous range. Rather than using Java's standard date, I'm using my own
date class that only has date precision (see the discussion in Time Point.

The basic constructors and accessors are quite simple.

class DateRange...
public DateRange (Date start, Date end) {
this (new MfDate(start), new MfDate(end));
}
public DateRange (MfDate start, MfDate end) {
this.start = start;
this.end = end;
}

class DateRange...
public MfDate end(){
return end;
}
public MfDate start() {
return start;
}
public String toString() {
if (isEmpty()) return "Empty Date Range";
return start.toString() + " - " + end.toString();
}
public boolean isEmpty() {
return start.after(end);
}

The key method to provide in any use of Range is the includes method.

class DateRange...
public boolean includes (MfDate arg) {
return !arg.before(start) && !arg.after(end);
}

I like to provide extra constructors for open-ended ranges and the empty range.

http://www.martinfowler.com/ap2/range.html (3 of 6)05/12/2003 15:36:21


Analysis Pattern: Range

class DateRange...
public static DateRange upTo(MfDate end) {
return new DateRange(MfDate.PAST, end);
}
public static DateRange startingOn(MfDate start) {
return new DateRange(start, MfDate.FUTURE);
}
public static DateRange EMPTY = new DateRange(new MfDate
(2000,4,1), new MfDate(2000,1,1));

It's useful to provide operations which allow you to compare ranges.

class DateRange...
public boolean equals (Object arg) {
if (! (arg instanceof DateRange)) return false;
DateRange other = (DateRange) arg;
return start.equals(other.start) && end.equals(other.
end);
}
public int hashCode() {
return start.hashCode();
}
public boolean overlaps(DateRange arg) {
return arg.includes(start) || arg.includes(end) ||
this.includes(arg);
}
public boolean includes(DateRange arg) {
return this.includes(arg.start) && this.includes(arg.
end);
}

For most applications this is all you need. But certain situations suggest other useful behaviors. One it to
find out what gap exists between two ranges.

class DateRange...
public DateRange gap(DateRange arg){
if (this.overlaps(arg)) return DateRange.EMPTY;
DateRange lower, higher;
if (this.compareTo(arg) < 0) {
lower = this;
higher = arg;

http://www.martinfowler.com/ap2/range.html (4 of 6)05/12/2003 15:36:21


Analysis Pattern: Range

}
else {
lower = arg;
higher = this;
}
return new DateRange(lower.end.addDays(1), higher.
start.addDays(-1));
}
public int compareTo(Object arg) {
DateRange other = (DateRange) arg;
if (!start.equals(other.start)) return start.compareTo
(other.start);
return end.compareTo(other.end);
}

Another is to detect whether two date ranges abut each other.

class DateRange...
public boolean abuts(DateRange arg) {
return !this.overlaps(arg) && this.gap(arg).isEmpty();
}

And to see if a group of ranges completly partitions another range.

class DateRange...
public boolean partitionedBy(DateRange[] args) {
if (!isContiguous(args)) return false;
return this.equals(DateRange.combination(args));
}
public static DateRange combination(DateRange[] args) {
Arrays.sort(args);
if (!isContiguous(args)) throw new
IllegalArgumentException("Unable to combine date ranges");
return new DateRange(args[0].start, args[args.length -
1].end);
}
public static boolean isContiguous(DateRange[] args) {
Arrays.sort(args);
for (int i=0; i<args.length - 1; i++) {
if (!args[i].abuts(args[i+1])) return
false;
}

http://www.martinfowler.com/ap2/range.html (5 of 6)05/12/2003 15:36:21


Analysis Pattern: Range

return true;
}

© Copyright Martin Fowler, all rights reserved

http://www.martinfowler.com/ap2/range.html (6 of 6)05/12/2003 15:36:21



 


 

      
 
  
 
  
 
  
 
 

 


 
 
  

 


  



  
 
  
   
    
 

 !"# 
$ # 
$





  
   

  % 


&'  

  




  


 

(




 

) 
  

  
 

 
 
  
 








  

* 
  



  


   
*
   
  
 


 

 

  






#

  
 

 
 





  

 

Accounting Entries

Events

System


 

  

  





  



(     


 #   

 



  



  ( 
 



   
   +,   
 
 

    

(
 
% 
 



 


 
'
  % 


 

 & 
  +,
 


 
       


  
'


( 
  
 



+,  
 
 



  
 




 



 
 

 

 


  
 
 

 
  
 

 (   
 

 

 
    (

 


     
 
 
 

 
  
 
 
 


   




   



 

 
 
 $ 




& -
 
   
 



 


  
. 
  
    

  
  
  


 /  0,1

reads Processor creates


Event Accounting Entry
process(Event)

  


* 
 
 
  


  
( 
 
 
 -
 

#
 





 
 

(

         






  

 
& 
& 
& &

&

   


.


    
   
  
 
 
 
  



& 
   
 
 
  
 

 
 
(  

 
 


   
 
 

 
 
   /   021

 


 


 
 




 
.





Event
Agreement creates
Accounting Entry
process() find
findAgreement(Event) process(Event)

  


&




 
(

  
 


 
        
  
  


( 
   


  
&  

 






 
3
   
   
  4 
    
  
 
  
   
  
 
       
   





&







%
 

  



 


#
 
 
 
 
  
 

 
 

5 




 

. 
  
  

  



  
 

   ( 

  
       
  

 
  
 

 (
 





 








 




 


Posting Rule creates


Event Type Accounting Entry
1 ✻ process(Event)

1 ✻

✻ 1
Event
Agreement

process() find
getRule(EventType)
findAgreement(Event)

 

 
 
&


 
 

 

  
 

  

 


 

 
  

 . 
 
 

  
 

  
  
 



&



   


  

 
 

 

    
 
 6
3 

 
 

 

 


 
 


 
 


 
 

 





 
( 

 
'





78
 
 

  



 
 '  9
6
  

 


  
: 

  
  

 



.


 


 
 #  


  
 




 

 

 
  

  

#  

*  
 
   
 
 
  
 




 
.     

 





 (




  








Posting Rule
creates
Event Type effectivity: Date Range Accounting Entry
1 ✻ process(Event)
1

✻ 1
Event
Agreement
process() find
findAgreement(Event) getRule(EventType, Date)

    
 

  
   




  

  

    



 


  

   
 % 
.       
6

  
     
  
  
      
 !" # $   "  % &&  

  
  


     



( 
   
 



  
 



 
 
*
  

 



% 
   
 
 
 4


    




 
 
  






 
 
 
 
 

 

   
 
 
&   


 
 

   

  

 % 
 



 
   

  
    & 


 % 

    


 

 
 ( 
 


 

 

 
( 
 
 
 
 


 


 4






!     
  


   
  
;'
 
  
 


 




'
  



 

 
 

   
  
   
 


 
 

 
 
 

 
  (


 


 
 4  
& 

 
 

 
 

  

(  


 

 
 
( 



 
 


 
 
   
 (  
     
 
 
    
   
 
      
 
 



 
(  

  
 



 
 




  
  ** 

% 

 


 
 <
  



 
#

 
 
  
 


 
 


 
 

 

 
   
'
 

  
      
  

 

  
 
 
 


 
 

 



(   
 
 '
.
 '
  



  
  



   





(  

 

  


 
 
       

 .
 



 
 
/  0=1




 


/  0>1

replacement adjusted event


Accounting Event
0..1 0..1

  

 

old events old events


Accounting Event
✻ ✻

Adjustment
0..1 0..1

  

(
   
 


  


 

  


 

 


#
 
 

  
 

 

&
 


  






 
        
(
  

 
 

 

 





  





source
Event Accounting Entry
1 ✻

    





( 
 

 

   0?

 

 

 

  


 
 
 


 

    
 
  

  
 '


 
  
     
 
 


 


      


(
   
 
 6 
 
  

   ! ""
 
  
*

 
 
   
  
 
   

 
 

 

 





 






   





 (  
 
 
   

  
 
     

  
     
    
    
 & 
 
 


 






' 



  
(
 %    
  3 

 




 


 
(  
  

 
 
  % 



  
 


(  




  
* 

 



  


  

(
 

  




'

 
 

 

 
   
 


  
  /
  

 
 
 1 #
     
 
  
 
 

 

 
 

&

 
 %   ! ""
 
  .

   





  


  


 


 

 * 

 


 




 
 
 
   
 
 


  


&
   


 % @

  


 
  
 
  
  

 



#


 
 
 



 % 




:/28

#   " 




$  ""  

Event ✻ 1
subject Event Type
1 ✻ when ocurred : DateTime
when noticed : DateTime

  %   &'( "   


)* 
  '   + )    '
  

* $ 
   ,- .* $ '     *

 $    )+ %" &'(  
 
  
 
(

   
 

  / * 
   $ ' / +

(   -
  
  

    
   



(
 

 
7 


 
   
 
  
 
     




(  
        
    
     

 

( 
 



 

 
 
 





( 

 
 








 
 
*
 

 



 


 
 

 





  

 


(
 

   
  
      
      

  




  

) 
  

A 
B 
  
  
   
 

   
 
 ( 
   

 
 
   
     
  
   




& 

    



 
 
   






  



 
 
 


 

5






 

 





 
 





*     
   
 
 
       

    
 
 (       
  
   
 
  




& 
 



  
 
 
  
  
  
   
    
:
( 



*  


(   
 

  
 
  
        
   

 




7   


  
5
  

3 

  
 


   



 
 
 
  
  
 
  

 






5
  



 

 

 
5
 


 





. 
  %






 
  
 

 
 

 (
 

  


 

 
 

 



5
 



  
  
 
 

 

 ( 

 

 

  
  
 
 
interface Event {
Event newEvent (EventType type, AccountNumber account,
Date whenOccurred, Date whenNoticed);
EventType getType();
AccountNumber getAccount();
Date getWhenOccurred();
Date getWhenNoticed();


#
 
   


'
 

  

   

 
 







&




 
 
 

: 


%  

 



  
 


interface Sale extends Event {


Sale newSale (AccountNumber account,
Date whenOccurred, Date whenNoticed,
Vendor vendor, Money amount);
Vendor getVendor();
Money getAmount();

 
4  
   





   


(   


 
    

 
-




 
*

   
 


 


interface Event...
boolean isProcessed();
Set getResultingEntries();
void addResultingEntry(Entry arg);
...
  
 
 

 


 
& 

 
 
 


 
 

 
)   
    
      
 
   
  
 
  
       



 
#
   6 
 



 
 
  09'  
  ) 



 

 



(



 



 





< 


 




 
 





Event
{frozen} Event Process Log
1
type
isProcessed
account
resultingEntries
whenOccurred
whenNoticed

Implementation
Perspective
Sale
{frozen}

vendor
amount


 
       
 
) 


 


 

 




(  




 




    
 





)

  










 
 ( 
 
 
 
  
 
  
  
 
 
) 


  
  
   
 



 


   
$ 



 )   


 

 




7





  






 
"   " 


Accounting Entry

when booked : DateTime descriptor


amount: Money ✻ ✻

 % $ $ 011 "  -



 
)+ )  $ ' 




 $ 
  011* $   )* 
 $    
-

+

  
 
 011 
    " $- 
  
2
+ )  $ ' 



 $   * 
  011 

     "  $- 
 * 
     "   2
 +

 ) ' " 3        4 
 #+ ) 
$ ' 



 $ 
    '  4
  
 $
  $ 3   
  4 
 #+

# 
       
 

   
 
6


  

  
 
 
  

  

  &  
          
 ( 

 



 
 
 





( 
 
 
    
 


  
 
 

 



  
  


 




  




&
 

 

  

 

 



    
  

 


  
  



 
  



    
  
  



 


 



  



  &


 



( 


  

 


 % 
    
        


  
/& 

  
C. 
 
C1
*

   




 
 









     
 





 

 
&   
 



  
 
   
   

 (  
  

 

 


  


 
   080

Accounting Entry

descriptors
accounting entry

✻ 1
Cost Type
Entry


Project
1

    


  

  



 

)   
  
 % 



   ( 
           
   

  
    



  

% 
 
 
(

 



 

 
3  
 

 

 % 



  
 


      


: 
       


 &    

 

  
'

 
 


 


  





  
2


  &
    
 
  
  





 




   
 

interface Entry {
Entry newEntry (CostType costType, Project project, Money amount, Date date);
CostType getCostType();
Project getProject();
Money getAmount();
Date getBookingDate();

( 
   ' 

 
  





5
 
 




 


(  




 6
void setCostType (CostType arg) {
if (isOpen())
costType = arg
else
throw new ImmutableEntryException();
}

   
    
  


     

 




  
 
  

 


A
 
B     
  
 
   
 

 

source
Event Accounting Entry
1 ✻




   

       




!
 $ 


   -

  



1
host


Posting Rule ´ createsª
Event Type Accounting Entry
1 ✻ process(Event)

 5
$    
* $ '    '  
 
 "
    '   "
 "        
+ )  $ '
   
 $ 
  $ '  
* $  $ ' 
 * 
 $  
  $  $ '  
  
 ' +

 
*



 

 


   

7 #  7 



      

 
       







(  

 
 
   
     


 
  
 ' 
 
 
7
'
 
 
   




 
   
     ""
 
  ""
   
+
 
    ""
 * '   ""
  
  '   "  +
%
       
 $ '   ""
 * 
 

 ""
  

  
   +


#
 

  
(
 
   ""      6 

   
(   




  





 '   
 4
 






  





  
   


 
 
  
  
     

  #
  
   





 

   











  



 


 

 
 


 

  

   
 



 

   (% 
 

   4(



 


 

 

 

 
   '     
 


 (

 
   

    
 

 
   


 

% 
  
 
 &
 
 

 
  



 


Posting Rule
posting rule
event type accounting entry
host

event type
✻ 1
Event Type Service Agreement Posting Rule
date

1 1

´ createsª
✻ ✻
✻ 1
Accounting Event Customer Entry
1 ✻


 

  

  '
   
 
 
 .   
  



  


      
. 

 



 
. 







class AccountingEvent {
private EventType _type;
private MfDate _whenOccurred;
private MfDate _whenNoticed;
private Customer _customer;
private Set resultingEntries = new HashSet();

AccountingEvent (EventType type, MfDate whenOccurred,


MfDate whenNoticed, Customer customer)
{
this.type = type;
this.whenOccurred = whenOccurred;
this.whenNoticed = whenNoticed;
this.customer = customer;
}

Customer getCustomer() {
return customer;
}
EventType getEventType(){
return type;
}
MfDate getWhenNoticed() {
return whenNoticed;
}
MfDate getWhenOccurred() {
return whenOccurred;
}
void addResultingEntry (Entry arg) {
resultingEntries.add(arg);
}
PostingRule findRule() { /*discussed later*/}
void process() {/*discussed later*/}
}

class EventType extends NamedObject{


public static EventType USAGE = new EventType("usage");
public static EventType SERVICE_CALL = new EventType("service call");

public EventType (String name) {


super(name);
}
}

&    


   

 
 
    

 


  

-'
  
 

 
5
(


class Entry {
private MfDate date;
private EntryType type;
private Money amount;
public Entry (Money amount, MfDate date, EntryType type) {
this.amount = amount;
this.date = date;
this.type = type;
}
public Money getAmount() {
return amount;
}
public MfDate getDate() {
return date;
}
public EntryType getType() {
return type;
}
}
class EntryType extends NamedObject {
static EntryType BASE_USAGE = new EntryType("Base Usage");
static EntryType SERVICE = new EntryType("Service Fee");
public EntryType(String name) {
super(name);
}
}

< 
 

 
class Customer extends NamedObject {
private ServiceAgreement serviceAgreement;
private List entries = new ArrayList();
Customer (String name) {
super(name);
}
public void addEntry (Entry arg) {
entries.add(arg);
}
public List getEntries() {
return Collections.unmodifiableList(entries);
}
public ServiceAgreement getServiceAgreement() {
return serviceAgreement;
}
public void setServiceAgreement(ServiceAgreement arg) {
serviceAgreement = arg;
}
}
( 





 





 
( 

    
 


 
 

 


class ServiceAgreement {
private double rate;
private Map postingRules = new HashMap();
void addPostingRule (EventType eventType, PostingRule rule, MfDate date) {
if (postingRules.get(eventType) == null)
postingRules.put(eventType, new TemporalCollection());
temporalCollection(eventType).put(date, rule);
}
PostingRule getPostingRule(EventType eventType, MfDate when) {
return (PostingRule) temporalCollection(eventType).get(when);
}
private TemporalCollection temporalCollection(EventType eventType) {
TemporalCollection result = (TemporalCollection) postingRules.get(eventType);
Assert.notNull(result);
return result;
}
public double getRate() {
return rate;
}
public void setRate(double newRate) {
rate = newRate;
}
}
(
  

 





 
  

 )   6&
 







 

  ' 


 





 
( 
 



 
abstract class PostingRule {
protected EntryType type;
protected PostingRule (EntryType type) {
this.type = type;
}
private void makeEntry(AccountingEvent evt, Money amount) {
Entry newEntry = new Entry (amount, evt.getWhenNoticed(), type);
evt.getCustomer().addEntry(newEntry);
evt.addResultingEntry(newEntry);
}
public void process (AccountingEvent evt) {
makeEntry(evt, calculateAmount(evt));
}
abstract protected Money calculateAmount(AccountingEvent evt);
}

   


(


(
 
  

 





 


 6

 


 
 
 
&  



 '. 



  

( 
 

  


  

 



#
   

   
public class Usage extends AccountingEvent
{
private Quantity amount;
public Usage(Quantity amount, MfDate whenOccurred, MfDate whenNoticed, Customer customer) {
super(EventType.USAGE, whenOccurred, whenNoticed, customer);
this.amount = amount;
}
public mf.Quantity getAmount() {
return amount;
}
double getRate() {
return getCustomer().getServiceAgreement().getRate();
}
}
7     # 
 5
  %
     


.
 
  


-



 

 

 

 


 
 











 3'



  
  


 


 
 
 

 


(   
 ( 
  





 



 
 
&
  
 

 
 

class MultiplyByRatePR extends PostingRule{
public MultiplyByRatePR (EntryType type) {
super(type);
}
protected Money calculateAmount(AccountingEvent evt) {
Usage usageEvent = (Usage) evt;
return Money.dollars(usageEvent.getAmount().getAmount() * usageEvent.getRate());
}
}
&



 /  0821 



C( 


 


/ 
08D1    
 
 
 
 


 


PostingRule
AccountingEvent
process(AccountingEvent)
calculateAmount(AccountingEvent)

UsageEvent MultiplyByRatePR

amount : Quantity
calculateAmount(AccountingEvent)
{type = USAGE}



     

 

class AccountingEvent {
public void process() {
findRule().process(this);
}
PostingRule findRule() {
PostingRule rule =
customer.getServiceAgreement().getPostingRule(this.getEventType(),
this.whenOccurred);
Assert.notNull("missing posting rule", rule);
return rule;
}...


multiply by rate
usage event service agreement
posting rule

process
find rule

get posting rule (usage event type, occurred date)

process (usage event)

get amount of usage

get rate
new
usage entry


      

. 
  
 

 






 


/  
  




 
  

1
(   

 

  

 





 
 
public void setUpRegular (){
acm = new Customer("Acme Coffee Makers");
ServiceAgreement standard = new ServiceAgreement();
standard.setRate(10);
standard.addPostingRule(
EventType.USAGE,
new MultiplyByRatePR(EntryType.BASE_USAGE),
new MfDate(1999, 10, 1));
acm.setServiceAgreement(standard);
}
...
.






public void testUsage() {


Usage evt = new Usage(
Unit.KWH.amount(50),
new MfDate(1999, 10, 1),
new MfDate(1999, 10, 1),
acm);
evt.process();
Entry resultingEntry = getEntry(acm, 0);
assertEquals (Money.dollars(500), resultingEntry.getAmount());
}
(   
 





  
 

    


  


   
&
 
 . 

  

     
   3
       
 



 
 "


 




 
 
 
(
 

 




 
 
 





class MonetaryEvent extends AccountingEvent {
Money amount;
MonetaryEvent(Money amount, EventType type, mf.MfDate whenOccurred,
mf.MfDate whenNoticed, Customer customer) {
super(type, whenOccurred, whenNoticed, customer);
this.amount = amount;
}
public mf.Money getAmount() {
return amount;
}
}
-


   



 
 

(   

  
 




 


 
. 

 


 
public void testService() {
AccountingEvent evt = new MonetaryEvent(
Money.dollars(40),
EventType.SERVICE_CALL,
new MfDate(1999, 10, 5),
new MfDate(1999, 10, 5),
acm);
evt.process();
Entry resultingEntry = (Entry) acm.getEntries().get(0);
assertEquals (Money.dollars(30), resultingEntry.getAmount());
&  

   

   






class AmountFormulaPR extends PostingRule {


private double multiplier;
private Money fixedFee;
AmountFormulaPR (double multiplier, Money fixedFee, EntryType type) {
super (type);
this.multiplier = multiplier;
this.fixedFee = fixedFee;
}
protected Money calculateAmount(AccountingEvent evt) {
Money eventAmount = ((MonetaryEvent) evt).getAmount();
return (Money) eventAmount.multiply(multiplier).add(fixedFee);
}
}
.
  

 
 
 
public void setUpRegular (){
acm = new Customer("Acme Coffee Makers");
ServiceAgreement standard = new ServiceAgreement();
standard.setRate(10);
standard.addPostingRule(
EventType.USAGE,
new MultiplyByRatePR(EntryType.BASE_USAGE));
standard.addPostingRule(
EventType.SERVICE_CALL,
new AmountFormulaPR(0.5, Money.dollars (10), EntryType.SERVICE));
acm.setServiceAgreement(standard);
}

      

 
    




 
   .      
 
       



public void setUpRegular (){


acm = new Customer("Acme Coffee Makers");
ServiceAgreement standard = new ServiceAgreement();
standard.setRate(10);
standard.addPostingRule(
EventType.USAGE,
new MultiplyByRatePR(EntryType.BASE_USAGE),
new MfDate(1999, 10, 1));
standard.addPostingRule(
EventType.SERVICE_CALL,
new AmountFormulaPR(0.5, Money.dollars (10), EntryType.SERVICE),
new MfDate(1999, 10, 1));
standard.addPostingRule(
EventType.SERVICE_CALL,
new AmountFormulaPR(0.5, Money.dollars (15), EntryType.SERVICE),
new MfDate(1999, 12, 1));
acm.setServiceAgreement(standard);
}

event type = USAGE event type = SERVICE CALL


effectivity = later than Oct 1 1999
standard : Service Agreement effectivity = starts Dec 1 1999

event type = SERVICE CALL


effectivity = starts Oct 1 1999, ends Dec 1 1999

a MultiplyByRatePR an AmountFormulaPR an AmountFormulaPR

entry type = BASE USAGE entry type = SERVICE entry type = SERVICE
multiplier = 0.5 multiplier = 0.5
fixed fee = $10 fixed fee = $15


        
 


 



 
 


public void testLaterService() {


AccountingEvent evt = new MonetaryEvent(
Money.dollars(40),
EventType.SERVICE_CALL,
new MfDate(1999, 12, 5),
new MfDate(1999, 12, 15),
acm);
evt.process();
Entry resultingEntry = (Entry) acm.getEntries().get(0);
assertEquals (Money.dollars(35), resultingEntry.getAmount());
}


  
E 

 

 
' 

  
  
 "

   

  
  
     
&   


  
+0


  
 

 
 



  
  
 

 

( 
    
 
  
 
   

 


 

class PoorCapPR extends PostingRule {
double rate;
Quantity usageLimit;
PoorCapPR (EntryType type, double rate, Quantity usageLimit) {
super(type);
this.rate = rate;
this.usageLimit = usageLimit;
}
protected Money calculateAmount(AccountingEvent evt) {
Usage usageEvent = (Usage) evt;
Quantity amountUsed = usageEvent.getAmount();
Money amount;
return (amountUsed.isGreaterThan(usageLimit)) ?
Money.dollars(amountUsed.getAmount() * usageEvent.getRate()):
Money.dollars(amountUsed.getAmount() * this.rate);
}
}
.
  
 


  


private void setUpLowPay (){


reggie = new Customer("Reginald Perrin");
ServiceAgreement poor = new ServiceAgreement();
poor.setRate(10);
poor.addPostingRule(
EventType.USAGE,
new PoorCapPR(EntryType.BASE_USAGE, 5, new Quantity(50, Unit.KWH)));
poor.addPostingRule(
EventType.SERVICE_CALL,
new AmountFormulaPR(0, Money.dollars (10), EntryType.SERVICE));
reggie.setServiceAgreement(poor);
}
$       

public void testLowPayUsage() {


Usage evt = new Usage(
Unit.KWH.amount(50),
new MfDate(1999, 10, 1),
new MfDate(1999, 10, 1),
reggie);
evt.process();
Usage evt2 = new Usage(
Unit.KWH.amount(51),
new MfDate(1999, 11, 1),
new MfDate(1999, 11, 1),
reggie);
evt2.process();
Entry resultingEntry1 = (Entry) reggie.getEntries().get(0);
assertEquals (Money.dollars(250), resultingEntry1.getAmount());
Entry resultingEntry2 = (Entry) reggie.getEntries().get(1);
assertEquals (Money.dollars(510), resultingEntry2.getAmount());
}

&  
 
  
  
  

 
   



  
     
   
   

     
         
 
  
' 

 
:
  

 
 

  ( 
 

 
 
  
   
    
 
   

)  


 
   
 
 
 
 / 
   
1 





 / 
  

1
@ 






 

  




 



     
         
 
) 



 
 
#
' 
'




++F
'

 ) 


  

   
 




'#


 



 

 


 






(   
 * 
 


  

  
(
 






 
(  







(
A
'
 B 
'
  
 

   

 
    
 



'

 




'

 

 

  

 



)     
           
  
 
 


  


 



 
 
'

   

 

++F
'
 
 ' 

 

 

# 
 $


 


class Tester...
public void setUpRegular (){
acm = new Customer("Acme Coffee Makers");
ServiceAgreement standard = new ServiceAgreement();
...
standard.addPostingRule(
EventType.TAX,
new AmountFormulaPR(0.055, Money.dollars(0), EntryType.TAX),
new MfDate(1999, 10, 1));
acm.setServiceAgreement(standard);
}
* 

 





'





 

 
  
 

 

  
class PostingRule...
public void process (AccountingEvent evt) {
makeEntry(evt, calculateAmount(evt));
if (isTaxable()) new TaxEvent(evt, calculateAmount(evt)).process();
}
-


 


'

'

  


  # 

  


class PostingRule...
private boolean isTaxable() {
return !(type == EntryType.TAX);
}

multiply by rate
usage event service agreement
posting rule

process
find rule

get posting rule (usage event type, occurred date)

process (usage event)

get amount of usage

get rate
new
usage entry

new
tax event

process


 

 
 

(' 

    



G



  


 
-



'
(
'
  
class TaxEvent extends MonetaryEvent {
private AccountingEvent base;
public TaxEvent(AccountingEvent base, Money taxableAmount) {
super (taxableAmount, EventType.TAX, base.getWhenOccurred(),
base.getWhenNoticed(), base.getCustomer());
this.base = base;
Assert.isFalse("Probable endless recursion", base.getEventType() == getEventType());
}
}


 /  1

 
  


 

 
   



     




 
   





  

   
  

   
   
      ! 

   
    
   
" #   

 

  
 



 
#
 
  
   
 



6
    

 








(
 

 



 
 

class TaxEvent...
public TaxEvent(AccountingEvent base, Money taxableAmount) {
super (taxableAmount, EventType.TAX, base.getWhenOccurred(),
base.getWhenNoticed(), base.getCustomer());
this.base = base;
base.friendAddSecondaryEvent(this);
Assert.isFalse("Probable endless recursion", base.getEventType() == getEventType());
...
class AccountingEvent ...
private List secondaryEvents = new ArrayList();
void friendAddSecondaryEvent (AccountingEvent arg) {
// only to be called by the secondary event's setting method
secondaryEvents.add(arg);
}
.
 


 
  
class AccountingEvent...
Set getAllResultingEntries() {
Set result = new HashSet();
result.addAll(resultingEntries);
Iterator it = secondaryEvents.iterator();
while (it.hasNext()) {
AccountingEvent each = (AccountingEvent) it.next();
result.addAll(each.getResultingEntries());
}
return result;
}
3 






class Tester
public void testUsage() {
Usage evt = new Usage(
Unit.KWH.amount(50),
new MfDate(1999, 10, 1),
new MfDate(1999, 10, 1),
acm);
evt.process();
Entry usageEntry = getEntry(acm, 0);
Entry taxEntry = getEntry(acm, 1);
assertEquals (Money.dollars(500), usageEntry.getAmount());
assertEquals (EntryType.BASE_USAGE, usageEntry.getType());
assertEquals (Money.dollars(27.5), taxEntry.getAmount());
assertEquals (EntryType.TAX, taxEntry.getType());
assert(evt.getResultingEntries().contains(usageEntry));
assert(evt.getAllResultingEntries().contains(taxEntry));
}





$     

  
  ##
% &
 

Account

balance
Entry
balance (DateRange)
withdrawels(DateRange) 1 ✻
deposits(DateRange)

# 
       
 .

   
 
 

 


 
H
  

   



(  

 

 
 # 

 

   
   
  /  '  1 .   
 

 

 
 
( 
 

 

    


 
) 
  

 
 
   
 
 
 




 
   




 
 
 

 


 





 
#
 
  
 
 
 







 
 

 
 
 
  







 
@ 
    




 

  
 


1
Customer


✻ 1
Entry Location


1
Entry Type

1
Customer


✻ 1 ✻ 1
Entry Account Location


1
Entry Type


    
        
.
 
 

  
 

 

3 
 


 




  

 


 
.

  

 
 < 
 
  $ E
  






 
  
  


 
  
 
 






( 
 
 % 


  
 

6    


 

     4  


 
&    
 

  


 4

  
(
 4

 %  
  

    
  
  
    
 
  
 
    
  
        
 
 
  



 
5
 
    
 

   
  
 3 

 
        
  

     
   
  
 
    
    
  
 

  (     
 
   
 

  
 
 
 


 



 

 
3
 

 '

 
 
)   '




   
 
 
&    



    
  


 


 
  
 
  




   


 
  



 




   

  
  
   
 
()
 !
  

(
    4       
 

  
 



 






 
      



( 
 
   
  
  

  
  
 


    
 

  
   
 
    *# +

    !I
  
 

    


 *# 
    !
(     '  


 




 
 
( 
 

 
 
 
*
    

   
   +
'   
  &  
 

        !


 ,   " #        
        
#
 
  
   '
 
   
 
  

 
 



    




 
   

 
    


 



 
   
  


3

 



   
% 




.   
  





'
 H



 








(   
 

 
 





 /  '  1    
<


   
class Account ...
private Collection entries = new HashSet();
private Currency currency;
void addEntry(Money amount, MfDate date){
Assert.equals(currency, amount.currency());
entries.add(new Entry(amount, date));
}

(  


 


  


class Account...
Money balance(DateRange period) {
Money result = new Money (0, currency);
Iterator it = entries.iterator();
while (it.hasNext()) {
Entry each = (Entry) it.next();
if (period.includes(each.date())) result = result.add(each.amount());
}
return result;
}
Money balance(MfDate date) {
return balance(DateRange.upTo(date));
}
Money balance() {
return balance(MfDate.today());
}
*

  
   
  

 

  

 




Money deposits(DateRange period) {


Money result = new Money (0, currency);
Iterator it = entries.iterator();
while (it.hasNext()) {
Entry each = (Entry) it.next();
if (period.includes(each.date()) && each.amount().isPositive())
result = result.add(each.amount());
}
return result;
}
Money withdrawels(DateRange period) {
Money result = new Money (0, currency);
Iterator it = entries.iterator();
while (it.hasNext()) {
Entry each = (Entry) it.next();
if (period.includes(each.date()) && each.amount().isNegative())
result = result.add(each.amount());
}
return result;
}



 

-   #      


  

  


  % 

Entry 2 1 Accounting
Account
Transaction
1 ✻ amount: Money

{sum of amounts of
entries equals 0}


 


!  
  
3
 
  
     
6   
   (
     
    %
    
  
  


( 
  



 


 





  
    
 

 



 



. 




 

   
#





  
 (  

 
 


# 



  
 

 

  


 
  

 
4
  


an Entry
cash: Account
amount = $100

an Accounting
Transaction

an Entry
checking: Account
amount = -$100


 

   

(


 


 



  

 
 

 
   


 
  
 




 



.





 
I 






(  


  
 

 
  
.   
 







 
  
    

 
 &   

 / 
1
 /
1 

 
#&



  
  



  

  

  





1 from ✻
Accounting Transaction
Account
amount: money
1 to ✻


 

   
  
  


Entry 2..✻ 1 Accounting


Account
Transaction
1 ✻ amount: Money

{sum of amounts of
entries equals 0}

   
    

   
   
   
 
 

   
 
.
 




   
  





#



 
%
 3
   



  
  
 &
 
     
.&"  !
    

    

 


  

 


an Entry
royalties: Account
amount = - $50

an Entry
an Accounting
salary: Account
Transaction
amount = - $100

an Entry
checking: Account
amount = $150


 
    
    
 

  
! 
   

  


 

(
 


  
 
 
   
 
  

  

 


 .

 
 





  
  -  

 
  
 






 
   
 

 


 
  



 



  

(  
          *

  //  
  
 



    

  *

 // 


   


    
 
  &        
      
 
   
 *

 //

#


   *

 // 

 
 
 
 (   
 
 
    
  
    &     ' 
    
 
 


  
 I    *

 //  

  
&     '


 




   
 
 '

 
  '



" 

  *



 //'



'

 

 

  
   *

 //  

 




   
   7 


    


 '  

  
 
      
      

    3   
 
 


  
 
 


7 




  
 &    


     
 
 
 




 


 





 %






&







 

( %

 










   
 



  

   




 





 



 
  


 

public class AccountingTransaction {
private Collection entries = new HashSet();
public AccountingTransaction(Money amount, Account from, Account to, MfDate date) {
Entry fromEntry = new Entry (amount.negate(), date);
from.addEntry(fromEntry);
entries.add(fromEntry);
Entry toEntry = new Entry (amount, date);
to.addEntry(toEntry);
entries.add(toEntry);
}
.

   



 



 



 


 

 


E
  
 


 
 

$

    


 
 
  

  

 


 
 

void withdraw(Money amount, Account target, MfDate date) {
new AccountingTransaction (amount, this, target, date);
}
( 
  

 


public void testBalanceUsingTransactions() {
revenue = new Account(Currency.USD);
deferred = new Account(Currency.USD);
receivables = new Account(Currency.USD);
revenue.withdraw(Money.dollars(500), receivables, new MfDate(1,4,99));
revenue.withdraw(Money.dollars(200), deferred, new MfDate(1,4,99));
assertEquals(Money.dollars(500), receivables.balance());
assertEquals(Money.dollars(200), deferred.balance());
assertEquals(Money.dollars(-700), revenue.balance());
}


 

( 
 
  


 



 

       .&"  !








 




 


 


.

 


 


 

 


*










 





 
4

 


 






 




 
 

public class AccountingTransaction {
private MfDate date;
private Collection entries = new HashSet();
private boolean wasPosted = false;
public AccountingTransaction(MfDate date) {
this.date = date;
}
&

 '



(  

 



 
 
' 
(

 



  






class Transaction...
public void add (Money amount, Account account) {
if (wasPosted) throw new ImmutableTransactionException
("cannot add entry to a transaction that's already posted");
entries.add(new Entry (amount, date, account, this));
}

     


  
 









 
/5
  

 
  

 
  

 1
class Entry...
private Money amount;
private MfDate date;
private Account account;
private AccountingTransaction transaction;
Entry(Money amount, MfDate date, Account account, AccountingTransaction transaction) {
// only used by AccountingTransaction
this.amount = amount;
this.date = date;
this.account = account;
this.transaction = transaction;
}
* 
 











class AccountingTransaction...
public void post() {
if (!canPost())
throw new UnableToPostException();
Iterator it = entries.iterator();
while (it.hasNext()) {
Entry each = (Entry) it.next();
each.post();
}
wasPosted = true;
}
public boolean canPost(){
return balance().isZero();
}
private Money balance() {
if (entries.isEmpty()) return Money.dollars(0);
Iterator it = entries.iterator();
Entry firstEntry = (Entry) it.next();
Money result = firstEntry.amount();
while (it.hasNext()) {
Entry each = (Entry) it.next();
result = result.add(each.amount());
}
return result;
}
class Entry...
void post() {
// only used by AccountingTransaction
account.addEntry(this);
}

 



 
 
AccountingTransaction multi = new AccountingTransaction(new MfDate(2000,1,4));
multi.add(Money.dollars(-700), revenue);
multi.add(Money.dollars(500), receivables);
multi.add(Money.dollars(200), deferred);
multi.post();
assertEquals(Money.dollars(500), receivables.balance());
assertEquals(Money.dollars(200), deferred.balance());
assertEquals(Money.dollars(-700), revenue.balance());

#
 
 
   



  



( 

  





  


 

 





class Account...
void withdraw(Money amount, Account target, MfDate date) {
AccountingTransaction trans = new AccountingTransaction(date);
trans.add(amount.negate(), this);
trans.add(amount, target);
trans.post();
}



 

      

 

  


 


  &"    
 &"   

   


  
   
 
 

0

 
1
#         
 

  
  

&" &  2 
 
0



 

" 3   &      


 

    
# 
 0

original Usage Event resulting entries original Usage Entry

amount = 50 kwh amount = $500

adjusted event

reversing Usage Entry

amount = ($500)

replacement event

new Usage Event replacing Usage Entry

amount = 60 kwh amount = $600


resulting entries

 


  

 


 

 



$
 

 








 
 


 *
 
   
    
  
    
 
 
 


 ( 

  

 

   



 


 
 
& 
       +0    
 
   7 ( 

   +
# 
80
# ( 
 
 
   0,,


a Usage Event a Usage Entry

amount = 50 kwh amount = $500


when occurred = 1 Oct 99 date = 5 Oct 99
when noticed = 5 Oct 99




 

(8
E  4

 

 
 
=0(  
 

 
  0,2
)  
    


  
  

 


(   



 

 





 
 


 
 &

 




  
.


 






 
 
 
 

original Usage Event original Usage Entry


resulting entries
amount = 50 kwh amount = $500
when occurred = 1 Oct 99 date = 5 Oct 99
when noticed = 5 Oct 99
has been adjusted = true

adjusted event reversing Usage Entry

amount = ($500)
replacement event date = 15 Oct 99

new Usage Event


replacing Usage Entry
amount = 60 kwh
when occurred = 1 Oct 99 amount = $600
when noticed = 15 Oct 99 date = 15 Oct 99
resulting entries
has been adjusted = false


   


@   
" #   
 

  
 &

  

   

   
  
 
  
 

 


 

 ' & 
 % 



  
 
  
 &   
  
   
     

 
%  

 

$

 


  

 

   
# " # 4(   
 


 
 


 6  

  
:
 
  


   . 
  




 
 
,  " #   
  

@ 
 


         



 
 
 
 
  





   
# " # 4*
  
 

 

 
 



(   
 

  
# " # 4 
" #  



(  
 
('
  

   

  
  . 



 










 ' 
 &  

  
      +0 

8
 


 >0
8+


class Tester...
public void setUp(){
setUpRegular();
setUpLowPay();
usageEvent = new Usage(
Unit.KWH.amount(50),
new MfDate(1999, 10, 1),
new MfDate(1999, 10, 1),
acm);
eventList.add(usageEvent);
eventList.process();
}

public void testAdjustment() {


Usage adjustment1 = new Usage (
Unit.KWH.amount(70),
new MfDate(1999, 10, 1),
new MfDate(1999, 10, 15),
usageEvent);
eventList.add(adjustment1);
eventList.process();
assertEquals(Money.dollars(700), acm.balanceFor(EntryType.BASE_USAGE));
assertEquals(Money.dollars(38.5), acm.balanceFor(EntryType.TAX));

  


  

 
  


   

 
I
 

 

 

 




 


class AccountingEvent...
private AccountingEvent adjustedEvent, replacementEvent;
AccountingEvent (EventType type, MfDate whenOccurred,
MfDate whenNoticed, AccountingEvent adjustedEvent) {
if (adjustedEvent.hasBeenAdjusted())
throw new IllegalArgumentException (The " + adjustedEvent + " is already adjusted");
this.type = type;
this.whenOccurred = whenOccurred;
this.whenNoticed = whenNoticed;
this.adjustedEvent = adjustedEvent;
adjustedEvent.replacementEvent = this;
}
protected boolean hasBeenAdjusted() {
return (replacementEvent != null);
}
( 
 

 
 

 





 


 


 

(



  

 
   
 




class AccountingEvent...
public void process() {
Assert.isFalse ("Cannot process an event twice", isProcessed);
if (adjustedEvent != null) adjustedEvent.reverse();
findRule().process(this);
isProcessed = true;
}
void reverse() {
Collection entries = new HashSet(getResultingEntries());
Iterator it = entries.iterator();
while (it.hasNext()) {
Entry each = (Entry) it.next();
Entry reversingEntry = new Entry(
each.getAmount().reverse(),
whenNoticed,
each.getType());
getCustomer().addEntry(reversingEntry);
this.addResultingEntry(reversingEntry);
}
reverseSecondaryEvents();
}
private void reverseSecondaryEvents(){
Iterator it = getSecondaryEvents().iterator();
while (it.hasNext()) {
AccountingEvent each = (AccountingEvent) it.next();
each.reverse();
}
}


secondary event of
replacement event adjusted event an existing Entry
adjusted event

process
[adjusted event != null]
reverse

* get information

* create
reversing entry

* reverse

find rule

continues with usual process


   
  







" 
           & 

  



&  0

original Usage Event original Usage Entry

amount = 50 kwh resulting amount = $500


entries
adjusted
event

replacement
event

new Usage Event adjusting Usage Entry

amount = 60 kwh amount = $100


resulting
entries

   
 

 
         
   
  

   
" #       
 
  

  
   
 

   
 
6 





.
  
# " # 4   
  

 
 
  



 
 
   

    
  


 
  



:Entry :Entry :Entry

amount = $500 amount = $800 amount = $750

:Usage Event :Usage Event :Usage Event

amount = 50kwh amount = 80kwh amount = 75kwh

old events

:Entry
:Adjustment
amount = ($550)

new events

:Usage Event :Usage Event :Usage Event

amount = 50kwh amount = 50kwh amount = 50kwh


  
 

 
 ' 
 
 

 
0,+ 
-
 

 

 

  




 )  
  

  



 
 
 







(  
    

    
 
  

  


   

 

 
   

 



  

(

  
 
  

 

  
" #   :





 

 
( 


 


 

 

(


 
  
 
 
. 
 


  

  

 

 

:Entry :Entry :Entry

amount = $500 amount = $800 amount = $750

Usage Account

: Customer


  
 
   
  

( 

 


 
5

 
 

  



:Entry :Entry :Entry

amount = $500 amount = $800 amount = $750

Usage Account

: Customer

shadow account

:Entry :Entry :Entry

amount = $500 amount = $800 amount = $750


 
 


-

  

 



:Entry :Entry :Entry

amount = $500 amount = $800 amount = $750

Usage Account

balance = $2050

: Customer

shadow account

balance = $1500

:Entry :Entry :Entry

amount = $500 amount = $800 amount = $750

:Entry :Entry :Entry

amount = $500 amount = ($800) amount = ($750)

:Entry :Entry :Entry

amount = $500 amount = $500 amount = $500


  
       

(

 




 


:Entry :Entry :Entry :Entry

amount = $500 amount = $800 amount = $750 amount = ($550)

Usage Account

balance = $1500

: Customer


      
  
 
 

  

.  4





J 

 


J 

 

 


J 

 

 


J 


     

   

    
 






 
  


 
    

 

 
 
    
 
 





 


 

/  0201(


 




  
 






 

  




old events old events


Accounting Event
✻ ✻

Adjustment
0..1 0..1

  ! "  

 




 

      (   



  
 
 


   
 
 

 


(

   



 

   
(   
  




    
( 
 

   

 




 
 

5 
   
  
 " #     ,   " #
   
        
   '
 


 


 

 



' 
  
 
" #   
  ,  " #  



  
" #  
,  " #   

    
 (  
      
  
 



 
   



     

 
     

 
  
 
  

      /)    
   

" #   1
# 


  
 

 




public class Adjustment extends AccountingEvent ...


private List newEvents = new ArrayList();
private List oldEvents = new ArrayList();

public Adjustment(MfDate whenOccurred, MfDate whenNoticed, Subject subject) {


super(null, whenOccurred, whenNoticed, subject);
}
public void addNew(AccountingEvent arg) {
newEvents.add(arg);
}
public void addOld(AccountingEvent arg) {
if (arg.hasBeenAdjusted())
throw new IllegalArgumentException
("Cannot create " + this + ". " + arg + " is already adjusted");
oldEvents.add(arg);
arg.setReplacementEvent(this);
}
) 

 
 


 
 
class Tester...
// original events
usageEvent = new Usage(
Unit.KWH.amount(50),
new MfDate(1999, 10, 1),
new MfDate(1999, 10, 15),
acm);
eventList.add(usageEvent);
Usage usage2 = new Usage (// snip constructor args
eventList.add(usage2);
Usage usage3 = new Usage (// snip constructor args
eventList.add(usage3);
eventList.process();

// replacement events
MfDate adjDate = new MfDate(2000,1,12);
Usage new1 = new Usage (// snip constructor args
Usage new2 = new Usage (// snip constructor args
Usage new3 = new Usage (// snip constructor args
Adjustment adj = new Adjustment(adjDate, adjDate, acm);
adj.addOld(usageEvent);
adj.addOld(usage2);
adj.addOld(usage3);
adj.addNew(new1);
adj.addNew(new2);
adj.addNew(new3);
eventList.add(adj);
eventList.process();

( 

   




class Adjustment...
private java.util.Map savedAccounts;
public void process() {
Assert.isFalse ("Cannot process an event twice", isProcessed);
adjust();
markProcessed();
}
void adjust() {
snapshotAccounts();
reverseOldEvents();
processReplacements();
commit();
secondaryEvents = new ArrayList();
secondaryEvents.addAll(oldEvents);
}
public void snapshotAccounts() {
savedAccounts = getCustomer().getAccounts();
getCustomer().setAccounts(copyAccounts(savedAccounts));
}
void reverseOldEvents() {
Iterator it = oldEvents.iterator();
while (it.hasNext()) {
AccountingEvent each = (AccountingEvent) it.next();
each.reverse();
}
}
void processReplacements() {
AccountingEvent[] list = (AccountingEvent[])newEvents.toArray(new AccountingEvent[0]);
for (int i = 0; i < list.length; i++){
list[i].process();}
}
public void commit() {
AccountType[] types = AccountType.types();
for (int i = 0; i < types.length; i++) {
adjustAccount(types[i]);
}
restoreAccounts();
}
public void adjustAccount(AccountType type) {
Account correctedAccount = getCustomer().accountFor(type);
Account originalAccount = (Account) getSavedAccounts().get(type);
Money difference = correctedAccount.balance().subtract(originalAccount.balance());
Entry result = new Entry (difference, MfDate.today());
originalAccount.addEntry(result);
resultingEntries.add(result);
}
public void restoreAccounts() {
getCustomer().setAccounts(savedAccounts);
}

  
 

   



   
 


 
 
  




 
(
 

 
 

(
 
 
 
 
  
 
   



     
 *

    
  
   
 


/ 
1  (
 

   




 

  



 

" 
 & #   
  
  # 

original Usage Event resulting entries original Usage Entry entries {destroyed}

amount = 50 kwh amount = $500

adjusted event

:customer

replacement event

new Usage Event replacing Usage Entry entries

amount = 60 kwh amount = $600


resulting entries

$
  

  
 
 
   
  
 

  



 

 




(   %
     

 

 .   
  


  



  

 


 




 
 


   


 
!

   
  
     

       



 

  




 
 
 


  
     
    
    
 

  

 

  
 
 





 

( 
 
  

 


  
    

  


 
   4
'

 

 


 




  


 .
 
" #  , +
 " #     
    

 
 
  
  
  

 (   
 


    
           
   

/  
 1
 

 
(
 
 

  
# " # 4 



 
 
(


   
#
" #  4 
 
  
" #     ,   " #   
@
 

 
    
# " # 4



   
 

 (      
      
 
 
 


% 
#
 
  
# " # 4 
 





 

 # 

/   1

  
     
 )   
  
 

    

  
 
  

   


 




(  
  
(   


 
 









.



 
 
 



class AccountingEvent
private AccountingEvent adjustedEvent, replacementEvent;
public AccountingEvent (EventType type, MfDate whenOccurred,
MfDate whenNoticed, AccountingEvent adjustedEvent)
{
if (adjustedEvent.hasBeenAdjusted())
throw new IllegalArgumentException
("Cannot create " + this + ". " + adjustedEvent + " is already adjusted");
this.type = type;
this.whenOccurred = whenOccurred;
this.whenNoticed = whenNoticed;
this.adjustedEvent = adjustedEvent;
adjustedEvent.replacementEvent = this;
}
protected boolean hasBeenAdjusted() {
return (replacementEvent != null);
}
( 
  
  
  
 
      
 

  



public void process() {


Assert.isFalse ("Cannot process an event twice", isProcessed);
if (adjustedEvent != null) adjustedEvent.undo();
findRule().process(this);
isProcessed = true;
}
public void undo() {
Entry[] entries = getResultingEntries();
for (int i = 0; i < entries.length; i++)
getSubject().removeEntry(entries[i]);
undoSecondaryEvents();
resultingEntries = null;
}
private void undoSecondaryEvents(){
Iterator it = getSecondaryEvents().iterator();
while (it.hasNext()) {
AccountingEvent each = (AccountingEvent) it.next();
each.undo();
}
}

1

Organization Structures

It seems that remarkably early in our lives we become familiar with organizational
structures. The classic management hierarchy appears on an org chart early in our
career, but even by then we’ve already come across the notion in plenty of places. So
in a way it shouldn’t be surprising that organization structures crop up frequently
enough in business software too. I recognized many organizational patterns several
years ago and ever since they keep turning up again.
A good way to start thinking about modeling organization structures is to think of
the obvious way. Imagine a company where people work in departments, which are
organized into divisions. Figure 0.1 shows an explicit model for this where each part of
the structure is a separate class.

Division Department Person


1 ✻ 1 ✻

Figure 0.1 An explicit, and obvious,organizational structure.

Explicit structures have two main disadvantages. They don’t work well if there is
much common behavior between the kinds of organization. They also embed the cur-
rent organizational categories into the design. Should some bright spark decide to add
regions between divisions and departments, you have some modificaitons to do.
2

parent 1 {hierarchy}


Organization

children

Figure 0.2 Organization hierarchy

Faced with these problems, the obvious move is to create a supertype for the orga-
nization, which leads you to Organization Hierarchy (7) in Figure 0.2. The organization
hierarchy works best when you don’t have much different behavior between the orga-
nization sructures. It also allows you to stay very flexible if new kinds of organizations
appear. If you do have some varied behavior you can use subtypes to pull this down.

Party

{hierarchy}

parent 1

Person Organization

children

Figure 0.3 Adding Party to an organization hierarchy

Making a supertype for the organization is a pretty obvious move, another com-
mon, if less obvious, supertype is Party (5): a supertype between the organization and
person, leading to Figure 0.3. Often you find that there isn’t much difference between
the hierarchic association between organizations and the association between person
and organization so you can pull these associations up to the supertype (Figure 0.4).
3

{hierarchy}

parent 1

Party

children

Person Organization

Figure 0.4 A hierarchy on Party

A hierarchy like this is a good choice for many organizations, it certainly captures
the usual org charts pretty well. But as organizations get larger then you tend to see a
number of different kinds of links between your parties. This might be matrix style
organizational structures where people are organized by job function and geographic
location at the same time. Obviously one way to do this is to create a second party
hierarchy, but this only goes so far. You don’t want your party festooned with hierar-
chies.
This situation leads you to Accountability (17), where you make the interparty
releationship an object in its own right, typed according to the kind of link you need
to have (Figure 0.4). Accountabilities represent the most powerful, and also the most
complex way of dealing with organizational strucutres. So like most of these power
tools, you don’t get them out unless you really need them. But when you do account-
abilties give you a very flexible way of handling all sorts of relationships.
When you have accountabilties there are often rules that say what kinds of parties
can be connected together. You can use a Knowledge Level (32) to capture and enforce
these rules.
4

Accountability
Party Type
Type

1 1

✻ ✻
✻ 1 child
Accountability Party

✻ 1 parent

Person Organization

Figure 0.5 Using Accountability for the organization structures


5

Party

An abstraction of people and organizational units

Party

Person Organization

Example: A telephone utility’s customers may be individuals or businesses. Many aspects of


dealing with customers are the same, in which case they are treated as parties. Where they
differ they are treated through their subtype.
Take a look through your address book, what do you see? If its anything like mine you
will see a lot of addresses, telephone numbers, the odd email address… all linked to
something. Often that something is a person, however the odd company shows up. I
call ‘Oak Grove Taxi’ frequently, but there’s no person I want to speak to — I just
want to call a cab.
If I were to model an address book, I might choose to have people and companies,
each of which have postal addresses and telephone numbers, but the resulting dupli-
cation is painful to the eye. So I need a supertype of person and company. This class is
a classic case of an unnamed concept — one that everybody knows and uses but
nobody has a name for. I have seen it on countless data models on various names: per-
son/org, player, legal entity….
The term I prefer is party, and I’ve been glad to see that over the last few years it’s
turned into a fairly standard name.
6

Making it work
I usually define party as the supertype of person and organization. This allows me to
have addresses and phone numbers for departments within companies, or even infor-
mal teams.
Put any behaviror that is common to people and organizational units on Party, only
put things particular to one or the other on the subtype. When you put behavior on
the subtype, think about whether it makes sense on the supertype, often you may be
surprised how well things fit on the supertype

When to use it
The obvious case to use Party (5) is when you have people and organizations in
your model and you see common behavior. However you should also consider this
pattern when you don’t need to distinguish between people and organizations. In this
case it’s useful just to define a party class and not to provide the subtypes.
If you see parties playing different roles in a business, you’ll often see one of the role
patterns in play. Coad in particular is a big fan of Role Object (116). It’s a common pat-
tern with party, but isn’t one to turn to blindly, but take a look at Role Object (116) for
more discussion of that issue.
The main point of this pattern is to look for it to see if you have common behavior,
and if so to use the name Party for that supertype. The name has become quite widely
used these days, so choosing that name helps in communication.
7

Organization Hierarchy

Represents the hierarchy of organizational units within a business

parent 1 {hierarchy}


Organization

children

Associated Coffee
Makers: Organization

purchasing :
sales : Organization
Organization

Boston sales : London sales :


Organization Organization

Making it work
Hierarchies are a common structure in organizations. This is because they reflect a
natural and common technique for human beings to deal with complexity. Modeling a
hierarchy is thus a common thing to do, yet it is both easy and complicated.
8

It’s easy because you can show it with a recursive association, my old data model
teachers called it a “pigs ear”. However the recursive association does not tell the
whole story. In most cases there is one parent, but how about for the one at the top?
Hierarchies also have rules, such as the fact that you can’t have cycles (your grandpar-
ent cannot be your grandchild). There is no standard notation for dealing with this in
the UML. I use a constraint {hierarchy} on the association to suggest what is going
on.
Even the {heirarchy} constraint, however, is strictly imprecise. It doesn’t tell you
the difference between a tree (one top) and a forest (multiple tops). If this is impor-
tant to you model you should say what it is, most of the time I find it isn’t that vital.
In the sketch I use the terms parent and children. Naming these association roles
can be tricky. Parent works well with most companies, but child isn’t as good as sub-
sidiaries. However I’ve come to the view that children is the best name. The use of
parent and child is a very useful metaphor when discussing hierarchies, or indeed any
other kind of directed graph structure. I can use such phrases as “sales in London is a
cousin of purchasing in Java” and, although it sounds wacky, you can easily figure out
what I mean. The metaphor gives us a useful vocabulary which is worth the fact that it
often sounds a little odd.

When to use it
You need to use this pattern when you have a hierarchic corporate structure that
affects the software you are using.
• hierarchic: because the pattern handles a hierarchy not anything more complex.
If your needs are more complicated you can tweak the pattern (there are some
suggestions below) or use Accountability (17) instead.
• affects the software: because you only need to capture the corporate organization
if it really affects what you are doing. It’s important to ask yourself what would
happen if you didn’t capture the hierarchy. If the consequences are not painful
then it’s not worth carrying the cost of the links (and above all the costs of main-
taining the links). Remember that it’s easy to add this pattern in later to an
exisiting list of organizations or parties.
GOF fans will note that this pattern is an application of the GOF composite pat-
tern, although a somewhat degenerate one as the composite and leaf classes aren’t
pulled out. Certainly you should consider using composite when you implement it,
and bear in mind that it’s quite common not to have distinguishing behavior between
composites and leaves in this use.
You don’t need to limit yourself to a single hierarchic association. If an organiza-
tion has different structures for regional vs functional management, you can use a pair
9

of hierarchies as in Figure 0.6 This allows sales in the London office to have sales as
its functional parent and the London office as its regional parent. Of course as you get
more hierarchies this will get messy, and this is the point where you’ll want to use
Accountability (17).

functional
parent 1 {hierarchy}

regional parent ✻
Organization
1 functional
children
✻ regional
children

{hierarchy}

Figure 0.6 Using a pair of hierarchies

Similar logic can lead to abandoning the heirarchy in favor of a more general graph
structure to allow you to have multiple parents. Here I would be more cautious. Ask
yourself whether you really have different kinds of parents that should be distin-
guished. In many cases you’ll find that multiple hierarchies or Accountability (17) will
serve you better. Once you lose the single parent, you lose the ability to easily aggre-
gate up the hierarchy, in particualar you won’t be able to use Aggregating Attribute
(14).

Sample Implementation
The key thing about implementing this pattern is to get the right kind of interface on
the classes. This means providing the right mix of operations to navigate the structure
how you need it to be navigated.
For this sample implementation I’m using the static variable as a Registry (2) for
organizations.
10

class Organization ...


private static Map instances = new HashMap();
private String name;
void register () {
instances.put(name, this);
}
static void clearRegistry() {
instances = new HashMap();
}
static Organization get(String name) {
return (Organization) instances.get(name);
}

At the core, we need operations to get hold of the parent and the children. In this
case I use a field to store the parent, and determine the children by a lookup from the
registry.
class Organization ...
private Organization parent;
Organization (String name, Organization parent) {
this.name = name;
this.parent = parent;
}
Organization getParent() {
return parent;
}
Set getChildren() {
Set result = new HashSet();
Iterator it = instances.values().iterator();
while (it.hasNext()) {
Organization org = (Organization) it.next();
if (org.getParent() != null)
if (org.getParent().equals(this)) result.add(org);
}
return result;
}
With these methods in place, we can then add other methods to navigate the struc-
ture further. Here are some examples.
11

public Set getAncestors() {


Set result = new HashSet();
if (parent != null) {
result.add(parent);
result.addAll(parent.getAncestors());
}
return result;
}

public Set getDescendents() {


Set result = new HashSet();
result.addAll(getChildren());
Iterator it = getChildren().iterator();
while (it.hasNext()) {
Organization each = (Organization) it.next();
result.addAll(each.getDescendents());
}
return result;
}

public Set getSiblings() {


Set result = new HashSet();
result = getParent().getChildren();
result.remove(this);
return result;
}
Notice how using the familial metaphor means that the method names clearly
communicate what’s being returned by these queries.
Not just are these queries useful for navigation, they are also essential to ensure
that you don’t include a cycle in the hierarchy. The cycle can be prevented with
check along the following lines.
void setParent(Organization arg) {
assertValidParent(arg);
parent = arg;
}
void assertValidParent (Organization parent) {
if (parent != null)
Assert.isFalse(parent.getAncestors().contains(this));
}
Notice that you only need the check on the modifier, you don’t need it on creation.
Also if you’re thinking of setting the parent and then trying the assert, run a test
before you release it.

Variation: Subtypes for Levels


In some cases you may find variation between the various levels in the heirarchy. So
an enterprise may be divided into divisions that are divided into departments. If there
12

is no specific behavior to the organizations at these three levels, then a single organi-
zation class will do the trick for all of them. However if there is variation, then it can
be worthwhile to form subtypes for them as in Figure 0.7

{a company is thee
parent of divisions
which are parents of parent 1 {hierarchy}
departments}

Organization

children

Company Division Department

Figure 0.7 Using subtypes for the various levels

In this case you have a choice, is it better to put the association on the supertype,
or have several associations on the subtypes. The decision rests on how you work the
navigation. If you more often find you navigate around organizations, then it’s better
on the organization. If the explicit levels tend to matter more, then put the associa-
tions on the subtype. If both occur then you can provide both interfaces. I usually find
the single association on organization easier to work with as it usually removes dupli-
cate behavior. You can enforce the constraint when you assign the parent.
If there is no common behavior between the organizational groups, then you can
ditch the organization class completely, although I confess I’ve never done this. Usu-
ally I find there’s some duplicate behavior lying around somewhere that I’d rather
have on the parent.

Sample Implementation
One way of doing the parent checking is to override the parent checking code to put a
run time type check into place.
13

class Division extends Organization ...


void assertValidParent (Organization parent) {
Assert.isTrue(parent instanceof Company);
super.assertValidParent(parent);
Of course this is only a run time check, and you may prefer a compile time check.
You can partly do this by restricting the type on the constructor.
class Division...
Division (String name, Company parent) {
super(name, parent);
}
Putting this checking into the modifier is more awkward. To get it right you need
to remove the Organization’s modifier and put appropriate modifiers only on the sub-
types.
14

Aggregating Attribute

Allow a child to use an attribute value from a parent

Often you may find that an organization shares attributes from its parents to its chil-
dren. Thus the head company, the sales division, and the Boston sales group all use
US dollars as their accounting currency. This is not a coincidence, in fact the intent is
that a child uses the accounting currency of the parent unless there is a specific over-
ride.

Making it work
Showing this on a model can be awkward. From the specification perspective we
would say that every organization has an accounting currency, ie the multiplicity is 1.
But the implementation picture says the currency is optional. You need a field, but a
null would indicate you should look at the parent.
I model this with a stereotype to show an aggregating association as in Figure
0.8 .Again there’s no standard UML way to show this, so a little light extending
makes sense. This notion of an aggregating association or attribute can crop up when-
ever you have some form of composite, so it’s a handy extension.
tbd ref to SanFrancisco

parent 1 {hierarchy}
accounting currency
«aggregating»

Currency Organization
1 ✻ children

Figure 0.8 Aggregating association for currency


15

When to use it
I find this pattern comes naturally with any form of hierarchic structure. The key
question to ask is whether a change in a value for a parent should affect all the chil-
dren. If so, then is sounds like Aggregating Attribute (14). (If the parent provides a
default which is adopted by a child but subsequent changes to the parent do not
change children with the same value, then that’s not Aggregating Attribute (14).)
Of course this will only work well when there is a clear, single parent. If you have
multiple hierarchies, or you’re using Accountability (17) this becomes more compli-
cated. In these situations you need to indicate clearly which parent you’re using as the
basis for the aggregating behavior, and be sure that you are dealing with a hierarchy
rather than a more general graph structure. If you have a more general graph structure
which really does need multiple parents, then you’re hosed and can’t use Aggregating
Attribute (14), which is a good reason to try to avoid multiple parents.

Sample Implementation
An aggregating attribute needs a query method that checks the parent if the appropri-
ate field is null.
class Organization...
Currency getAccountingCurrency() {
if (accountingCurrency != null)
return accountingCurrency;
else {
if (parent != null)
return parent.getAccountingCurrency();
else {
Assert.unreachable();
return null;
}
}
}
Since the association is mandatory, it is an error for the accounting currency to return
a null, so instead it raises an exception. That way should a bug sneak in, you’ll get an
exception closer to the pesky insect. Of course a chance of a virtual cockroach can be
reduced, if not eliminated, by ensuring the setter checks for the correct values.
16

void setAccountingCurrency(Currency arg) {


assertValidAccountingCurrency(arg);
accountingCurrency = arg;
}

void assertValidAccountingCurrency(Currency arg) {


Assert.isFalse (arg == null && getParent() == null);
}

Obviously, if you have a deep hierarchy with frequent access than looking up the
hierarchy each time will be rather slow. So in those cases you can cache the parent’s
value in the children. While this alters the internal behavior it doesn’t alter the exter-
nal behavior, so the pattern is still present and any tests written for the slow imple-
mentation should still work for the optimized version.
17

Accountability

Represents a complex graph of relationships between parties

Accountability
Type


✻ 1 child
Accountability Party

✻ 1 parent

If you are dealing with an organization with a single hierarchy, or even a couple, then
Organization Hierarchy (7) is the simplest way to deal with things. However larger
organizations grow beyond this. You often find a host of different relationships
between parties, all of which carry their own meaning. If your hierarchies start breed-
ing like viagra infused rabbits, it’s time to look to Accountability (17).

Making it work
Accountability (17) uses a Typed Relationship (117) to provide the necessary flexibil-
ity. Each instance of accounability represents a link between two parties, the account-
ability type indicates the nature of the link. This allows you to handle any number of
organizaational relationships. Create an instance of accountability type for each kind
of relationship you need, and connect together the patries with accountabilities of
those types (see Figure 0.9 )
18

New England Sales

parent parent

type type
regional : regional :
:Accountability :Accountability
accountability type accountability type

child child

BostonSales

Figure 0.9 An instance diagram showing BostonSales as a child of NewEngland under the regional
sturcture and a child of Sales under the functional structure.

You can then use accountabilities to provide similar navigational behavior to what
you have with Organization Hierarchy (7). The main difference is that much of this
behavior is now qualified by the accountability type. So instead of saying “who are the
parents of Boston Sales” you say “who are the regional parents of Boston Sales”.
Accountability (17) tends to encourage more complicated variations, the most sig-
nificant one is to use a knowledge level to capture rules about what kinds of parties
can be connected together (See page 22).

When to use it
Use Accountability (17) when you need to show organizational structures but Orga-
nization Hierarchy (7) won’t suffice. Remember that Accountability (17) is a good bit
more complicated to use than Organization Hierarchy (7), so don’t use it until you
need it. The main driver is that you have to record several different lines of authority.
If you only need a couple, then using Organization Hierarchy (7) will do the trick, but if
the lines increase in number, then Accountability (17) ends up being simpler.
It’s not difficult to refactor an Organization Hierarchy (7) into using Accountability
(17). Initially you can use both patterns together on the party. The first step is to
rationalize the interface so that clients can use the Accountability (17) interface to
manipulate links held on the original hierarchies. Once you’ve done that you can
19

choose either to dropthe old interface, or to retain it for convenience. You can keep
the old implementation side by side with the new for as long as it’s not getting in the
way. The interface is the thing to sort out first.

Sample Code
The basic implementation for accountability involves three classes: party, account-
ability, and accountability type. In the simple form accountability type has no interest-
ing behavior.
class AccountabilityType extends mf.NamedObject {
public AccountabilityType(String name) {
super(name);
}
}

In this sample I use bidirectional relationships to link accountability and party.


class Accountability {
private Party parent;
private Party child;
private AccountabilityType type;

Accountability (Party parent, Party child, AccountabilityType type) {


this.parent = parent;
parent.friendAddChildAccountability(this);
this.child = child;
child.friendAddParentAccountability(this);
this.type = type;
}
Party child() {
return child;
}
Party parent() {
return parent;
}
AccountabilityType type() {
return type;
}
}
20

class Party extends mf.NamedObject {


private Set parentAccountabilities = new HashSet();
private Set childAccountabilities = new HashSet();
public Party(String name) {
super(name);
}
void friendAddChildAccountability(Accountability arg) {
childAccountabilities.add(arg);
}
void friendAddParentAccountability(Accountability arg) {
parentAccountabilities.add(arg);
}
}
This is the code needed to create structures. Much of the navigation of the structure
then involves code that is along the similar lines to the sample code for Organization
Hierarchy (7). However the code for finding parents and children is a little more com-
plicated.
class Party...
Set parents() {
Set result = new HashSet();
Iterator it = parentAccountabilities.iterator();
while (it.hasNext()) {
Accountability each = (Accountability) it.next();
result.add(each.parent());
}
return result;
}
Set children() {
Set result = new HashSet();
Iterator it = childAccountabilities.iterator();
while (it.hasNext()) {
Accountability each = (Accountability) it.next();
result.add(each.child());
}
return result;
}
You then can set up and use these objects with code like this.
21

class Tester...
AccountabilityType supervision = new AccountabilityType("Supervises");
Party mark = new Party("mark");
Party tom = new Party("tom");
Party stMarys = new Party ("St Mary's");
public void setUp() {
new Accountability (stMarys, mark, appointment);
new Accountability (stMarys, tom, appointment);
}
public void testSimple() {
assert(stMarys.children().contains(mark));
assert(mark.parents().contains(stMarys));
}
Also you often need to carry out navigation along a single accountability type.
class Party...
Set parents(AccountabilityType arg) {
Set result = new HashSet();
Iterator it = parentAccountabilities.iterator();
while (it.hasNext()) {
Accountability each = (Accountability) it.next();
if (each.type().equals(arg)) result.add(each.parent());
}
return result;
}
class Tester...
AccountabilityType appointment = new AccountabilityType("Appointment");
public void testParents() {
Accountability.create(tom, mark, supervision);
assert(mark.parents().contains(stMarys));
assert(mark.parents(appointment).contains(stMarys));
assertEquals(2, mark.parents().size());
assertEquals(1, mark.parents(appointment).size());
assertEquals(1, mark.parents(supervision).size());
assert(mark.parents(supervision).contains(tom));
}

Cycle Checking
Just as with Organization Hierarchy (7) we have to follow certain rules about how we
connect together our parties, in particular we have to ensure that we don’t create
cycles in our accountability structure.
Here there is a difference to Organization Hierarchy (7) in that we treat account-
abilities as immutable objects. As such we need to do the checking when we create
the accountability. We’ll follow the approach of first checking to see if we can create
an accountability, and only then do we create it. We can’t do this in a constructor, so
we need a factory method.
22

class Accountability...
private Accountability (Party parent, Party child, AccountabilityType type) {
...
}
static Accountability create (Party parent, Party child, AccountabilityType type) {
if (!canCreate(parent, child, type))
throw new IllegalArgumentException ("Invalid Accountability");
else return new Accountability (parent, child, type);
}
static boolean canCreate (Party parent, Party child, AccountabilityType type) {
if (parent.equals(child)) return false;
if (parent.ancestorsInclude(child, type)) return false;
return true;
}

class Party...
boolean ancestorsInclude(Party sample, AccountabilityType type) {
Iterator it = parents(type).iterator();
while (it.hasNext()) {
Party eachParent = (Party) it.next();
if (eachParent.equals(sample)) return true;
if (eachParent.ancestorsInclude(sample, type)) return true;
}
return false;
}
Not the fastest algorithm in the world, but nothing that a well placed cache couldn’t
solve.
This checking now allows us to prevent cycles.
class Tester...
public void testCycle() {
Accountability.create(mark, tom, supervision);
try {
Accountability.create(tom, mark, supervision);
fail("created accountability with cycle");
} catch (Exception ignore) {}
assert(!mark.parents().contains(tom)); //just be sure!
AccountabilityType modelMentor = new AccountabilityType();
Accountability.create(tom, mark, modelMentor); // okay to create with different type
assert(!mark.parents().contains(tom)); //now okay
}

Using a Knowledge Level


The basic form of accountability is quite loose, allowing any combination of parties
to be organized in any fashion with any accountability types. While this works well for
some applications, often you want to put some constraints into place to limit the way
23

accountabilties can be organized. You can do this by using a Knowledge Level (32). The
knowledge level for accountability requires a set of party types, and sets up the
accountability types to describe how the party types should be connected together.

Connection Rules
Connection rules (Figure 0.10) provide a simple yet very flexible form of knowl-
edge level. In this form each accountability type contains a group of connection rules
each of which defines one legal pairing of parent and child party types. Figure 0.11
shows an example of how you might configure one of these knowledge levels.

Accountability
Type 1 ✻
Connection Rule
-- checks validity of
accountabilities

1
✻ ✻
allowed parent 1 1 allowed child

Party Type

✻ ✻ ✻
parent 1
Accountability
Party
Time Period
✻ child 1

{the accountability type must have a


connection rule where the parent's
type is the allowable parent and the
child's type is the allowable child

Figure 0.10 Knowledge level for directed graphs.


24

allowable allowable
child parent
doctor : Party Type : connection rule hospital : Party Type

allowable
parent

appointment:
: connection rule
accountability type

allowable
child

allowable allowable
parent child
consultant : Party
patient : Party Type : connection rule
Type

patient care:
accountability type

Figure 0.11 This example shows two accountability types. The appointment accountability type
allows consultants and doctors to be appointed to hospitals. The patient care accountability type records
consultants’ responsibility towards patients.

You then use the knowledge level to check accountabilities. Whenever you create
an accountability, the accountability uses uses its type to check to see if the account-
ability is valid. It is best to place the checking behavior on the accountability type
because different accountability types will define different rules about connectivity. So
if you want to change the rules by just replacing a single object, the accountability
type is the point of replacement.
25

Sample Code
Here is an example that adds knowledge level connection rules to our exisiting sample
code.
We need a simple structural change to party to include the party type.
class PartyType extends mf.NamedObject {
public PartyType(String name) {
super(name);
}
}
class Party ...
private PartyType type;
public Party(String name, PartyType type) {
super(name);
this.type = type;
}
PartyType type() {
return type;
}
}
The rules are added to the accountability type. As we shall see there are more than
one way you can set up rules like this, so I’ll make a subclass to hold the connection
rules.
class ConnectionAccountabilityType extends AccountabilityType ...
Set connectionRules = new HashSet();
public ConnectionAccountabilityType(String name) {
super(name);
}
void addConnectionRule (PartyType parent, PartyType child) {
connectionRules.add(new ConnectionRule(parent, child));
}
Structurally, the connection rule just holds its allowable parent and child types.
class ConnectionRule {
PartyType allowedParent;
PartyType allowedChild;
public ConnectionRule(PartyType parent, PartyType child) {
this.allowedChild = child;
this.allowedParent = parent;
}
}
We can then set up an accountability type with connection rules.
26

class Tester...
private PartyType hospital = new PartyType("Hospital");
private PartyType doctor = new PartyType("Doctor");
private PartyType patient = new PartyType("Patient");
private PartyType consultant = new PartyType("Consultant");
private ConnectionAccountabilityType appointment
= new ConnectionAccountabilityType("Appointment");
private ConnectionAccountabilityType supervision
= new ConnectionAccountabilityType("Supervises");

public void setUp()...


appointment.addConnectionRule(hospital, doctor);
appointment.addConnectionRule(hospital, consultant);
supervision.addConnectionRule(doctor, doctor);
supervision.addConnectionRule(consultant, doctor);
supervision.addConnectionRule(consultant, consultant);

mark = new Party("mark", consultant);


tom = new Party("tom", consultant);
stMarys = new Party ("St Mary's", hospital);
With the structure out of the way, now let’s look at the validation behavior. The
accountability already has behavior for checking basic cycle rules. With the knowl-
edge level in place we can add to this behavior to request the accountability type to
check for the correct party types (Figure 0.12).
class Accountability...
static boolean canCreate (Party parent, Party child, AccountabilityType type) {
if (parent.equals(child)) return false;
if (parent.ancestorsInclude(child, type)) return false;
return type.canCreateAccountability(parent, child);
}

The accountability type can now check the parent and the child through the con-
nection rules.
27

class AccountabilityType...
boolean canCreateAccountability(Party parent, Party child) {
return areValidPartyTypes(parent, child);
}

class ConnectionRuleAccountabilityType...
protected boolean areValidPartyTypes(Party parent, Party child) {
Iterator it = connectionRules.iterator();
while (it.hasNext()) {
ConnectionRule rule = (ConnectionRule) it.next();
if (rule.isValid(parent, child)) return true;
}
return false;
}

class ConnectionRule...
boolean isValid (Party parent, Party child) {
return (parent.type().equals(allowedParent) &&
child.type().equals(allowedChild));
}

appointment :
Accountability a connection rule
Accountability Type

create

can create

can create accountability

are valid party types

* is valid

return result

[result is true] new


new Accountability

Figure 0.12 Interactions for checking an accountability with the knowledge level

With this in place any attempt to create an accountability without a connection


rule should fail.
28

class Tester...
public void testNoConnectionRule() {
try {
Accountability.create(mark, stMarys, appointment);
fail("created accountability without connection rule");
} catch (Exception ignore) {}
assert(!stMarys.parents().contains(mark)); // am I paranoid?
}

Hierarchic Accountability Type


When you’re using accountabilties, you may well find that some of your accountability
types need to maintain a hierarchy, while others don’t need that. You can enforce
hierarchic rules selectively within the validation method of the accountability type.

Sample Code
For the code sample I do this with a flag on the accountability type.
class AccountabilityType ...
private boolean isHierarchic = false;
void beHierarchic() {
isHierarchic = true;
}
boolean canCreateAccountability(Party parent, Party child) {
if (isHierarchic && child.parents(this).size() != 0) return false;
return areValidPartyTypes(parent, child);
}
}

Levelled Accountability Type


Connection rules are the most common way of representing the rules for an account-
ability type. However from time to time you run into situations where there is a strict
set of of levels of party types. An example of this is a regional breakdown where
national parties have children that are states, which have children that are counties,
that have children that have cities.
29

You can represent this with connection rules, but a simpler alternative is to list the
levels on the accountability type.

Accountability Type

Levelled
✻ ✻
Party Type
Accountability Type levels
{ordered}

Figure 0.13 Levelled Accountability types

Sample Code
Setting up levels needs a different test fixture.
30

public class LevelledTester extends junit.framework.TestCase {


private PartyType nation = new PartyType("nation");
private PartyType state = new PartyType("state");
private PartyType county = new PartyType("county");
private PartyType city = new PartyType("city");
private Party usa, ma, nh, middlesex, melrose;
private LevelledAccountabilityType region = new LevelledAccountabilityType();

public LevelledTester(String name) {


super(name);
}
public void setUp() {
PartyType[] levels = {nation, state, county, city};
usa = new Party("usa", nation);
ma = new Party("ma", state);
nh = new Party("nh", state);
middlesex = new Party("usa", county);
melrose = new Party("usa", city);
region.setLevels(levels);
Accountability.create(usa, ma, region);
Accountability.create(usa, nh, region);
Accountability.create(ma, middlesex, region);
Accountability.create(middlesex, melrose, region);
}
public void testLevels() {
assert(melrose.ancestorsInclude(ma, region));
}
public void testReversedLevels() {
try {
Accountability.create(ma, usa, region);
fail();
} catch (Exception ignore) {}
}
public void testSameLevels() {
try {
Accountability.create(ma, nh, region);
fail();
} catch (Exception ignore) {}
}
public void testSkipLevels() {
try {
Accountability.create(ma, melrose, region);
fail();
} catch (Exception ignore) {}
}
}

However the behavior of the levelled accountability type is quite simple. We need
to be able to set the list of levels and to check for valid party types from the exisiting
method in accountability type.
31

class LevelledAccountabilityType extends AccountabilityType {


private PartyType[] levels;
public LevelledAccountabilityType(String name) {
super(name);
}
void setLevels(PartyType[] arg) {
levels = arg;
}
protected boolean areValidPartyTypes(Party parent, Party child) {
for (int i=0; i<levels.length; i++) {
if (parent.type().equals(levels[i]))
return (child.type().equals(levels[i+1]));
}
return false;
}
}
This sample does not allow you to skip levels, i.e. you can’t have a city as a child of
state. If you want to allow level skipping it’s easy to amend areValidPartyTypes to sup-
port this (an exercise for the reader). However if you want to skip some levels but not
others then you’re better off with connection rules.
32

Knowledge Level

A group of objects that describe how another group of objects should behave (also known as
a meta level)

✻ 1
Retirement Plan Employee Type Pay Strategy
1 ✻
1
Knowledge Level

Operational Level ✻
✻ 1
Employee Department

Knowledge Level (32) is one of those abstract patterns that is difficult to describe on it’s
own, although one that you soon recognize in more complex object systems. You have
a Knowledge Level (32) when you have a group of objects whose instances affect the
behavior of a group of operational objects, typically allowing you to alter a system
“without programming” but instead by creating and wiring together some of these
knowledge objects.
33

✻ 1
Retirement Plan Employee Type Pay Strategy
1 ✻
1

Match Cap Wage Proportion Monthly Salary


Hourly Pay Strategy
Retirement Plan Retirement Plan Strategy

Knowledge Level

Operational Level ✻
✻ 1
Employee Department

Figure 0.14 An example knowledge level using employees

Figure 0.14 shows an example of using a knowledge level for employees. The inten-
tion here is that employee types are created with common combinations of payment
and retirement policies. Employee’s are then marked with an employee type to indi-
cate which policies they use. If you need to customize how employees work you would
create a new instance of Employee Type connected to new instances of payment strat-
egy and retirement plan. This choosing and wiring together of objects is how the sys-
tem is configured.

Terminology
In this book, as with the previous edition, I use the term Knowledge Level (32). How-
ever I can’t claim that this is a completly standard term in design circles. There isn’t
such a standard term as yet, which is why I stick with knowledge level.
I started using the terms operational and knowledge levels while working on the
Cosmos project for the UK National Health Service. In this project I worked on a
joint team with doctors and nurses. We coined the terms together because they
seemed to fit the way we looked at the model. The objects in the operational level rep-
resented the day to day operational behavior of the clinicians, while the knowledge
level represented their clinical knowledge.
Another term you commonly come across is meta as in meta-data. Meta is greek for
‘about’ so meta-data means ‘data about data’. You often hear people talk about meta-
34

objects, or meta-levels. If I had to do a poll on terms for this concept using meta some-
thing would probably top the list. However I still prefer knowledge level as I think it
means more to non-software people.
Another term is ‘Active Object Model’. The rationale behind this is that the
knowledge objects take an active part in determining the behavior for the operational
objects. However the term isn’t that widely used, and I don’t like the connotation that
the operational level is somehow passive.
Another personal convention is my habit of drawing the knowledge level at the top
of the diagram and the operational level at the bottom often, but not always, sepa-
rated by a dashed line. Again this is a Cosmos habit which I’ve stuck with as I find it
useful. However it’s not part of any standard, I guess my influence in the world is more
limited than I might like!
It’s a common convention to make the connection between the knowledge and
oeprational level through associations between a ‘thing’ and a ‘thing type’. This has
become so prevalent that I would now hesitate before using any other naming scheme.
The thing type is often referred to as the ‘type object’ of the thing, following the type
object pattern.

Making it work
Knowledge levels are pretty complicated things to put together, and as such people
usually look upon them as an advanced OO technique. The difficulty lies in choosing
a set of objects that really does allow you to handle most changes without touching
much, or any of the source code. It’s often hard to see what combinations will work in
advance, so like with most complicated frameworks, the design needs to evolve.
It’s not possible to say how to do this in the abstract. Instead you need to look at
specific patterns that involve knowledge levels and see what you can learn from them.
It may be that you can use that specific pattern. Or it may be that looking at knowl-
edge levels will help you with a knowledge level for your circumstances.

When to use it
When people start using, or considering to use, a knowledge level; the common
hope is that this will allow non-programmers to change the system behavior ‘without
programming’. While this may occur from time to time, in my experience it is an eldo-
rado. Understanding how the knowledge works and how to configure it is still a pretty
complicated exercise, not one suited for casual programmers. Indeed often experi-
enced programmers find knowledge levels hard to work with.
In my view the benefit of a knowledge level is that it allows people who are experi-
enced with the design to make changes much more quickly than they would otherwise
be able to do.
35

The fact that many of these changes can be made at run time is also appealing.
However this also comes with warnings. Just because you can change the system
‘without programming’ doesn’t mean you can change it without testing. Indeed testing
can be more critical for knowledge levels and often harder to do. Knowledge levels are
there because what they capture is very dynamic, so testing becomes quite an exercise.
Also the fact that changes are done ‘without programming’ means that you usually
have to do your changes without tools. Debugging does not go away with knowledge
levels, nor does configuration control. If your ‘non-programming’ environment doesn’t
provide debugging, configuration, and testing tools (as it won’t) then you’ll either
have to do without or roll your own. I often see people building graphical editors for
knowledge levels, but actually editing is rarely the hardest part of ‘non-programming’.
All of these are serious caveats for using a knowledge level, if they scare you a bit,
then that’s the point. This is not a pattern to be used lightly. However in a complex
business system there always seem to be a few spots where knowledge levels are worth
their cost. When you have a large amount of volatile rules, then a knowledge level can
make a lot of sense. We don’t really have enough of a handle yet on what the guide-
lines are for using them, but we do know know that they should be used rarely, but
when you need them they are essential. Rather like parachutes.
36

Object Graph

A group of objects connected together in a graph structure.

parents ✻ {dag}


Organization

children

Associated Coffee
Makers: Organization

sales : Organization London : Organization

Boston sales : London sales :


Organization Organization

Object graphs are a common way of representing situations where many objects of the
same fundamental type can be connected in a recursive structure. You see them in
organizational structures, work breakdown structures, product structures... the list
goes on and on.
When talking about object graphs in the abstract, you usually talk about nodes and
links. So in the sketch organizations are the nodes, and the instances of the parents/
children association are the links.
37

However I find it hard to talk sensibly about object graphs in the abstract. So I’ve
included this pattern in the organizational structures chapter because organizational
structures provide a good example of how to use Object Graph (36) in practice. For
this pattern I’m really just going to coin some terms that you may find useful in talking
about object graphs when you run into them, and to point out the abstract nature of
the ideas.
Most graph structures you come across in practice are acyclic. That means that if
you look at your ancestors you won’t find yourself.

Variations
There are a number of common variations on the object graph theme
Object Hierarchies have only one parent to each node. Although hierarchies are
more restricitive they do permit some useful behaviors based onthe fact that there is
only one parent, such as Aggregating Attribute (14). Organization Hierarchy (7) is an
example of an object hierarchy. Structures that permit multiple parents are often
referred to lattices, networks, or the intimidating (but mathematically correct)
directed acyclic graph (or dag for short).
The links in a structure may be represented through an association or through a
separate association object. Organization Hierarchy (7) just uses the association while
Accountability (17) uses an association object. In Accountability (17) the accountability
class is the association object. Often when you find association objects you’ll find the
association is typed, allowing you to define multiple graphs over the same set of nodes,
as in the multiple organizing structures discussed in Accountability (17).
You may find the leaf and non-leaf nodes broken out into separate subtypes as in
Figure 0.15. You should do this if there is significant differences in the behavior for the
leaf and non-leaf cases. However it is a good idea to try to put as much of interface up
on the parent as possible, even when it doesn’t look like it makes sense.
An example of this would be a method numberOfChildren. On first sight it seem
that such a method should be on organization as only organizations have children.
However it is useful to define the interface on party and implement it in person to
return 0. If you do that you’ll find that a method such as numberOfDescendents is much
easier to write.
Patterns afficionados will recognise Figure 0.15 as the classic shape of the compos-
ite pattern. Indeed composite usually applies to hierarchic object graphs.
38

children ✻
Party

{hierarchy}

parent 1

Organization Person

Figure 0.15 Breaking out the leaf and non leaf nodes in an object graph.

Making it work
I’ve discussed the issues in making Object Graph (36) work in the organizational pat-
terns: in particular Organization Hierarchy (7) and Accountability (17). Much of what
you need for any use of Object Graph (36) you can find in there.
One point worth reiterating is the way to name the links. These days I always try to
use parent/child, even if that naming does not fit the domain very well. Familial rela-
tionships are a powerful metaphor for these kinds of relationships: if I say the market-
ing department is my grand-uncle it sounds silly, but you know exactly what the
relationship is.
There is a huge body of academic work on representing graph structures in com-
puter programs. Most of this is far more than you would ever need to know, but it
repeatidly suprises me how many people don’t know about this work. If you’re having
difficultiy doing something with a graph structure, dig out some abtruse work on graph
theory, algorithms, or data structures — you may well find an answer to your problem.

When to use it
The choice of when to use the structure is usually better discussed with respect to
the particular applications of the pattern in particular domains. So it’s more useful to
say “when should I use Organization Hierarchy (7) or Accountability (17)” than to ask
“when should I use Object Graph (36) and if so what kind?”
However reading the narrative and discussions around Organization Hierarchy (7)
and Accountability (17) will give you some useful guidelines. In particular bear in mind
39

that using association objects is a good bit more complicated than a simple associa-
tion, so only go that far if you need to.
40
Working Draft

Dealing with
Roles
Martin Fowler
fowler@acm.org

Anyone who runs a company deals with other companies. Such companies may act as suppliers
of goods or services, they may be customers of your products, they may act as agents for selling
goods to your customers, they may be regulatory agencies who you have to deal with to stay on
the right side of the law.
People may do many things within a company. You have engineers, salesmen, directors, accoun-
tants, any of which may need different features in the computer systems within your organiza-
tion.
Dealing with these situations is one of the most common situations in modeling. You have a
group of objects which exhibit bunches of common behavior. They don’t all have the same be-
havior, but they may have some common behavior. At first glance it sounds like a classic case
for inheritance, but there are complications. An object might exhibit more than one bunch of be-
haviors, or may take on new bunches during its lifetime. You may have an agent who is also a
customer, you have an accountant who becomes an engineer.
This paper is an analysis patterns paper, hence I’m looking at the alternatives from a conceptual
point of view, rather than an implementation point of view. I’m asking how we represent our
view of the world in our software, and I’m not looking at important implemenation issues such
as performance, distribution, concurrency etc. I’ve provided some code samples, but they are
there to illustrate the conceptual ideas rather than as statements of what the implementation
should look like. The biggest consequence to this is that I’m concentrating much more on inter-
face than on implementation. You will notice that in particular when you compare the use of
State Object and Role Object. The implementation is essentially the same, the difference is all
about interface.
I’ve divided up how to deal with roles into five broad categories. If most of the objects have the
same behavior with few variations, then you can use just one type to handle all of them ( Single
Role Type).Conversely if they are very different and have no common behavior then just treat
them all as seperate types (Separate Role Type). These are the simple cases, and often they are
the right decision.
The complication comes when there is some similar and some different behavior. Often the most
obvious way of doing this is to use subtyping to show the different behaviors (Role Subtype).
This does not mean that you necessarily use subclassing and inheritance to implement it. These
are analysis patterns and thus more concerned with concepts and interfaces than with impleme-
natations. The key behind this pattern is that clients think they are dealing with a single object
that has multiple changable types. Internal Flag, Hidden Delegate, and State Object are three
patterns that can help you maintain this illusion. Providing the illusion makes the client’s life
simpler, it can be well worth the effort.

© Martin Fowler 20 Jul 1997 1


Working Draft

The illusion is often not worth the effort. In this case it is worth having a seperate object for each
of the roles, linked to a base object that ties things together (Role Object). In some cases it is
better to think of the role as a relationship between two objects (Role Relationship).
In discussing these patterns I’ve also mentioned a couple of others in passing. With OO pro-
grams you try to avoid asking an object whether it is an instance of a type. But sometimes that
is legitamate information for a client to use, perhaps for a GUI display. Remember that asking
an object if it is an instance of a type is something different than asking it if it is an instance of
a class, since the types (interfaces) and the classes (implementations) can be different. Explicit
Type Method and Parameterized Type Method are two ways of getting this information.
So this subject of roles brings with it several techniques. Like most issues in modeling there is
no right way that works in all situations. This paper helps point out the options and the trade-
offs involved.

Problem Solution Pattern p


Combine all the fea-
tures of the roles into a Single Role Type 4
single type
Treat each role as a
Separate Role Type 4
separate type
Make a subtype for
each role. Put com-
Role Subtype 5
mon behavior in the
supertype
How do you represent the many
roles of an object? Put common features
on a host object with a
separate object for
each role. Clients ask Role Object 14
the host object for the
appropriate role to use
a role’s features.
Make each role a rela-
tionship with an appro- Role Relationship 17
priate object
Table 1: Table of Patterns

2 Dealing with Roles


Working Draft

Problem Solution Pattern p


Use an internal flag. Do
method selection inside Internal Flag 8
the class
Put the varying fea-
tures inside a separate,
private class. Delegate Hidden Delegate 10
messages to this object
How do you implement general- when needed.
ization? Create a hidden dele-
gate for each subtype.
Give them a common
supertype with default
State Object 13
behavior. The public
class has a non-null
link to the supertype.
see [Gang of Four].
Use methods named
isTypenam and Explicit Type Method 8
beTypename
How do refer to the dynamic
Use methods of the
type of an object?
form hasType(type-
Parameterized Type Method 14
name) and
beType(typename)
Table 1: Table of Patterns

representing roles

Single Role Separate Role Subtype Role Object Role Rela-


Type Role Type tionship

implement with
need type informatio

Internal Flag
Hidden Dele- State Object Parameterized
gate Explicit Type Type Method
Method

Dealing with Roles 3


The Simple Options Working Draft

The Simple Options


So you have engineers, salesmen, managers and accountants in your organization. Do you really
need to differentiate between them? You need their job description, or some similar indicator.
So, use a Single Role Type with an attribute either of string or of some simple job description
type. If they don’t have any significantly different features to them, then don’t worry about try-
ing to discriminate between them with any of the other patterns in this article.

Single Role Type


How do you represent the many roles of an object?
Combine all the features of the roles into a single type

✓ Simple
✗ Leads to a single complex type

This pattern is here because I’ve seen people do all sorts of things that are just not necessary. Its
really a blank ‘do nothing’ case, but it deserves a mention because you should always ask ‘is
this sufficient?’. Perhaps for the moment you don’t need any other pattern, but you are worried
that version x of the system will need to do something at some point in the future. Well don’t
worry, leave it until then. The one really tangible benefit of object-oriented programming is that
it allows you to change things easily, so do it then. Maybe you won’t need to do it. Even if you
do you may find the world looks rather different then, and the decisions you make now will not
be valid. And this pattern is easy to migrate to the other patterns.
On the other hand consider a situation where you have engineers, salesmen, managers and ac-
countants. They each have many different features. Since they are different you can make them
different types: each role is Separate Role Type. This is what countless developers have done
before you, and it carries the advantage that it separates these different types, removes any cou-
pling between them and allows people to work on them without getting tangled up with worry-
ing about the relationships between them.
But there are two big problems with Separate Role Type : duplicated features and loss of integ-
rity. Engineers, salesmen, managers and accountants are all kinds of person, and as such they
carry a lot of similar things around with them. Names, addresses, personnel information: any-
thing that is general to people. All of these features will have to copied if you have Separate
Role Type, so if there are any changes that affect these common features you have to track down
all these copies and fix them all in the same way. This tedious task is what inheritance is sup-
posed to fix.
The loss of integrity comes when our engineer John Smith adds some managerial responsibili-
ties. If he is both an engineer and a manager we have to create separate objects for each role,
and we cannot tell that they refer to the same person Such loss of information is important if
there might be interactions between being an engineer and being a manager. This lack of integ-
rity is a surprisingly common problem in business systems which often do this with customers
and suppliers. Tying everything back together again can be quite complicated.

Separate Role Type


How do you represent the many roles of an object?
Treat each role as a separate type

✓ Simple
✗ Any shared behavior must be duplicated
✗ Difficult to deal with single object playing many roles

4 Dealing with Roles


Working Draft Using Subtyping

On the whole I don’t like this pattern, because of these two problems. But you should look to
see if the problems are really there. Maybe there is no common behavior, maybe you never have
engineers that are managers (or it is so rare that you just don’t care). If that is really the case then
this pattern is fine. I would be surprised if this were the case, however, in any but a small system.
What if you are looking at a legacy system where they did this, and you need to change it to
provide integrity? In these situations the patterns Object Merge1 and Object Equivalence2 from
[Fowler] may help you out.

Using Subtyping
If your engineers, salesmen, managers and accountants have some similarities and some differ-
ences then an obvious route is that of subtyping as in Figure 1. Put the common features of each
type into the person supertype, and put each additional feature of the subtypes into the appro-
priate Role Subtype. This pattern fits well our usual conception of subtyping. Engineers are spe-
cial kinds of person, each instance of engineer is an instance of person, engineers inherit all the
features of person but may add some features. An application can treat a collection of people at
the supertype level if it doesn’t care about the specialized features. If a person is both an engi-
neer and a manager then it is of both the subtypes. If the party later becomes a retiree we add a
retiree Role Subtype to the party.

Role Subtype
How do you represent the many roles of an object?
Make a subtype for each role. Put common behavior in the supertype

✓ Conceptually simple
✓ Interface is simple
✗ Cannot directly implement if there are multiple or changing roles
✗ Each new role causes the interface of the supertype to change

Oh dear, I hear the sad sounds of object-oriented programmers screaming. What have I done?
Well its that last couple of sentences that’s caused the problem. The major OO languages have
single, static classification; while those offending sentences require multiple, dynamic classifi-
cation. Single classification says that an object may be of only one type and inherit behavior
from other types. Thus John Smith may be an engineer and thus inherit the features of person.
To be a manager as well we need to create a combination engineer/manager type that multiply
inherits from both engineer and manager. If we have many subtypes we will have combinatorial
explosion of these combination subtypes — which is going to be a pain to manage. Multiple
classification means that we can just give John Smith the engineer and manager types without
having any relationship between the types. Static classification means that once an object is giv-
en a type it cannot change type, dynamic classification would allow an accountant to change to
become a engineer.
So since OO programming languages have single, static classification most developers do not
consider this pattern to be an option. In fact it is not as cut and dried as that. When doing analysis

1.Two objects are in fact the same therefore either: copy all the attributes of one over to the
other and switch references, mark one as superseded, or link the two objects with an es-
sence.
2.Some people think that two objects are the same therefore create an equivalence object
between them.

Dealing with Roles 5


Using Subtyping Working Draft

Figure 1. Using subtypes for the roles.(Notation is that of the UML [Fowler UML])

we are looking at capturing the domain experts view of the world. We then match this view of
the world to the interface of our software components. Since we are looking at interface then
this approach is possible.
Lets begin by looking at what our interfaces should be. Take the model of Figure 1. This figure
implies the code in Listing 1. Everything defined in Listing 1 is an interface. This is what we
need to manipulate the objects from the outside.

interface Person {
public String name();
public void name(String newName);
public Money salary ();
public void salary (Money newSalary);
public Money payAmount ();
public void makeManager ();
}
interface Engineer extends Person{
public void numberOfPatents (int value);
public int numberOfPatents ();
}
interface Salesman extends Person{
public void numberOfSales (int numberOfSales);
public int numberOfSales ();
}
interface Manager extends Person{
public void budget (Money value);
public Money budget ();
}

Listing 1. Java interfaces developed from Figure 1

So that’s all very nice, but how do we implement it? There are several answers to how we im-
plement subtyping (see [Fowler]) but here I will show three approaches: Internal Flag, Hidden
Delegate, and State Object.

6 Dealing with Roles


Working Draft Using Subtyping

public class PersonImpFlag implements Person, Salesman, Engineer,


Manager{

// Implementing Salesman

public static Salesman newSalesman (String name){


PersonImpFlag result;
result = new PersonImpFlag (name);
result.makeSalesman();
return result;
};

public void makeSalesman () {


_jobTitle = 1;
};

public boolean isSalesman () {


return _jobTitle == 1;
};

public void numberOfSales (int value){


requireIsSalesman () ;
_numberOfSales = value;
};

public int numberOfSales () {


requireIsSalesman ();
return _numberOfSales;
};

private void requireIsSalesman () {


if (! isSalesman()) throw new PreconditionViolation ("Not
a Salesman") ;
};

private int _numberOfSales;


private int _jobTitle;
}

Listing 2. Implementing the salesman type with flags

First I’ll show how to do it with an Internal Flag. In this case we have a single person class that
implements all four interfaces. For each partition of subtypes we need to indicate which subtype
is appropriate in this case. The methods newSalesman, makeSalesman, and isSalesman
(in Listing 2) show how we can do this. (For these examples I’ve named the type manipulation
methods using Explicit Type Method). These methods can be added to the interface of person.
When it comes to the operations defined on person we need to guard them to ensure they are

Dealing with Roles 7


Using Subtyping Working Draft

only invoked on a salesman, Listing 2 does this with the private method requireIsSalesman.
Any use of the salesman operations on a non-salesman results in a run-time error.

Explicit Type Method


How do refer to the dynamic type of an object?
Use methods named isTypename and beTypename

✓ Explicit interface
✗ If a new type is added the superclass’s interface must change

The payAmount operation is a polymorphic operation, defined on person but implemented dif-
ferently by the subtypes. We can implement this by defining a public operation that is essentially
a case statement based on the type indicator. This kind of type based case statement is generally
a bad idea in object-oriented software, but here it is fine because it is hidden within the person
class. Since we cannot use polymorphic methods we use the internal case statement to imitate
them

public Money payAmount (){


if (isSalesman()) return payAmountSalesman();
if (isEngineer()) return payAmountEngineer();
throw new PreconditionViolation ("Invalid Person");
};

private Money payAmountSalesman () {


return _salary.add (Money.dollars(5).multiply
(_numberOfSales));
};
private Money payAmountEngineer () {
return _salary.add (Money.dollars(2).multiply
(_numberOfPatents));
};

Listing 3. The flags implementation of the polymorphic payAmount method.

The Internal Flag provides a reasonable implementation of this kind of more complex classifi-
cation. It does, however, result in a complex person class which has to take on all the data and
behavior of the subtypes, as well as provide the method selection capabilities. As these respon-
sibilities grow they all get lumped into single class: which can become the kind of beast that will
stalk your nightmares.

Internal Flag
How do you implement generalization?
Use an internal flag. Do method selection inside the class

✓ Supports multiple, dynamic classification


✗ The implementing class has the features of all the types it implements.

Another implementation is to use a Hidden Delegate. In this case the additional data and behav-
ior required by the subtype is implemented in a separate class. This class is hidden because any
client class does not see it. The client software still invokes methods on the person, the pers

8 Dealing with Roles


Working Draft Using Subtyping

class then hands off the methods to the delegate when required. Listing 4 shows how this is done
for the manager type. All the public methods declared in the manager interface have to be de-
clared and implemented in person. The implementation in person checks that the receiving ob-
ject is a manager, and if so delegates the request to the hidden manager object.

public class PersonImpHD implements Person, Salesman, Engineer,


Manager{
// implement manager
public void makeManager () {
_manager = new ManagerImpHD();
};

public boolean isManager (){


return (_manager != null);
};

private void requireIsManager () {


if (! isManager()) throw new PreconditionViolation ("Not a
Manager") ;
};

public void budget (Money value) {


requireIsManager();
_manager.budget(value);
};

public Money budget () {


requireIsManager ();
return _manager.budget();
};

private ManagerImpHD _manager;


}
class ManagerImpHD {

public ManagerImpHD () {
};

public void budget (Money value){


_budget = value;
};

public Money budget (){


return _budget;
};

private Money _budget;

Listing 4. Implementing manger using a hidden delegate

When using the hidden delegate in this way we move the manager specific behavior and data to
the manager object. This reduces the complexity of the person class. It is a significant difference
if the Role Subtype contains a lot of additional behavior and features. The bad news is that per-

Dealing with Roles 9


Using Subtyping Working Draft

son class still has all the interface of the Role Subtype and also has to do the method selection:
the decision of whether to pass the message to the Hidden Delegate.

Hidden Delegate
How do you implement generalization?
Put the varying features inside a separate, private class. Delegate messages to this object
when needed.

✓ Supports multiple, dynamic classification


✓ Varying behavior is separated into the delegate
✗ Method selection is done by the public class.

We can deal with the method selection aspect of the problem by using the State Object of [Gang
of Four]. This works very well when we have some mutually exclusive subtypes, such as sales-
man and engineer. The subtypes are each implemented with hidden objects. The hidden classes
are given a superclass. The person class contains a reference to the superclass object. This hid-
den hierarchy now has the responsibility for determining method selection and type testing, and
it can use inheritance and polymorphism to do this.
Listing 5 and Listing 6 show how we can use State Object for salesman. The data and behaviors
are defined on the salesman hidden object. The superclass hidden object (JobHD) provides a
default behavior, which is to indicate an error. The person provides the overall public interface
and delegates the method in its entirety to the hidden delegate. See the contrast between this and
the manager in Listing 4, in this case the person does nothing other than delegate.
The technique works particularly well for payAmount, as shown in Listing 7. In this case the
state object requires some information from person. This is done by Self Delegation [Beck]:
passing the person as an argument when the delegation is done.

10 Dealing with Roles


Working Draft Using Subtyping

public class PersonImpHD implements Person, Salesman, Engineer,


Manager{

public static Salesman newSalesman (String name){


PersonImpHD result;
result = new PersonImpHD (name);
result.makeSalesman();
return result;
};

public void makeSalesman () {


_job = new SalesmanJobHD();
};

public boolean isSalesman () {


return _job.isSalesman();
};

public void numberOfSales (int value){


_job.numberOfSales(value);
};

public int numberOfSales () {


return _job.numberOfSales();
};

private JobHD _job;

Listing 5. The PersonImpHD class using a state object to implement the salesman interface.

Dealing with Roles 11


Using Subtyping Working Draft

abstract public class JobHD {

private void incorrectTypeError() {


throw new PreconditionViolation("Incorrect Job Type");
};

public boolean isSalesman () {


return false;
};

public void numberOfSales (int value) {


incorrectTypeError();
};

public int numberOfSales (){


incorrectTypeError();
return 0;//value not returned since exception is thrown,
compiler needs return
};
}
public class SalesmanJobHD extends JobHD{

public boolean isSalesman () {


return true;
};

public void numberOfSales (int value){


_numberOfSales = value;
};

public int numberOfSales () {


return _numberOfSales;
};

private int _numberOfSales = 0;


}

Listing 6. JobHD and its subtype for salesman

12 Dealing with Roles


Working Draft Turning the roles into separate objects

public class PersonImpHD implements Person, Salesman, Engineer,


Manager{
public Money payAmount (){
return _job.payAmount(this).add(managerBonus());
};

abstract public class JobHD {
abstract public Money payAmount (Person thePerson);

public class SalesmanJobHD extends JobHD{

public Money payAmount (Person thePerson) {


return thePerson.salary().add (Money.dollars(5).multiply
(_numberOfSales));
};

Listing 7. Implementing payAmount using a state object

If you want to use this with an incomplete partition, i.e. if a person might be neither a salesman
or an engineer but a vanilla person, then you can either make JobHD a concrete class, or create
a nullJobHd class for that case.

State Object
How do you implement generalization?
Create a hidden delegate for each subtype. Give them a common supertype with default
behavior. The public class has a non-null link to the supertype. see [ Gang of Four].

✓ Supports multiple, dynamic classification


✓ Varying behavior is separated into the delegate
✓ Method selection is done by inheritance and polymorphism.
✗ An effort to set up

I must stress the common theme behind all these alternatives: each implementation lies behind
the same set of interfaces declared in Listing 1. We can switch any of these implementations
without affecting any of the users of these interfaces.
I tend to use Internal Flag if there are not many features involved, andHidden Delegate or State
Object if things are more complex. Since they all the same interface you can safely work with
the simplest approach to begin with and change it later when it begins to get awkward.

Turning the roles into separate objects


An alternative to Role Subtype is to use Role Object. In this case we consider engineer, salesman,
accountant, manager, and retiree to all be roles that the employee may play. Person has an multi-
valued association with person role where person role is the supertype of engineer, salesman,
accountant, manager, and retiree. This, referred to by [Coad] as the actor-participant pattern, is
a common technique for these circumstances.
The implementation looks very similar to using the State Object pattern, the difference lies in
the interface. When using Role Subtype with State Object, the state objects are entirely hidden
from the user of the class. To find a manager’s budget a user asks the person object, which then
makes the appropriate delegation. When using Role Object, however, the user asks the person

Dealing with Roles 13


Turning the roles into separate objects Working Draft

object for its manager role, and then asks that role for the budget. In other words the roles are
public knowledge.
Roles are most often used in the style of Figure 2, where each person has a set of role objects
for its various roles. Listing 8 shows how person adds and accesses these roles. We begin with
the person, as before, but changing the amount of sales for a salesman now requires two steps:
first we find the salesman role for the person, then we change the value.

Role Object
How do you represent the many roles of an object?
Put common features on a host object with a separate object for each role. Clients ask
the host object for the appropriate role to use a role’s features.

✓ Direct implementation
✓ If you add a new role you don’t have to change the host’s interface.
✗ Awkward if roles have constraint
✗ Exposes role structure to clients of the host object

Figure 2. Using role objects for person.

In this case I have used a different approach for the type information. In Listing 6 I used a meth-
od isSalesman which defined in the superclass to be false and overridden in the subclass. I could
use the same approach in this case. However, for variety’s sake, I’ve shown a different approach
which uses a parameterized hasType(String) method. The hasTyp approach has the advan-
tage that we don’t need to change the interface of person role or person when we add a new role.
Its disadvantages are that it makes the interface less explicit and the compiler cannot check the
correctness of the parameter. I usually prefer the explicit form, but find the parameterized form
useful when interface changes due to new types become too much to be worth the compile time
checking.

Parameterized Type Method


How do refer to the dynamic type of an object?
Use methods of the for hasType(typename) and beType(typenam )

✓ New types do not cause a change to the superclass


✗ Interface is less explicit

14 Dealing with Roles


Working Draft Turning the roles into separate objects

class Person {
public void addRole(PersonRole value) {
_roles.addElement(value);
};

public PersonRole roleOf(String roleName) {


Enumeration e = _roles.elements();
while (e.hasMoreElements()) {
PersonRole each = (PersonRole) e.nextElement();
if (each.hasType(roleName)) return each;
};
return null;
};

private Vector _roles = new Vector();



}
public class PersonRole{

public boolean hasType (String value) {


return false;
};

public class Salesman extends PersonRole{

public boolean hasType (String value) {


if (value.equalsIgnoreCase("Salesman")) return true;
if (value.equalsIgnoreCase("JobRole")) return true;
else return super.hasType(value);
};

public void numberOfSales (int value){


_numberOfSales = value;
};

public int numberOfSales () {


return _numberOfSales;
};

private int _numberOfSales = 0;


}
// To set a salesman’s sales we do the following
Person subject;
Salesman subjectSalesman = (Salesman)
subject.roleOf("Salesman");
subjectSalesman.numberOfSales(50);

Listing 8. Salesman as one of a set of roles on person.

This common use of roles does not really provide the same model as Figure 1. In Figure 1 there
are definite rules as to what combinations of roles can be used. You must be one of either a sales-
man or engineer, and you may be a manager in addition. To preserve the rules we have two al-
ternatives. One alternative is to change the addRole method to check the validity of a new role
as in Listing 9. A better way, however, is to alter the interface of person to make the restriction
more explicit as in Listing 10.

Dealing with Roles 15


Turning the roles into separate objects Working Draft

class Person {
public void addRole(PersonRole value)throws CannotAddRole {
if (! canAddRole(value)) throw new CannotAddRole();
_roles.addElement(value);
};

private boolean canAddRole(PersonRole value){


if (value.hasType("JobRole")){
Enumeration e = _roles.elements();
while (e.hasMoreElements()) {
PersonRole each = (PersonRole) e.nextElement();
if (each.hasType("JobRole")) return false;
};
};
return true;
};

Listing 9. Checking a added role is valid

class Person {

public void jobRole(JobRole value){


_jobRole = value;
};

public PersonRole jobRole() {


return _jobRole;
};
private JobRole _jobRole;
}

Listing 10. Using an explicit interface to capture the constraints of job roles in person.

In the kind of situation here, where there are not too many roles and there are restrictions, I tend
to prefer using Role Subtype. Role Subtype provides a simple single class interface. The disad-
vantage of Role Subtype is that the interface of person has to include all the methods defined on
the roles, which is awkward if the role interface is large or volatile. If it is awkward to continu-
ally change the person’s interface then that is the force that drives me towards Role Object. In
most situations where that force is present the set of roles of Figure 2 makes the most sense. Any
rules on combinations of roles must be captured: if they are simple I use the technique of Listing
9, if they are more complex then I will change the interface and use Listing 10 style. In practice
I find that the situations that propel to a Listing 10 style interface are best solved usingRole Sub-
type anyway. Remember that you can use one technique for some roles and a different one for
other roles.
A useful variation on this pattern is to make the role objects decorators of the core object. This
means that a client who uses only the features of employee person can deal with a single object
and not need to know about the use of role objects. The cost is that when ever the interface of
person changes, all the roles need to be updated. See [ Bäumer et al] for more details on how to
do this.
The final alternative in modeling roles that I’m discussing in this paper is Role Relationship. The
need for Role Relationship comes up when you consider an organization with several different
groups, where an employee might have roles in more than one group. A salesman may begin

16 Dealing with Roles


Working Draft Which Role to Choose

with one group, change to another, take retirement, but still do some work for another. In this
case in each role we need to know not just the role, but also which group the employee keeps
the role with. You can think of the role as an employment relationship between the employee
and the group. As soon as you start thinking of a role as a relationship the Role Relationship
pattern of Figure 3 starts to make sense.

Figure 3. Treating the role as a relationship

Using and implementing Role Relationship is pretty similar to Role Object (see Listing 11), the
main difference is in the fact that setting up and accessing the roles needs a group as a parameter.
If there are constraints between the roles, then you can use the same techniques as with Role
Object.

Role Relationship
How do you represent the many roles of an object?
Make each role a relationship with an appropriate object

✓ Natural if the host object may have more than one role in relationship to another
object.

A common situation with this pattern is that the Role Relationship change over time, and a his-
tory of these changes needs to be kept. There might also be rules that indicate which kinds of
people can have what kinds of Role Relationship with different kinds of groups. Accountability
and related patterns in [Fowler] discuss these kinds of complications furthe .

Which Role to Choose


Whenever you have a situation that involves roles, never forget that you have several options to
choose from in modeling it.
Are the role significantly different? If the differences are minor the I use Single Role Type. I
don’t worry about it not being flexible enough. If I need the flexibility later, it is easy to refactor
it.
Are there any common behaviors between the roles? If not I might go for Separate Role Type .
I’m always wary of the integrety issue though. This pattern can be more awkward to shift later
on if this crops up.
Only if I know I have significant common and shared behavior, and I need to ensure integrety
do I need to go to the heavyweight options. Here often the key decision is betweenRole Subtype

Dealing with Roles 17


Which Role to Choose Working Draft

class Person {
public void addRole(PersonRole value)throws CannotAddRole {
_roles.addElement(value);
};

public PersonRole roleOf(String roleName, Group group) {


Enumeration e = _roles.elements();
while (e.hasMoreElements()) {
PersonRole each = (PersonRole) e.nextElement();
if ((each.hasType(roleName)) && (each.group() ==
group)) return each;
};
return null;
};

private Vector _roles = new Vector();



public class PersonRole{

protected PersonRole (Group group){


_group = group;
};

public Group group(){


return _group;
};

protected Group _group;



public class Salesman extends PersonRole{

public Salesman (Group group){


super (group);
};

Listing 11. Using a relationship for the role.

and Role Object. Many authors will tell you to always use Role Object, I don’t agree. The key
question I ask is what is the best interface for the users of my classes? Three indicators suggest
Role Subtype: there aren’t too many roles, new roles do not appear often, and there are signifi-
cant rules about what combinations and migrations of roles that can occur. If those forces are
present then I go with Role Subtype. That way I present a simpler interface. I make that decision,
and then choose how to implement it. The implementation is a little harder thanRole Object, but
I’m saving my clients that same amount of work. Since there are many of them, that can be a
considerable favor.
I would choose Role Object when either I have a lot of roles, or I often get new roles. These
forces would lead to a large or volatile interface for a Role Subtype. By this point it would be-
come just too much work to keep up the Role Subtype.
I consider Role Relationship when the roleness I’m interested in is all about a relationship be-
tween the core object and some other object. This is a particularly true if the core object can play
the same role with many other objects, or if I want to track the changes to the roles that the core
object plays over time.

18 Dealing with Roles


Working Draft A Role with Many Players

A Role with Many Players


All of these patterns make a common assumption, that a role is something played by a single
core object within some context. But this assumption is not true of all situations that suggest
roles. When I ring up an airline to book a reservation, I am looking for someonw to play the
reservation role for me, but I don’t care which person plays it. In this situation the role is the key
element but the person is irrelevent. I can ring up three times about the same reservation and I
will usually have a different person each time. In this situation I don’t usually know very much
about the role.
A slightly different situation appears when you have consistent on-going dealings with a role
where there is usually a single core object, but it changes over time. This might occur when you
work with a regional salesman for your area. The actual person changes but the role stays the
same. Again the role is more important to you than the person.
I’m not going to discuss these situations in this paper, at least not until a later version. I still need
to think more about the patterns I have seen for this kind of problem. The latter case (a role with
many actors over time) can be modeled using the Post pattern[Fowler].

Summing up
I wrote this article because I was frustrated. This frustration is good source for patterns. Often
it’s the frustration of seeing people do the same thing wrong time and time again. In this case
the frustration stems from people who use one of these patterns all the time, and decry the oth-
ers. I don’t object to any of these patterns — what I object to is a practice of using one of them
all the time.
Design is all about trade-offs, and every one of these patterns comes with its own set of trade
offs. Any of the patterns in this paper can be the right pattern for your problem. Dogmatic ad-
herence to one pattern is not the answer, you have to understand an evaluate the trade-offs. This
truth is eternal in design.

Further Reading
Roles have long been a technique known to the object and data modeling communties. I consid-
ered writing about them in Analysis Patterns [Fowler], but considered the subject too trivial
(rather like saying numbers can support arithmetic). I changed my mind because so often people
will describe one of these patterns (particularly Role Object) as the only solution without talking
about the full set of trade-offs. Hence there is no real treatment of the subject in Analysis Pat-
terns, except for the discussion of Accountability (2.4) which is a use of Role Relationship.
[Bäumer et al] provides a in-depth discussion of implementing Role Object. Their approach
makes the role object a decorator [Gang of Four] of the base object. This means that clients can
deal with the role object without knowing that the base object is in fact a seperate object. If that
helps simplify things for the client, it is a useful tactic.
[Gamma, Extension] discusses a pattern for extending the behavior objects using a similar ap-
proach to that of role objects. The solution is similar to that of Role Object but the intent is some-
what different. The Extension pattern is mainly about dealing with unanticipated changes to an
objects services, while the Role Object pattern is more about dealing with an object playing
many seperate roles.
[Schoenfeld] discusses a couple of uses of Role Object with people and documents.
[Hay] has many examples of role modeling problems dealt with in a relational flavor.

Dealing with Roles 19


Further Reading Working Draft

[Coad] describes the Actor-Partcipant pattern, which is essentiallyRole Object, and gives many
examples of using it.
I should mention that a proper reference to everybody who has discussed using roles would con-
sume more pages than this paper. Using roles in some way or another is to modeling what if-
then-else statements are to programming. Thus there is a lot that has been written on the subject,
usually in an off-had way that is characteristic when people write about very well-known con-
structs. My apologies to the many people I could have referenced here, but did not.

References
[Arnold/Gosling] Arnold, K. and Gosling, J. The Java Programming Language, Addison-Wesley,
Reading, MA, 1996.
[Beck] Beck, K. Smalltalk Best Practice Patterns, Prentice Hall, Englewood Cliffs, NJ, 1997
[Bäumer et al] Baumer D, Riehle D, Siberski W and Wulf M The Role Object Pattern, submitted for PLoP
97
[Coad] Coad, P., North, D. and Mayfield, M. Object Models: strategies, patterns and applications,
Prentice Hall, Englewood Cliffs, 1995.
[Fowler] Fowler, M Analysis Patterns: reusable object models , Addison-Wesley, Reading MA, in press.
[Fowler UML] Fowler M with Scott K, UML Distilled: Applying the Standard Object Modeling
Language, Addison-Wesley, 1997.
[Gang of Four] Gamma, E., Helm, R., Johnson, R. and Vlissides, J. Design Patterns: elements of reusable
object-oriented software, Addison-Wesley, Reading, MA, 1995.
[Gamma, Extension] Gamma E, The Extension Objects Pattern , Submitted to PLoP 96
[Hay] Hay D, Data Model Patterns: Conventions of Thought , Dorset House 1996
[Meyer] Meyer, B. "Applying “Design by Contract”," IEEE Computer, 25,10, (1992), pp. 40–51.
[Odell] Martin J and Odell JJ Object Methods: Pragmatic Considerations, Prentice Hall 1996
[Schoenfeld] Schoenfeld A, Domain Specific Patterns: Conversions, Persons and Roles, and Documents
and Roles, submitted to PLoP 96

20 Dealing with Roles


Specifications
by Eric Evans <evans@acm.org> and Martin Fowler <fowler@acm.org>

Introduction
One of the nice things about working in Silicon Valley is that almost any time of the year you can
walk around outside while discussing some design point. Due to serious follicle impairment Martin
needs to wear a hat when doing this in the sunshine. Eric was talking to him about the problems of
matching shipping services to the requests customers make and the similar process as the shipper
makes requests to contractors. There was some similarity here that suggested an abstraction. Eric had
been using a model he called "specification" to represent the requirements for a route and to ensure
that cargoes were stored in proper containers. Martin had come across similar problems before. In a
trading system people were responsible for looking at the risk implied by some subset of the bank’s
contracts. Healthcare observations could be made on a population to indicate typical ranges of some
phenomenon type (such as the breathing flow for a heavy smoker in his 60’s). He suggested some
extensions to the model. From that point it was clear that there were patterns in our experiences, and
we could pool our ideas. As we explored the patterns further, they helped clarify the abstractions for
Eric’s project and gave Martin ideas on how some of the analysis patterns in his book [Fowler] could
be improved.

A valuable approach to these problems is to separate the statement of what kind of objects can be
selected from the object that does the selection. A cargo has a separate storage specification to
describe what kind of container can contain it. The specification object has a clear and limited
responsibility, which can be separated and decoupled from the domain object that uses it.

In this paper we examine the specification idea and some of its ramifications in a series of patterns.
The central idea of Specification is to separate the statement of how to match a candidate, from the
candidate object that it is matched against. As well as its usefulness in selection, it is also valuable for
validation and for building to order.

This paper is not going to go into details about how a specification is implemented. We see this as an
analysis pattern, a way of capturing how people think about a domain, and a design pattern, a useful
mechanism for accomplishing some system tasks. We do have some sample code, though, as is
rather too glib to talk about objects that have all these capabilities without at least outlining how this
could be done. Also, there are consequences to different implementations. We will look into three
implementation strategies you can apply to specifications. A Hard Coded Specification implements the
specification as a code fragment, essentially treating the specification as a Strategy [Gang of Four]. This
allows a great deal of flexibility, but requires programming for every new specification. A Parameterized
Specification allows new specifications to be built without programming, indeed at run time, but you are
limited as to what kind of specifications you can build by what the programmers have set up.
Although programmers can be generous in providing parameters to customize, eventually they can
make the parameterized specification too complex to use and difficult to maintain. A Composite
Specification uses an interpreter [Gang of Four] to cut a very agreeable middle path. The programmers
provide basic elements of the specification and ways to combine them, later users can then assemble
specifications with a great deal flexibility.

Once you have used specification, a powerful pattern that builds on it is Subsumption. The usual use of
specification tests the specification against a candidate object to see if that object satisfies all the
requirements expressed in the specification. Subsumption allows you to compare specifications to see if
satisfying one implies satisfaction of the other. It is also sometimes possible to use subsumption to
implement satisfaction. If a candidate object can produce a specification that characterizes it, the
testing with a specification then becomes a comparison of similar specifications — removing the

1
coupling of specification mechanism entirely from the domain. Subsumption works particularly well
with Composite Specifications.

Sometimes it is useful to think about cases where you have a Partially Satisfied Specification. You may not
find any matches for the complete specification. Or you may have completed part of the specification
and need to consider alternatives for the part that remains.

Problem Solution Pattern

You need to select a


subset of objects based
on some criteria, and to
refresh the selection at
various times Create a specification that is able Specification
to tell if a candidate object
You need to check that matches some criteria. The
only suitable objects are specification has a method
used for a certain role isSatisfiedBy (anObject) :
Boolean that returns "true" if all
You need to describe criteria are met by anObject.
what an object might do,
without explaining the
details of how the object
does it, but in such a way
that a candidate might be
built to fulfill the
requirement

Code the selection criteria into Hard Coded


the isSatisfied method as a block Specification
of code

How you implement a Create attributes in the


specification? specification for values that Parameterized
commonly vary. Code the Specification
isSatisfiedBy method to combine
these parameters to make the
test.
Composite
Create a particular form of Specification
interpreter for the specification.
Create leaf elements for the
various kinds of tests. Create
composite nodes for the and, or,
and not operators (see
Combining Specifications,
below).

2
How do I compare two Create an operation called Subsumption
specifications to see if isGeneralizationOf(Specification
one is a special case of ): Boolean that will answer
the other, or is whether the receiver is in every
substitutable for another? way equal or more general than
the argument.

You need to figure out Add a method Partially Satisfied


what still must be done "remainderUnsatisfiedBy" that Specification
to satisfy your returns a Specification that
requirements. expresses only the requirements
not met by the target object.
You need to explain to (Best used together with
the user why the Composite Specification).
specification was not
satisfied.

The Need for a Specification


Imagine a trader in a bank who is responsible for a managing the risk on some set of contracts that
the bank deals in. He might consider a portfolio of all contracts that involve the yen. A colleague,
concerned about a particular set of risks wants to examine all Deutchmark contracts with US based
companies. Each of these traders wants the ability to specify selection criteria for the kind of contracts
that they want to monitor in their portfolio, and for the system to remember these selection criteria.
They might look at the resulting portfolio at regular intervals, or they may want to keep the portfolio
always on the screen and have it automatically recognize any new contracts that fit the conditions that
they are concerned about. The portfolio is responsible for selection of appropriate contracts.

Imagine a shipping company that moves various kinds of goods around the world. It has a cargo of
meat that it wants to put in a container. Not all containers would be suitable for such a cargo. To hold
meat a container must be refrigerated (known in the trade as a "reefer") and must be clean enough to
safely store food. Whenever a cargo is assigned to a container you need to check that the container is
a suitable container for the cargo. The system has the responsibility for validation when we assign a
cargo to a container.

Imagine a customer booking a shipment. They want to move meat from Des Moines to Beijing
entering China at Shanghai. There are various routes that a shipping company could use to do this,
but they need to know the constraints on the routes in order to construct an appropriate itinerary.
This way they can build the route to order from the request.

3
Specification

Problem

Selection: You need to select a subset of objects based on some criteria, and to refresh the selection at
various times

Validation: You need to check that only suitable objects are used for a certain purpose

Construction-to-order: You need to describe what an object might do, without explaining the details of
how the object does it, but in such a way that a candidate might be built to fulfill the requirement

Solution

Create a specification that is able to tell if a candidate object matches some criteria. The
specification has a method isSatisfiedBy (anObject) : Boolean that returns true if all
criteria are met by anObject.

Consequences

+ decouple the design of requirements, fulfillment, and validation

+ allows clear and declarative system definitions

Each of these situations is common in business systems. Although they seem different they share a
common theme. This theme is the notion of some test that we can apply to candidate objects to see if
they fit our needs, this test is a specification of what is needed. The specification is, in essence, a
boolean function which applies to the candidate which indicates whether or not it matches. If you use
specification in a strongly typed language, you usually set the parameter type of isSatisfiedBy to be the
type of candidate object you are looking for.

Uses of Specification
The trader defines a specification for the kind of contracts that he wants to monitor in a portfolio.
When the portfolio is created it will look at all contracts and select those that satisfy the specification.
Whenever a new contract is created, it may have to check itself against existing portfolios to see if it
belongs to some of them. Alternatively, the portfolio's contents might be derived by a query each time
it is used. You can think of the portfolio as a subset of contracts that is defined by the specification.

4
Portfolio Specification
1
Portfolio
isSatisfiedBy (Contract) : boolean
[

«derivation»
all contracts for which the portfolio
[ specification returns true

Contract

Figure 1. Using specifications to describe the selection criteria for portfolios in contracts (see [Fowler] §9.2). All diagrams use the
UML notation [Fowler, UML]

A similar situation appears when you want to make an observation for a group of people — such as
typical ranges for respiratory function of heavy smokers over 60. The population has a specification
which selects appropriate patients as falling into the population. Observations can then be made of
patient, or of the population.

Observation

[
Population Specification
Population
1
isSatisfiedBy (Patient) : boolean
1 [

Object of Care

Patient

Figure 2. Using specification to define populations in healthcare (see [Fowler] §3.5 and §4.1)

In sales organizations an important part of the business is allocating sales to an appropriate sales
representative. This is important to the sales rep as commisions are based on how many sales occur in
the territory that the sales rep is responsible for. The territory is a specification which selects deals.
Typically they are based on geographic area (often with postal codes), size of the deal, the industry
group of the customer, and large customers are individually named. Complications include ensuring
that territories are not overlapping. Either the specification should only match one territory, or it
should ensure that there is a way of prioritizing or pro-rating between several matched territories.

5
Temporal specifications can be used to describe recurring calendar events. The elements in these
specifications may include the day of the week, a period within a year, specific named days, and fixed
length intervals from some seed date. Complications include handling how regular business events can
be put off by holidays.

Whenever a shipping company assigns a cargo to a container it checks the cargo’s storage
specification to ensure that the container is appropriate for the cargo. You can think of this as a
constraint on the container for a cargo.

Storage Specification
1
Cargo
isSatisfiedBy (Container) : boolean
[

{container must match the


1 storage specification}

Container

Figure 3. Using specifications to constrain which containers can be used for transporting a cargo.

The customer provides a route specification for the shipment. The shipping company will use the
specification as a constraint in coming up with a route.

Route Finder

suitableRoutes (Route Specifiion) : set of Routes


preferredRoute (RouteSpecification) : Route

1
Route
Shipment
Specification

Figure 4. Using a specification as an input to a route selector. This decouples the route selector from the shipment.

In each of these cases the specification object is a separate object to the domain object that uses it.
The portfolio could contain an operation to test for contract membership, the cargo could contain an
operation for checking that a container is valid, the shipment could provide the necessary information
for the route finder.

Treating the specification as a separate object has a number of advantages.

6
Consequences of Specification

Lets you decouple the design of requirements, fulfillment, and validation


Because the objects involved now have a crisper responsibility, it is easier to decouple them. This
allows us to avoid the duplication of effort of implementing similar functionality many times, and
makes integration much easier, since different parts of the system use the same constructs to express
constraints or requirements, and frequently communicate with each other in these terms.

Allows you to make your systemdefinitions more clear and declarative.


For example, if you have built a mechanism that is supposed to derive an object that fits a spec, even
if you trust the mechanism enough not to check, it gives your design a clear definition. RouteSelector
finds a Route that satisfies a RouteSpecification. Even if we do not do an isSatisfiedBy: test, we have
clearly defined the responsibility of RouteSelector without linking it to a specific process for finding
routes.

When Not to Use Specification

There are temptations to over-use Specification. The most common is to use it to build objects with
flexible attributes — a sort of poor man’s frame system. Remember that the specification has a clear
responsibility: to identify an object that satisfies it, and to combine with other specifications in various
ways that support that basic responsibility (see below). A route is not the same thing as a route
specification. The route should have responsibilities such generating an itinerary or reserving space
on the transports being used. The route could tell us that the cargo is expected to arrive at a certain
date and time on a certain vessel. The route specification might know that the cargo must arrive on
or before a certain date and time, and tell us if a chosen route meets its requirements. Since the
attributes of a route specification are so similar to the route, there is a temptation to combine the two
behaviors into one object, and a route just becomes a route specification that fully specifies every
detail of the journey. This would require the machinery of the specification to handle this quantity of
data efficiently, even though route requirements are usually relatively simple, and it would require
route behavior to operate off of an internal representation that was far more flexible that route needs
to be. Most of all, the clarity of the design is lost.

If you find yourself adding to the protocol other than for initialization, if you find that you don’t use
isSatisfiedBy or isGeneralizationOf (see below), if you find that your object is representing an actual
entity in the domain, rather than placing constraints on some other, possibly hypothetical, entity, you
should reconsider the use of this pattern.

Strategies for Implementing Specification


There are various ways you can implement a specification, and now we will look into that in more
detail. We won’t go into the details of implementation here, as these will vary depending on your
language and database. Instead we will just outline the principal approaches you can use. We will
illustrate the strategies by discussing how they would handle a storage specification (as in Figure 3).
The specification calls for the container to be able to store goods at less than -4°C and meet the
sanitary requirements for storage of food. The sample code is in Smalltalk.

7
Hard Coded Specification

How you implement a specification?

Code the selection criteria into the isSatisfied method as a block of code

Consequences

+ easy

+ expressive

- inflexible

The simplest approach is to just create special purpose objects that specify each target object of
interest and implement a single Boolean method.

Define an abstract class (or interface) that declares the isSatisfiedBy operation and provides the type
for the parameter.
StorageSpecification>>isSatisfiedBy: aContainer

Each subclass then implements that operation.


MeatStorageSpecification >> isSatisfiedBy: aContainer
^ (aContainer canMaintainTemperatureBelow: -4) and: [aContainer
isSanitaryForFood]

This is essentially an application of Strategy [Gang of Four], where each cargo has a strategy for
evaluating a potential container. Each validation rule we need requires a subclass of the strategy.

The problem with this approach is the need to create a subclass for every selection criterion. This
works well if we do not need too many selection criteria, and if we don’t need to create new ones at
runtime. Explicit code is straightforward, and expressive.

A variation on this that works in languages with block closures (such as Smalltalk) is to put the
implementation of isSatisfiedBy into a Boolean block object, so that we don’t need to use a subclass.
The code can even be added at runtime, although you do need someone who knows Smalltalk to
write the appropriate block. Also using Blocks in this way can be a pain to debug.

Parameterized Specification

How do you implement a specification?

Create attributes in the specification for values that commonly vary. Code the
isSatisfiedBy method to combine these parameters to make the test.

+ some flexibility

- still requires special-purpose classes

The problem with the hard-coded specification is that even small changes require a new subclass. If
you have conditions such as a car with a specified top speed, then it is silly to create a different
subclass for each possible speed. How do you implement a specification that will give you the

8
flexibility to express small variations simply? Make the key variables parameters of the specification.
(So you can put the speed into the specification as a parameter.)

This implies that you need these parameters in the specification as attributes. When you create the
specification, you put the values in the attributes, and the isSatisfiedBy method uses the parameters to
make its selection.

In the cargo specification example above, we might have a cargo specification that looks like this.

Cargo Storage Specification


maxTemp: Temperature
isSanitaryForFood: Boolean
isSatisfiedBy(Container) : Boolean

Figure 5. An example of a parameterized specification.

The isSatisfiedBy method would then look like


CargoStorageSpecification >> isSatisfiedBy: aContainer
^ (aContainer canMaintainTemperatureBelow: maxTemp) and: [
isSanitaryForFood ifTrue: [ aContainer isSanitaryForFood ] ifFalse:
[true]
]

Whereas the MeatStorageSpecification was very special purpose, this CargoStorageSpecification could
be used for a variety of cargoes.

The parameterized specification makes it easy to create a wide range of specifications as you vary the
parameters. Users can usually spell out the exact specification by filling in a dialog box. However you
can only vary those parameters that are provided. If you need to add a new parameter, that does
require new coding. If you have a lot of parameters, then a single parameterized specification can get
very complicated to code and to use.

Composite Specification
How do you implement a generalized specification that will give you the flexibility to express complex
requirements without implementing specialized classes for every different type of candidate? The hard
coded and parameterized specifications both use a single specification object to handle the
specification. The composite specification uses several objects arranged in the composite pattern
[Gang of Four] to do the work.

9
Composite Specification

How do you implement a specification?

Create a particular form of interpreter for the specification. Create leaf elements for the
various kinds of tests. Create composite nodes for the and, or, and not operators (see
Combining Specifications, below).

Consequences

+ very flexible, without requiring many specialized classes

+ supports logical operations

- must invest in complex framework

The key to this pattern is to provide a class that can combine specifications formed in different ways.
A simple example of this is a specification which is true if all its components are true (we will call is a
conjunction specification later on).
CompositeSpecification isSatisfiedBy: aCandidate
(self components do: [:each |
(each isSatisfiedBy: aCandidate) ifFalse: [^false]
]
^true

It need not know anything about how each component specification does its work. In the meat
example we might have one parameterized specification to test for temperature.
MaximumTemperatureSpecification isSatisfiedBy: aContainer
^aContainer canMaintainTemperatureBelow: maxTemp

And another for the food sanitation.


SanitaryForFoodSpecification isSatisfiedBy: aContainer
^aContainer isSanitaryForFood

We can then form the overall specification by combining them


meatSpecification
^CompositeSpecification
with: MaximumTemperatureSpecification new: -4
with: SanitaryForFoodSpecification new

The class diagram for this structure would look like this

10
Specification
[
components
isSatisfiedBy()

Composite Leaf
Specification Specification

isSatisfiedBy() isSatisfiedBy()

Maximum Temperature Specification SanitaryForFoodSpecification


maximumTemperature: number
isSatisfiedBy() isSatisfiedBy()

Figure 6. Composite Specification using conjunction.

And the instances would look like this

a Composite
Specification

components

a Sanitary For Food a MaximumTemperature Specification


Specification maximumTemperature: -4

Figure 7. An example of a composite specification.

Define class CompositeSpecification as a Specification stated in terms of other


Specifications. Special purpose primitive Specification subclasses may be needed for specialized
applications. But a few primitive specifications can be built that can serve in different situations.
Here we will define just one very versatile one, ValueBoundSpecification, to be a named
value that expresses a limit on an attribute identified by the name. Lower bounds, upper bounds and

11
exact values may be defined with separate subclasses, or with case logic. Using these primitives, a
range can be expressed by a composite of a lower bound and an upper bound.

Logical Expressions for Composite Specifications


In the example above, the composite specification combines its components by conjunction. All the
components must be true for the composite to be true. You can get more flexibility by providing
composite specifications for the other logical operators.

Specification
[
components
isSatisfiedBy()

Composite Leaf Negation


Specification Specification Specification

isSatisfiedBy() isSatisfiedBy() isSatisfiedBy()

Conjunction Disjunction
Specification Specification

isSatisfiedBy() isSatisfiedBy()

Figure 8. Composite Specification using a full logical expression.

This effectively creates an interpreter [Gang of Four] for the specification. The "language" being
interpreted allows us to describe a composite specification. For example in the example above, in
which we created a storage specification for a cargo of frozen foods, using the same parameterized
specifications as above (which would now be leaf specifications) we could now express the composite
like this
SanitaryForFoodSpecification new and:
(MaximumTemperatureSpecification newFor: -4)

If we create a few general-purpose leaf specifications, we can do a lot without custom coded
specifications. We can use Variable State [Beck] (also known as Property List) to allow ourselves to
declare attributes on the fly.

12
LeafSpecification

isSatisfiedBy(Object) : Boolean
and(Specification) : Specification
or(Specification) : Specification

Value Bound Specification


attribueName: aSymbol
value: aValue

Equal Specification GreaterThanOrEqualToSpecification LessThanOrEqualToSpecification

Figure 9. Value bound leaf specification

Placing the creation protocols on the abstract superclass, Specification, (a common practice in
Smalltalk), that same specification can now be created as follows
(Specification attributeNamed: #isSanitaryForFood equals: true) and:
(Specification attributeNamed: #temperature isLessThanOrEqualTo: -4)

To implement these additional classes, the code from CompositeSpecification moves to


ConjunctionSpecification. The DisjunctionSpecification implements this
DisjunctionSpecification >> isSatisfiedBy: aCandidateObject
^ self components contains: [:each | each isSatisfiedBy: aCandidateObject ]

Implementation of and: and or: can be completely generic, on the Specification superclass, although
in practice there are many simplifications of the result that would be desirable. The key, though is to
return a new Specification.
Specification >> and: aSpecification
^ ConjunctionSpecification with: self with: aSpecification
Specification >> or: aSpecification
^ DisjunctionSpecification with: self with: aSpecification

Comparing the alternatives for implementing specification


Each of these implementation strategies has its strengths and weaknesses.

The hard coded specification is very expressive. It can express any specification that you can represent
in the programming language that you are working with. However each specification needs a new

13
class, and you usually can not create new specifications at runtime. Also you need to know the
language to create a specification.

You can easily create new parameterized specifications at run time, and building them is easily done.
Most of the time a dialog box can capture the parameters. However you are limited to the parameters
supplied, and by the way the objects combine the parameters.

The specification interpreter represents a middle ground between the two. You get much more
expressiveness than the parameterized specification, because you can combine the leaf elements in any
logical expression you like. You can also set up the expression at run time. It is not quite as easy as the
parameterized specification to build, but a simple tool can capture many needs. You are still limited by
the leaf elements that are provided however. The specification interpreter is also a lot more effort to
build.

You may "upgrade" from one design to another, or use them in combination. For example, you may
realize you have hard-coded specifications already and wish to refactor them into parameterized
specifications. Later you may decide you need the power of the Composite Specification. Some of
your parameterized specifications can serve as leaf nodes. Multi-parameter specifications can be
broken down a bit at a time until you reach atomic, one-parameter specifications, which are the
simplest and most flexible form for the leaf nodes of a composite specification.

If you have to select from a lot of candidates on a database, then performance may well become an
issue. You will need to see how to index the candidates in some way to speed up the matching
process. How best to index will depend on your domain and on your database technology.

Subsumption
With Specification in place, there are two supplemental patterns that can provide further benefits:
Subsumption and Partially Satisfied Specifications.

So far we’ve just looked at how you test a specification against an object. However there is also a
purpose to compare specifications to each other, and to combine specifications.

This extension allows two specifications to be compared to one another. Specification B is a special
case of Specification A if and only if for any possible candidate object X, where A is satisfied by X, B
will always be satisfied by X also. If this is true, it is possible to apply any conclusion reached using B
to A, hence B can subsume A. For example, if we have two route requirements:

A: Hong Kong to Chicago

And B: Hong Kong to Chicago via Long Beach

We can find a route that satisfies B, and know that it will satisfy A, without testing A directly. B is a
special case of A, and therefore can subsume its place.

14
Subsumption

How do I compare two specifications to see if one is a special case of the other, or is substitutable for
another?

Create an operation called isSpecialCaseOf(Specification): Boolean that will answer


whether the receiver is in every way equal or more strict than the argument, and
therefore could stand in for the argument. (A complementary isGeneralizationOf
operation is convenient, also.)

People frequently want to compare two specifications without ever having a concrete candidate
object. For example, in a system that records service contracts and tries to match them to orders, we
have two sets of specifications: the specification that describes the type of service offered under the
contract; and the specification that describes the type of service being ordered. If a shipping company
had a contract with a local trucking company to deliver its containers from Long Beach to any site
within California, the specification might be:

Conditions for use of Contract:

Port must be Long Beach

Destination must be located within California

In order to deliver a shipment that is being routed through Long Beach and destined for Newport
Beach, the shipment routing system might generate a specification for contract applicability like this:

Service requirements of customer order:

Port must be Long Beach

Destination must be Newport Beach

The question becomes: Is the specification service requirements a special case of the conditions for
use of the contract? In this case it is. The contract's specification is more general than the order's
specification (is subsumed by it) and therefore this contract can be applied to the order.

Subsumption can also be used in the implementation of satisfaction, when we can characterize the
candidate object using a Specification. For example, if a Container is characterized by an attribute
called contentsSpecification, which is typed as a StorageSpecification, and a Cargo has an attribute,
storageSpecification, which is also a StorageSpecification, then we could implement isSatisfiedBy as
follows.
Cargo>>storageSpecification isSatisfiedBy: aContainer
^ aContainer contentsSpecification isSpecialCaseOf: self storageSpecification

This further decouples the Cargo from the Container.

If we had two shipments, and we wanted to know if they could be packaged together in the same
container, we would like to be able to recognize that two refrigerated cargoes with different storage
temperatures cannot be packaged together, without any reference to an actual container.

The result of the logical operators can be described in terms of subsumption. The result of an "and"
operation must subsume both of the terms. In other words, if I derive a specX
specX := specA and: specB.

Then I know that both of the following will return true


specX isSpecialCaseOf: specA

15
specX isSpecialCaseOf: specB

The result of an "or" operation must be a generalization of both terms.


specX := specA or: specB.

Therefore, both of the following will return true.


specX isGeneralizationOf: specA
specX isGeneralizationOf: specB

Implementing Subsumption
Add a method "isSpecialCaseOf(Specification) : Boolean" and a complementary
"isGeneralizationOf(Specification) : Boolean" to the Specification object. This can be implemented in
either the parameterized specification or the composite. In a parameterized specification, only two
members of the same class can be compared, and the isGeneralizationOf method must be written for
each specialized Specification. For CompositeSpecification, it can be generalized somewhat. As usual
we will illustrate it with Smalltalk. Doing this kind of thing in Smalltalk calls for Double Dispatch [Beck],
which can look a little odd to non-Smalltalkers.
Specification >> isGeneralizationOf: aSpecification
^self subclassResponsibility

NamedSpecification >> isGeneralizationOf: aSpecification


^ aSpecification isSpecialCaseOfNamedSpecification: self

Specification >> isSpecialCaseOfNamedSpecification: aNamedSpecification


"In the general case, it does not"
^ false

NamedSpecification >> isSpecialCaseOfNamedSpecification: aNamedSpecification


"Only specifications of the same name can subsume each other. Double
Dispatch again
within whatever subclasses you have, after comparing name"
^ self name = aSpecification name and: [ self
isSpecialCaseOfSpecificationOfSameName: aSpecification ]

as an example, magnitude comparisons would dispatch among themselves:


ValueBoundSpecification >> isSpecialCaseOfSpecificationOfSameName:
aNamedSpecification
^ aNamedSpecification isGeneralizationOfValueBoundSpecification: self

LessThanOrEqualToSpecification >> isGeneralizationOfValueBoundSpecification:


aValueBoundSpecification
^ aValueBoundSpecification isSpecialCaseOfLessThanOrEqualToSpecification:
self

EqualSpecification >> isSpecialCaseOfLessThanOrEqualToSpecification:


aLessThanOrEqualToSpecification
"Finally, we are comparing two leaf nodes."
^ self magnitude <= aLessThanOrEqualToSpecification magnitude

GreaterThanOrEqualToSpecification >>
isSpecialCaseOfLessThanOrEqualToSpecification: aLessThanOrEqualToSpecification
^false

And so on.

The Composite branch dispatches quite differently:


CompositeSpecification >> isGeneralizationOf: aSpecification
"True if each component is subsumed. False if any component is not
subsumed."

16
^ (self components contains: [:each | (each isGeneralizationOf:
aSpecification) not ]) not

CompositeSpecification >> isSpecialCaseOfNamedSpecification:


aNamedSpecification
"The composite isSpecialCaseOf the other Specification if any of its
components does."
^ self components contains: [: each | aNamedSpecification
isGeneralizationOf: each ]

Once this dispatching framework is built, new leaf nodes can be added by just making sure that they
implement all the messages expected within their branch.

Partially Fulfilled Specifications


The most common need is to know whether a specification is fully satisfied or fully subsumed. In
fact, if you are very interested in other matching patterns, it may be an indication that specification is
the wrong model for what you are doing. But there are at least two ways in which partial satisfaction
or subsumption does fit well into the specification model.

One is explanation of results. Using the container example above, it may be necessary not only to say
that a container does not meet spec, but to list exactly which part of the spec is not met: Is it not
refrigerated? Is it not sanitary? Both? Our example is so simple that a user could easily scan for
differences, but in a more realistic case, finding the discrepancy could be much more difficult.

Another situation that calls for partially satisfied specifications is when a specification may have to be
satisfied by two or more objects. This would typically happen when specifying requirements for a
service. If the originally selected service is only partially completed, it may be necessary to determine
what remains to be done and then select a service to satisfy the remaining portion.

Partially Satisfied Specification

You need to figure out what still must be done to satisfy your requirements.

You need to satisfy a requirement with more than one object.

You need to explain to the user why the specification was not satisfied.

Add a method "remainderUnsatisfiedBy(CandidateObject):Specification" that returns a


Specification that expresses only the requirements not met by the target object. (Best
used together with Composite Specification).

Here is an example of route selection from the shipping domain.

Original Route Specification:

• Origin: Hong Kong

• Destination: Chicago

• Stop-off: Salt Lake City (to drop off part of the cargo)

• Customs Clearance: Seattle

17
The original route was selected to satisfy this specification, spelling out a detailed itinerary of ships
and trains. According to this itinerary, the shipment was to go by train to Boise, there to be
transferred to another train to go to Salt Lake City. But, when the shipment arrives in Seattle, a
blizzard has engulfed Boise, and the train yards are temporarily shut down. It is time to select a new
route.

The problem is that the portion of the route already traversed cannot be changed. We really want to
select a new route that satisfies only those components of the original spec that have not been
satisfied by the already traversed route.

We ask the original spec for the remainder unsatisfied by the traversed route:
originalSpecification remainderUnsatisfiedBy: traversedRoute (returns a
new specification)

The new specification will look like this:

• Destination: Chicago

• Stop-off: Salt Lake City

There is one more requirement for the new route. It must start at our current location. So we add
that:
newSpecification and: (Origin: Seattle)

Which returns a specification that looks like this:

• Origin: Seattle

• Destination: Chicago

• Stop-off: Salt Lake City

We can now apply the route selection process to finding a way to fulfill these new requirements,
and we can check the result using isSatisfiedBy:. In this case, perhaps it will be shipped to
Portland and then sent on to Salt Lake. The final leg to Chicago may or may not be the same.

If the route specification is implemented as a composite, this operation is easy to implement.


Using the same iteration process used to walk the composite structure in the isGeneralizationOf:
or isSatisfiedBy: operations, you test each component:
aComponent isSatisfiedBy: anObject

and collect all the unsatisfied ones into the new specification.

Summary of the Full Specification Protocol


When all these patterns are used together, Specification as the base, CompositeSpecification to
represent more complex expressions, hard coded and parameterized Specifications as leaf nodes, with
the supplemental patterns added in, the full protocol would look something like this:

• isSatisfiedBy(Object) : Boolean

• isGeneralizationOf(Specification) : Boolean

• and(Specification) : Specification

18
• or(Specification) : Specification

• remainderUnsatisfiedBy: (Object) : Specification

In a strongly typed language you would want to ensure that the arguments to isSatisfiedBy and
remainderUnsatisfiedBy were restricted to the type of object you are working with.

Final Thoughts
Specifications have proven a valuable technique in current projects, and a technique we wished we
had used in previous work. Using a composite specification, in particular, is very capable. It is a bit of
effort to set it up, but once the building blocks are in place it can make life much easier. So far much
of our implementation experience with this pattern is in a Smalltalk/Gemstone environment, and we
will be interested to see how it applies to others. As we run into others who have used it, we are sure
we will be able pool ideas and develop this theme further.

Further Reading
Martin describes the notions of portfolio selecting its contracts in [Fowler] §9.2. Essentially this is a
use of a parameterized specification.

[Riehle] is a paper which is primarily about you can ask a superclass to create instances of subclasses
without knowing about the subclasses. To do this he uses a specification to help the creating object
choose an appropriate subclass. It includes good advice for implementing specifications for this kind
of problem.

Although we haven’t tried it, we would imagine that specifications would work well with the Shopper
pattern [Doble] to help specify the item list.

References
[Beck] Beck K, Smalltalk Best Practice Patterns, Prentice-Hall, 1997

[Doble] Doble J, Shopper, in [PloPD2], pp 143–154

[Fowler] Fowler M, Analysis Patterns: Reusable Object Models, Addison-Wesley, 1997

[Fowler, UML] Fowler M, with Scott K, UML Distilled: Applying the Standard Object Modeling
Language, Addison-Wesley, 1997

[Gang of Four] Gamma E, Helm R, Johnson R, and Vlissides J, Design Patterns: Elements of
Reusable Software, Addison-Wesley, 1995

[PloPD2] Vlissides J, Coplien J, and Kerth N (eds), Pattern Languages of Program Design 2,
Addison-Wesley, 1996

[Riehle] Riehle D, Patterns for Encapsulating Class Trees, in [PloPD2] pp 87–104

19
PLop Submission

Recurring Events
for Calendars
Martin Fowler
100031.3311@compuserve.com

I had a happy time when I lived in the South End of Boston. I had a nice apartment in an attrac-
tive brownstone building. It’s not the poshest part of town, but it was lively and a short walk from
most things I needed. I did have a few irritations, however, and one of these was street cleaning.
Now I like to have clean streets, but I also had to park my car on the street (off-street parking is
incredibly expensive). If I forgot to move my car, I got a ticket, and I often forgot to move my
car.
Street cleaning outside my old house occurs on the first and third Monday of the month between
April and October, except for state holidays. As such its a recurring event, and recurring events
have been a recurring event in my modeling career. An electricity utility I worked with sends
out their bills on a schedule based on recurring events, a hospital books its out-patient clinics on
a schedule based on recurring events, a payroll is run on a schedule based on recurring events,
indeed employees’ pay is based on rules that are often based on recurring events. This pattern
language describes how we can deal with these recurring events in a computer system, so that
the computer can figure out when various events occur.
An overview of the language
We begin by looking at where the responsibility should lie for working them out. Schedule sug-
gests that we define a specific class to handle the understanding of recurring events, so any ob-
jects that needs to deal with them (whether a doctor or a street) can do say by being given a
schedule. It can be tricky to see what this schedule object looks like, however, especially if you
tend to think of objects in terms of their properties. Schedule’s Interface allows you to think
about what you want from the schedule rather than how you set up a schedule.
With the interface in hand, we can now begin to think about schedule’s properties. A schedule
needs to work out which events (there may be several) occur on which days. Schedule Element
does this by giving a schedule a schedule element for each event, with the ‘when’ part delegated
to a temporal expression. A temporal expression has an individual instance method [Fowler] to
work out whether a day lies within the temporal expression or not. At this point we separate the
(simple) event matching from the (tricky) time matching.
We could come up with some language for defining temporal expressions, or some powerful
class that can be used to handle the rather wide range of temporal expressions that we need to
deal with. However I’m not inclined to develop a complex general solution if I can think of a
simple solution that solves my problem. Such a simpler solution is to think of some simple tem-
poral expressions, and define subclasses of temporal expression for them. Day Every Month
handles such expressions as ‘second monday of the month’. Range Every Year deals with such
things as ‘between 12 April and 4 November’ each year. I can then combine these temporal ex-

© Martin Fowler 1
Schedule PLop Submission

pressions with Set Expression to develop more complex cases, such as my old street cleaning.
Using set expressions in this way is a simple application of interpreter [Gamma et al].

Name Problem Solution


You need to model someone having Create a schedule object for the doctor
Schedule events which occur on certain recur- which can say which days an event
ring days. occurs on
Imagine a schedule object is already
You find it hard to see what schedule created and consider how you would
Scheduleís Interface
should look like. use it. Determine the key operations in
its interface.
Schedule Element with event and tem-
You need to represent recurring days poral expression. Temporal expres-
Schedule Element
without enumerating them sion has an individual instance method
to determine if dates match.
Use a day every month temporal
You need to represent statements of
Day Every Month expression with a day of the week and
the form 2nd Monday of the Month
a count
Use a range every year temporal
You need to represent statements of
Range Every Year expression with a day and month at
the form 14 March till 12 October
the start and end
You need to represent combinations of Define set combinations for union,
Set Expression
temporal expressions intersection and difference
Table 1: Table of Patterns

Schedule

My friend Mark is a physician in a London hospital. On the first and third monday of the month
he has a gastro clinic. On the second wednesday of the month he has a liver clinic. (Actually I
don’t know what his real schedule is and I’m making this up, but I’m sure you’ll forgive me.)
His boss may have a liver clinic on the second and fourth Tuesdays of a month, and golf on every
monday (hospital consultants seem to do a lot of research on golf courses, I guess the swing is
good for their technique).
One way of representing this might be to consider that Mark has a set of dates for each event
(Figure 1). This supports our needs, since we can now easily tell the dates of Mark’s clinics, but
it comes with its own problems.

Figure 1. OMT[Rumbaugh et al] object model for a person with an association for each event.

2 Recurring Events for Calendars


PLop Submission Schedule

The first problem is that when we have an association for each event that Mark has, we have to
modify the model for each change we make. Should our doctors get a new kind of clinic, or take
up gliding, we have to add an association, which implies changing the interface of the person
class.

Figure 2. Person with a qualified association to date

Figure 2 deals with this problem by using a qualified association. It defines a new type, event,
and says that each person has a set of dates for each instance of event (qualified association are
talked about in more detail in [Fowler] as keyed mappings, they correspond to Smalltalk dictio-
naries or C++ STL maps). Now whenever we get some new clinic, all we have to do is create a
new instance of event, which deals well with that problem. (For the purposes of this paper, event
is just a string representing some activity, like a clinic or golf game, but in practice it can get
rather more involved.)
Another problem is to ask how we would set up the dates? Do we actually want to imply that
we have to assert the individual dates for the person. We would prefer to just say ‘every second
monday’. Bear with me on that one, I’ll come to it later.
Figure 2 is certainly heading in the right direction, but I’m not comfortable with the responsi-
bility on person. There are many questions you might want to ask regarding the dates, and load-
ing all that stuff onto person is awkward, because person usually has enough to do. Also you
will find other objects that might have similar behavior, such as my street.

Figure 3. Using schedule as a separate object.

So I’m inclined towards Figure 3 which puts all the responsibility of tracking dates and events
on a separate type: schedule. Now if we want some type to have this behavior we just give them
a schedule.

Recurring Events for Calendars 3


Schedule’s Interface PLop Submission

Schedule’s Interface

What kind of questions are we going to ask the schedule? Schedule is one of those objects that
can really trip up people like me who have come from a data modeling / database background.
This is because that data modeling training makes us want to look at schedule in terms of its
properties. Providing we are using taking a conceptual perspective, and not getting hung up on
what is stored and what is calculated; this is not too much of a problem, at least for information
systems. I find that schedule is one of the exceptions, for whenever I have worked with it I get
frazzled.
Thinking of an object through its properties is a very natural way to think of something. It allows
us both to query and change the object easily. When frazzling occurs, however, then that is a
sign to try another tack. At this point I look at how I might use a schedule once I have one. I
forget about its internal structure, I also forget about how I set one up. Both of those are second-
ary to using a completed schedule, so I just assume its set up by magic and ask myself what I
want it to do.
I doubt if I would really want Mark’s schedule to tell me all the days he is due for a gastro clinic.
I might want to know which days he was booked this month, but not from the epoch to the end
of time. So one question would be Occurrences (Event, DateRange) which would return of set of
dates. Another would be to find out when his next gastro clinic is scheduled, this might be from
today, or from another date: nextOccurrence (Event, Date). A third would be to determine whether
an event would occur on a given date: isOccurring(Event, Date). Naturally you would examine
your use cases to come up with some more, but we don’t want the full list, merely the core items
(Listing 1). As it is these are not minimal, in that two could be defined on top of one of them.
Getting a few of them gives me a better feeling of how schedule will be used. Now I have a sense
of where to go next because I know what I want to aim at next.

class Schedule {
public boolean isOccurring(String eventArg, Date aDate)
public Vector dates (String eventArg, DateRange during)
public Date nextOccurence (String eventArg, Date aDate)
};

Listing 1. Java[Arnold & Gosling] interface for schedule

Schedule Element

With some picture of an interface we can now begin to think about how a schedule is created.
The main point of a schedule is that it tracks a correspondence between events and dates, and
does so in such a way that the dates can be specified by some expression. Since we have many
events, and each event has its own expression, this leads me to a schedule containing elements,
each of which links an event to an expression that determines the appropriate dates.
Using properties is not a good way to model expressions, so again I think of an interface. This
expression should have some way of telling whether a particular date is true or not. Thus each
instance of this temporal expression will have an Individual Instance Method1 that takes a date

4 Recurring Events for Calendars


PLop Submission Day Every Month

and returns a boolean (Figure 4). I will look at implementing this a little later, again sorting out
the interface is the first important thing.

Figure 4. Schedule Element

Example: Mark has a gastro clinic on the first and third monday of the month,
and a liver clinic on the second wednesday. This would be represented by a
schedule with two schedule elements. One schedule element would have an
event of ‘gastro clinic’ and a temporal expression that would handle the first
and third monday of the month. The other schedule element would have an
event of ‘liver clinic’ and a temporal expression that would handle the second
wednesday of the month.
Here the dynamic behavior is getting interesting. The core behavior is that of responding to isOc-
curring.The schedule delegates the message to its elements. Each element checks the event for a
match and asks the temporal expression if the date matches. The temporal expression thus needs
to support a boolean operation includes (Date). If the event matches and the temporal expression
reports true then the element replies true to the schedule. If any element is true then the schedule
is true, otherwise it is false. (Figure 5, and Listing 2)

The patterns have brought us to a point where the problem of considering the event is separated
from that of forming the temporal expression. All we need to do know is figure out how to form
the temporal expression, and all is dandy.

Day Every Month

So far we have a temporal expression which can say true or false for any given day. Now the
question is ‘how do we create such thing?’ The conceptually simplest idea is to have a block of

1. An Individual Instance Method [Fowler] is an operation whose method is different for


each instance of the class. There are several ways of implementing it: one of which is the
strategy pattern [Gamma et al]

Recurring Events for Calendars 5


Day Every Month PLop Submission

a Schedule a Temporal
a Schedule Element Expression
A schedule is asked to check an event isOccurring
on a date.
isOccurring
It asks each schedule element to check
the event and date.
The schedule element sees if the event includes
is the same and gets the temporal
expression to test the date.
If any schedule element replies true
then so does the schedule, otherwise it
replies false

Figure 5. Interaction diagram to show how a schedule finds out if an event occurs on a date.

class Schedule {
public boolean isOccurring(String eventArg, Date aDate) {
ScheduleElement eachSE;
Enumeration e = elements.elements();
while (e.hasMoreElements()) {
eachSE = (ScheduleElement)e.nextElement();
if (eachSE.isOccurring(eventArg, aDate))
return true;
}
return false;
}; …
class ScheduleElement {
public boolean isOccuring(String eventArg, Date aDate) {
if (event == eventArg)
return temporalExpression.includes(aDate);
else
return false;
};

Listing 2. Java method to determine if an event occurs on a date

code for each object, conceptually simple but rather awkward to implement. We could develop
some interpreter that would be able to parse and process a range of expressions that we might
want to deal with. This would be quite flexible, but also pretty hard. We could figure out some
way to parameterize the object so that all possible expressions could be formed by some com-
bination of properties. This may be possible, it certainly would be tricky.
Another approach is to look at some of kinds of expression that this system has to deal with, and
see if we can support them with a few simple classes. The classes should be as parameterized as
possible, but each one should handle a particular kind of expression. Providing they all respond
to includes, this will work. We may not be able to cover everything that we can conceive of, at
least not without creating a new class, but we may well be able to cover pretty much everything
with a few classes.
The first such animal is to cope with phrases like “first monday of the month”. In a phrase such
as this we have two variables: the day of the week, and which one we want in the month. So our

6 Recurring Events for Calendars


PLop Submission Day Every Month

day in the month temporal expression has these two properties (Figure 6). Internally includes
uses these to match the date (Listing 3).

Figure 6. Day in month temporal expression

abstract class TemporalExpression {


public abstract boolean includes (Date theDate);
}

class DayInMonthTE extends TemporalExpression{


private int count;
private int dayIndex;
public DayInMonthTE (int dayIndex, int count) {
this.dayIndex = dayIndex;
this.count = count;
};
public boolean includes (Date aDate) {
return dayMatches (aDate) && weekMatches(aDate);
};
private boolean dayMatches (Date aDate) {
return aDate.getDay() == dayIndex;
};
private boolean weekMatches (Date aDate) {
if (count > 0)
return weekFromStartMatches(aDate);
else
return weekFromEndMatches(aDate);
};
private boolean weekFromStartMatches (Date aDate) {
return this.weekInMonth(aDate.getDate()) == count;
};
private boolean weekFromEndMatches (Date aDate) {
int daysFromMonthEnd = daysLeftInMonth(aDate) + 1;
return weekInMonth(daysFromMonthEnd) == Math.abs(count);
};
private int weekInMonth (int dayNumber) {
return ((dayNumber - 1) / 7) + 1;
};

Listing 3. Selected Java code for a day in month temporal expression.


Java’s date class represents day of the week using an integer range 0–6 for sunday–saturday. I have
used the same convention.

Example: Mark has a gastro clinic on the second monday of the month. This
would be represented using a day in month temporal expression with a day of
the week of monday and a count of 2. Using Listing 3 this would be DayIn-
MonthTE (1, 2).

Recurring Events for Calendars 7


Range Every Year PLop Submission

Example: Mark also has a liver clinic on the last friday of the month. This
would be represented using a day in month temporal expression with a day of
the week of friday and a count of -1.

Range Every Year

Some events can occur in a particular range in a year. I used to work in a British government
establishment where turned the heating on and off at certain days in the year (they didn’t re-
spond to anything as logical as temperature). To handle this we can use another subtype of tem-
poral expression, this one can set up with start and end points, using a month and a day (Figure
7). We can create one of these expressions several ways, depending on whether we need date
precision or not (Listing 4). A common need is to indicate just a single month, as we shall see
later. The includes method now just looks at the date and tests whether it fits within that range
(Listing 5).

Figure 7. Range each year temporal expression.

public RangeEachYearTE (int startMonth, int endMonth,


int startDay, int endDay) {
this.startMonth = startMonth;
this.endMonth = endMonth;
this.startDay = startDay;
this.endDay = endDay;
};
public RangeEachYearTE (int startMonth, int endMonth) {
this.startMonth = startMonth;
this.endMonth = endMonth;
this.startDay = 0;
this.endDay = 0;
};
public RangeEachYearTE (int month) {
this.startMonth = month;
this.endMonth = month;
this.startDay = 0;
this.endDay = 0;
};

Listing 4. Creating a range each year temporal expression


If no date is specified it is set to zero.

8 Recurring Events for Calendars


PLop Submission Set Expression

public boolean includes (Date aDate) {


return monthsInclude (aDate) ||
startMonthIncludes (aDate) ||
endMonthIncludes (aDate)
};
private boolean monthsInclude (Date aDate) {
int month = aDate.getMonth();
return (month > startMonth && month < endMonth);
}
private boolean startMonthIncludes (Date aDate) {
if (aDate.getMonth() != startMonth) return false;
if (startDay == 0) return true;
return (aDate.getDate() >= startDay);
}
private boolean endMonthIncludes (Date aDate) {
if (aDate.getMonth() != endMonth) return false;
if (endDay == 0) return true;
return (aDate.getDate() <= endDay);
}

Listing 5. The includes method for RangeEachYearTE

Example: The heating is turned off on the 14 April and turned on the 12th
October. This could be represented as a range each year temporal expression
with a start month of April, start date of 14, end month of October, and end
date of 12. Using RangeEachYearTE it would be set up with RangeEachYearTE
(3, 9, 14, 12)1

Set Expression

The temporal expressions above provide some ability to represent the kinds of problem we deal
with, but we can greatly enhance their abilities by combining them in set expressions (Figure 8
and Listing 6). Set expressions require three classes: union, intersection, and difference. Each
set expression holds a number of components and processes them in the appropriate way. If we
make these three classes composites[Gamma et al], we can put set expressions within set ex-
pressions; which allows us to build quite complex expressions. This is a useful technique when-
ever you want to combine some kind of selection expression.2
Example: The US holiday of memorial day falls on the last monday in May.
This can be represented by an intersection temporal expression. Its elements
are a day in month with count -1 and day of week of monday, and a range ev-
ery year with start and end month of may.

1. Yes the months are correct. Java’s date class represents months with an integer of range
0–11.
2.You can also think of these as boolean operations, but I find thinking of sets of dates more
natural — and difference is easier than using and and not.

Recurring Events for Calendars 9


Set Expression PLop Submission

Figure 8. Set expressions

class UnionTE…
public boolean includes (Date aDate) {
TemporalExpression eachTE;
Enumeration e = elements.elements();
while (e.hasMoreElements()) {
eachTE = (TemporalExpression)e.nextElement();
if (eachTE.includes(aDate))
return true;
}
return false;
};
class IntersectionTE…
public boolean includes (Date aDate) {
TemporalExpression eachTE;
Enumeration e = elements.elements();
while (e.hasMoreElements()) {
eachTE = (TemporalExpression)e.nextElement();
if (!eachTE.includes(aDate))
return false;
}
return true;
};
class DifferenceTE …
public boolean includes (Date aDate) {
return included.includes(aDate) &&
!excluded.includes(aDate);
};

Listing 6. Includes methods for the set expressions

10 Recurring Events for Calendars


PLop Submission Set Expression

IntersectionTE result = new IntersectionTE();


result.addElement(new DayInMonthTE(1,-1));
result.addElement(new RangeEachYearTE (4));
return result;

Listing 7. Code for creating a temporal expression for memorial day.

Example: Street cleaning occurs from April to October on the first and third
mondays of the month, excluding state holidays. The representation is rather
tricky to describe in words, so take a look at Figure 9, the code is in Listing 8.

Figure 9. Instance diagram showing objects to represent a street cleaning schedule

public DifferenceTE streetCleaning() {


UnionTE mon13 = new UnionTE();
mon13.addElement(new DayInMonthTE(1,1));
mon13.addElement(new DayInMonthTE(1,3));
IntersectionTE nonWinterMons = new IntersectionTE();
nonWinterMons.addElement(mon13);
nonWinterMons.addElement(new RangeEachYearTE (3,9));
return new DifferenceTE(nonWinterMons, maHolidays());
}

Listing 8. Java code for the street cleaning schedule

Recurring Events for Calendars 11


Set Expression PLop Submission

Using set expression in this way is a use of the Interpreter1 pattern. It is interesting to note that
I didn’t realize this until Ralph Johnson pointed it out to me. In my mind interpreters are for lan-
guages, and languages are complicated. This is simple, and yet the interpreter pattern still works
very well, so well that it is easy to use it without realizing it, which I guess is the sign of a good
pattern!

Going Further
Time and the PLoP limits bring to a halt here, however I should not stop without indicating some
further patterns that need to be developed.
❍ When holidays occur they may cancel out the recurring event (as occurs in street
cleaning). But a substitute may occur, such as do it the following Monday, or the next
Thursday.
❍ The patterns here concentrate on events, but they can also be used to handle defining
days as working days, or further ways to classify days. This may be as simple as every
Monday to Friday is a working day.
❍ Some some events should not occur on the same day. Can we do something about this,
or just trust our ability to write good temporal expressions?
❍ How do we handle a schedule such as four weeks on two weeks off?

References
[Arnold & Gosling] Arnold, K. and Gosling, J. The Java Programming Language, Addison-Wesley,
Reading, MA, 1996.
[Fowler] Fowler, M. Analysis Patterns: reusable object models, Addison-Wesley, Reading MA, 1997.
[Gamma et al] Gamma, E., Helm, R., Johnson, R. and Vlissides, J. Design Patterns: elements of reusable
object-oriented software, Addison-Wesley, Reading, MA, 1995.
[Rumbaugh et al] Rumbaugh, J., Blaha, M., Premerlani, W., Eddy, F. and Lorensen, W. Object-Oriented
Modeling and Design, Prentice Hall, Englewood Cliffs, NJ, 1991.

1. An interpreter defines a representation for the grammar of a language together with an


interpreter that interprets sentences in that language [Gamma et al].

12 Recurring Events for Calendars


Dealing with
Properties
Martin Fowler
fowler@acm.org

A
lmost every object you create needs properties: some statement about the object. A
person may have a height, a company may have a CEO, a flight may have a flight
number. There are a number of ways to model properties. In this article I will explore
some of these ways and when you may want to use them. I’ve often seen patterns touch on
this subject, but they usually only cover part of the picture. Here I want to cover the issue
more broadly to give a better discussion of the options.

The most common, and the simplest case is to use a Fixed Property, that is just declare the
attribute on the class. In the vast majority of cases that is all you need to do. Fixed properties
begin to fail when you have a large amount of them, or you need to change them frequently,
possibly at run time. These forces lead you to the varieties of Dynamic Property. All dynamic
properties have the quality of a parameterized attribute where to query a property you need to
use a query method with a parameter. The simplest of these is the Flexible Dynamic Property
where the parameter is just a string. This makes it easy to define and use properties, but is
difficult to control. If you need that control you can use a Defined Dynamic Property where
your parameters must be instances of some class. A further step of control allows you to
strongly type your dynamic property with a Typed Dynamic Property.

As your property structures get more involved, you should consider making them Separate
Properties, which makes the property an object in its own right. If you need multi-valued
properties you can consider a Typed Relationship. The most complex example in this theme is
where you want rules to control what kinds of objects have what kinds of properties – this
needs a Dynamic Property Knowledge Level.

Another variety of property entirely is the Extrinsic Property, a pattern you use if you want to
give an object a property, but not alter its interface to support it.

Problem Solution Name page

Give it a specific attribute for that fact.


This will translate to a query method
Fixed Property 4
and probably an update method in a
programming language.

© Martin Fowler 1997 1


Provide a parameterizable attribute
which can represent different properties Dynamic Property 4
depending on the parameter

Provide an attribute parameterized with


a string. To declare a property just use Flexible Dynamic Property 5
the string.

Provide an attribute parameterized with


an instance of some type. To declare a
Defined Dynamic Property 7
property create a new instance of that
type

Provide an attribute parameterized with


a instance of some type. To declare a
property create a new instance of the Typed Dynamic Property 9
type and specify the value type of the
property.

How do you represent a fact about an Create a separate object for each
object, and allow facts to be recorded property. Facts about that property can Separate Properties 10
about that fact then be made properties of that object.

Create a relationship object for each


How do you represent a relationship link between the two objects. Give the
between two objects? relationship object a type object to
Typed Relationship 14
(How do you represent multi-valued indicate the meaning of the
dynamic properties?) relationship. (The type object is the
name of the multi-valued property.)

How do you enforce that certain kinds Create a knowledge level to contain the
Dynamic Property Knowledge
of objects have certain properties when rules of what types of objects use which 16
Level
you use dynamic properties? types of properties

How do you give an object a property Make another object responsible for
Extrinsic Property 18
without changing its interface? knowing about the property.

What is a property?

This is not a silly question. When people bandy around the term ‘property’ they can mean
many different things. To some a property is an instance variable or data member of a class.
To others they are kind of thing that goes in a box in a UML diagram. So before I start this
article I have to define my usage of the word.

For my purposes a property is some information about an object that you can obtain by a query
method. It may be a value type (such as int in Java) or an instance of a class. You may be able
to update the property, but not necessarily. You may set the property when you create the
object, but again not necessarily. The property may be stored as an instance variable or data
member, but it does not have to be. The class may get the value from another class, or go
through some further calculation. I am, therefore, taking an interface view of properties rather
than an implementation view. This is a regular habit of mine in design: for me the essence of
object-orientation is that you separate interface from implementation, and make interface
more important.

© Martin Fowler 1997 2


Fixed Properties

Fixed properties are by far the most common kind of properties that we use. A Fixed Property is
declared in the interface of the type. It gives the name and the return type for the property.
Figure 1 shows properties modeled in UML, Listing 1 shows how the query methods for these
properties would show up in Java. I’ve picked the example to show that this discussion applies
equally well to UML attributes as well as UML associations. It also applies to calculated values
(age) as well as those that are reasonably stored data (date of birth).

Person
date of Birth : Date 0..1
Company
age: int employer
height: Quantity

Figure 1. A Person modeled with fixed properties


class Person {
public Date getDateOfBirth();
public int getAge();
public Quantity getHeight();
public Company getEmployer();
public void setDateOfBirth (Date newDateOfBirth);
public void setEmployer (Company newEmployer);

Listing 1. Java operations for Figure 1

Query operations usually follow some naming convention. In smalltalk you always name the
query after the name of the property (dateOfBirth). C++ never had a fixed convention, some
people just named it after the property, others used the 'get' convention (getDateOfBirth).
Java started with no particular convention but now most people adopt the get convention.
Personally I find the ‘get’ irritating when you read code so I would prefer to leave it out, but
the Java style is to use the get, so I use it now. You should ensure that you follow the same
convention whether you are using stored or derived values. Clients of the person class should
not know or care whether age is stored or derived.

The presence of modifier operations depends on whether you want the values to be directly
modified. If you do then you will provide a modifier operation according to some naming
scheme, eg setDateOfBirth(Date). Different conventions exist as to the return value. You can
return the new value of the property (Date), the object being modified (Person), or nothing
(void). I prefer to return void on modifiers, to help make clear the difference between a
modifier and a query.

© Martin Fowler 1997 3


Fixed Property
How do you represent a fact about an object?
Give it a specific attribute for that fact. This will translate to a query method
and probably an update method in a programming language.
3 Clear and explicit interface
7 Can only add properties at design time

You may wish to provide arguments to the constructor for properties. Typically you want to
set enough properties in the constructor so that you construct a well-formed class.

Properties that you don’t want to be modified directly should not have a modifier operation.
This might be the case for the age property, if you only want that determined by calculation
from the date of birth. It also would be the case for an immutable property: one that does not
change for the lifetime of the class. When you think of making a property immutable,
remember to take human error into account. While the date of birth is an immutable property
for humans in the real world, you might make a mistake typing into a computer system, and
thus make it mutable. Software often models what we know of the world, rather than the
world itself.

Fixed properties are by far the most common form of properties that you will come across.
They are that way for good reasons: they are simple and convenient to use. You should use
fixed properties as your first and most common choice for representing properties. In this
paper I am going to give a lot of alternatives to fixed properties. For certain situations these
alternatives are better, but most of the time they are not. Remember that as we go through the
alternatives. I use fixed properties 99% of the time. Other varieties are more complex, which is
why I'm spending most of this paper on them — and also why I prefer not to use them!

Dynamic Properties

The key thing about fixed properties is that you fix them at design time, and all instances at
run time must follow that decision. For some problems this is an awkward restriction. Imagine
we are building a sophisticated contact system. There are some things that are fixed: home
address, home and work phone, email. But they’re all sorts of little variations. For someone
you need to record their parent’s address, another has a day work and evening work numbers.
It’s hard to predict all these things in advance, and each time you change the system you have
to go through compiling, testing, and distribution. To deal with this you need to use dynamic
properties.

Dynamic Property
How do you represent a fact about an object?
Provide a parameterizable attribute which can represent different properties
depending on the parameter
3 Can add properties at run time
7 Unclear interface

There are several variations on dynamic properties, each of which make different trade-offs
between flexibility and safety. The simplest approach is Flexible Dynamic Properties. The

© Martin Fowler 1997 4


essence of this pattern is that you add a qualified association to the person whose key is a
simple value, usually a string (see Figure 2 and Listing 2). If you want to add a vacation
address to a person Kent, you just use the code in Listing 3. You don’t need to recompile the
person class. You could even build a GUI or a file reader that would add properties without
recompiling the client either.

value
Person String Object
1

Figure 2. UML model for Flexible Dynamic Properties


class Person {
public Object getValueOf(String key);
public void setValueOf(String key, Object value);

Listing 2. Java methods for Figure 2


kent.setValueOf(“VacationAddress”, anAddress);
Address kentVactation = (Address) kent.getValueOf(“VacationAddress”)

Listing 3. Using dynamic properties

Said like that, you might wonder why anyone would ever use fixed properties, since dynamic
properties such as this give you so much more flexibility. Of course there is a cost, and it lies in
the reduction of the clarity of the dependencies between parts of the software. It is all very
well adding a vacation address property to a person, but how do you know to get it back again?
With fixed properties you can just look at the interface of person and see the properties. The
compiler can check that don’t ask an object to do something it doesn’t understand. With a
dynamic property you cannot do any design-time checking. Furthermore the interface of
person is harder to see. Not just do you look at Person’s declared interface – you also have to
find the dynamic properties, which will not be present in the class interface. You have to find
that part of the code that sets the property (which usually will not be in the Person class at all)
and dig it out.

Flexible Dynamic Property


How do you represent a fact about an object?
Provide an attribute parameterized with a string. To declare a property just
use the string.

Not just is the property hard to find, it also creates a nightmare dependency. With fixed
properties the client code has a dependency to the person class – a dependency that is easy to
keep track of. If you change the name of the property the compiler will let you know, and tell
you what code you need to change to fix things. But the Flexible Dynamic Property creates a
dependency into some arbitrary piece of code. It could be code that belongs to a class that is
not even visible to the client. What happens if someone changes the key string? What
happens if someone changes the type of object they put into the key string? Not just can the
compiler do nothing to help you, you don’t even know where to start looking for potential
changes.

Flexible Dynamic Properties show this problem at it’s most extreme. The property could be
created at design time by any client of Person. If another client of person uses that same

© Martin Fowler 1997 5


property you have a dependency between two classes that is very hard to find. Furthermore
properties can be added at run time by reading a file or by a GUI. It is impossible to find out,
even at run time, what are the legal dynamic properties for a person. True you can ask a
person if it has a property for vacation address – but if there isn’t one does that mean that that
person does not have a vacation address, or does it mean that there is no such property as
vacation address? And if it has no such property now, that doesn’t mean it won’t have one a
few seconds later.

Another key disadvantage of flexible dynamic properties is that it is difficult to substitute them
for operations. One of the key advantages of encapsulation is that a client that uses a property
cannot tell whether it is stored as part of an object’s data, or computed by a method. This is a
very important part of the object approach. It allows you not just a regular interface for both
purposes, but also to change your mind without the client knowing. In the presence of
subtyping you can even have a supertype store the property and subclasses compute or vice
versa. However if you want to use dynamic properties the only way you can change stored data
to a calculation is to put a specific trap in the general accessor for the dynamic property along
the lines of Listing 4. This code is likely to be brittle and awkward to maintain.
class Person {
public Object getValueOf (String key) {
if (key = “vacationAddress”) return calculatedVacationAddress();
if (key = “vacationPhone”) return getVacationPhone();
// else return stored value…

Listing 4. Replacing a dynamic property with an operation

Other forms of dynamic property help you solve some of these problems but not all. The
essential disadvantage of a dynamic property is that you lose the clear interface and all design-
time checking. Different approaches to dynamic properties give you different abilities to do
run-time checking. If you need dynamic properties, and there are certainly situations when
you do, then you just have to give up design time checking and a explicit design time
interface. The only question is how explicit an interface and how much checking you can do
at run time. With Flexible Dynamic Properties you don’t get any of either.

You find dynamic properties often in databases because it is often a pain to change the
database schema, especially if there would be a lot of data to migrate. Interfaces of distributed
components, such as in CORBA, also often use dynamic properties for a similar reason. There
are a lot of distant clients using the interface, so you are reluctant to change it. In both of
these cases it is not so much a distinction between compile-time and run-time, as much as a
distinction between design-time and production.

If all you are doing is displaying and updating information via a GUI, and the code never
makes a fixed reference to the keys (i.e. you never see code like Listing 3), then you are pretty
safe with a Flexible Dynamic Property. This is because you have not set up a nasty dependency
to some arbitrary string as a key. Otherwise you should consider one of the other approaches
to dynamic properties.

The first step towards more run-time checking is the Defined Dynamic Property. The key
difference between a defined as opposed to a flexible dynamic property is that the key used by
the dynamic property is no longer some arbitrary string, but is now an instance of some class
(Figure 3).

© Martin Fowler 1997 6


value
Contact
Person Object
Type
0..1

Contact Type

Figure 3. A Defined Dynamic Property

On the face of it using defined dynamic property does not change much. Indeed the code
interface is almost identical (Listing 5 and Listing 6). But now the choice of keys is no longer
entirely arbitrary, it is limited by the instances of contact type. Of course this still allows you to
add properties at run time – you just create a new contact type. However now there is at least
somewhere someone can look to get a list of potential keys without having to trawl through
the program text. Any keys added at design time can be collected in a loader routine in the
contact type class. You can easily provide services to find out the legal keys at run time.
class Person {
public Object getValueOf(ContactType key);
public void setValueOf(ContactType key, Object value);

Listing 5. Java interface for Figure 3


class ContactType {
public static Enumeration instances();
public static boolean hasInstanceNamed(String name);
public static ContactType get(String name);

Listing 6. Services for a defined property type

In particular you can now set up some checking to prevent errors due to someone asking for a
dynamic property that does not exist as in Listing 7. I’m throwing an unchecked exception
here because I consider that the precondition for get() is that the client provides a legal name
for a contact type. The client can always fulfill this responsibility by using
hasInstanceNamed(), but most of the time client software will hang on to contact type
objects, not strings.

Defined Dynamic Property


How do you represent a fact about an object?
Provide an attribute parameterized with an instance of some type. To
declare a property create a new instance of that type

Usually the contact types will be held in a dictionary, usually indexed by a string. This
dictionary could be a static field of contact type, but I prefer to make it a field on a Registrar.

Removing a contact type still has awkward consequences. In java the dynamic properties
would still be present on those objects that had them, unless you write some complicated
clean up code. I usually make it a rule to never delete the keys for a Defined Dynamic
Property. If you want to use a new name you can easily alias the contact type by giving it one
name but placing it in the defining dictionary several times.

© Martin Fowler 1997 7


class ContactType {
public static ContactType get(String name) {
if (! hasInstanceNamed (name)) throw new IllegalArgumentException(“No
such contact type);
// return the contact type
}

// use with

Address kentVactation =
(Address) kent.getValueOf(ContactType.get(“VacationAddress”));

Listing 7. Checking use of legal contract types

At this point you might be wondering about what this has to do with conceptual modeling,
after all I am writing a lot of code and discussing design trade-offs. This is an important
conceptual issue because the conceptual choice you make affects the implementation options
you have. If you choose to use flexible dynamic attributes in your conceptual model, you are
making it pretty hard to use either defined dynamic attributes or fixed attributes in your
implementation. One of the reasons you do conceptual models is to explore what is fixed and
what is changeable in your users’ concepts. If total flexibility was my only goal then I would
always use Figure 4. With this I can model any situation in the world. But this model is not
very useful. Its uselessness comes from the fact that it does not indicate what is fixed. When
you are doing a conceptual model you need to be aware of how your choices affect things in
implementation – otherwise you are abdicating your responsibility as a modeler.

I often find that people discover dynamic properties, and then want to use them everywhere.
The flexibility is so great, they get all the extendibility they ever want. Yes sometimes you
need dynamic properties. but never forget there is a price. Only use them when you really
need them. After all it is easy to add them later if you have to.

linked to
Object

Figure 4. A model that can model any domain uselessly.

The Defined Dynamic Property allows you to indicate rather more about what properties you
have. These properties are still untyped. You cannot enforce that the value of the vacation
address in Figure 3 is an address. You can do something about that by using a Typed Dynamic
Property.

© Martin Fowler 1997 8


value
Contact
Person Object
Type
0..1

1..[
{The set of types for a value at a
contact type must include the value
type of that contact type} Type

value type 1

Contact Type

Figure 5. Model for typed dynamic property using qualified associations

A typed dynamic property adds type information to the defined dynamic property (Figure 6 and
Figure 5 ). Here the instances of contact type do not just indicate what properites the person
has, they also indicate the type of each property. The type constrains the value, along the lines
of Listing 9.
class Person {
public Object getValueOf(ContactType key);
public void setValueOf(ContactType key, Object value);
class ContactType {
public Class getValueType();
public ContactType (String name, Class valueType);

Listing 8. Operations for typed dynamic properties


class Person {
public void setValueOf(ContactType key, Object value) {
if (! key.getValueType().isInstance(value))
throw IllegalArgumentException (“Incorrect type for property”);
// set the value

Listing 9. Doing the type checking

Doing type checking like this can help to avoid errors, but it still is not as clear as fixed
properties. The checking is at run time, not at design time, and is therefore not as effective.
Still it is better than no checking at all, particularly if you are used to a strongly typed
environment.

Typed Dynamic Property


How do you represent a fact about an object?
Provide an attribute parameterized with a instance of some type. To declare
a property create a new instance of the type and specify the value type of the
property.

As we delve deeper into dynamic properties, we find richer examples of reflection, an


architectural pattern which appears when we get runtime objects that are able to describe
themselves. [POSA] discusses reflection in much more detail than I intend to go into here.

© Martin Fowler 1997 9


Dynamic properties provide a reflective capability, even in those languages that don’t support
reflection themselves. Even with a language that does provide some reflection, the reflection
of dynamic properties is more focused – so you can provide an easier to use interface.

Using all of those qualified associations can get rather hard to follow. Another way of
providing typed dynamic properties is to use the separate property pattern. The essence of the
separate property pattern is that it makes the property an object in its own right (Figure 6 and
Listing 10). You can get hold of the properties of a person, and then with each property get
value and type information.

Separate Properties
How do you represent a fact about an object, and allow facts to be recorded about
that fact
Create a separate object for each property. Facts about that property can
then be made properties of that object.

Separate properties and qualified associations are two alternatives that are always available for
dynamic properties. So far I’ve described flexible and defined dynamic properties with
qualified associations because the qualified association presents a much easier interface to use.
You can use flexible and defined dynamic properties with separate properties if you wish,
although I’m not going to go into that here. As we get to the complexity of typed dynamic
properties and onwards the separate property style becomes more of an advantage.

value type
Contact Type Type
[ 1
1 index 1..[

[ [
[
value
Person Contact Property Object
[ 1 1

{The value's set of types must


{A person has up to one include the property's contact
contact property for each type's value type}
contact property type}

Figure 6. Model for typed dynamic property, using a separate property


class Person {
public Enumeration getProperties();

class ContactProperty {
public Object getValue();
public Class getType();
public ContactType getIndex();

Listing 10. Operations for typed dynamic properties using separate properties

Separate properties and qualified associations are not mutually exclusive. You can easily
provide both interfaces at the same time. This way you get the advantages of both. Of course
that makes the interface more complex, so think first about what the clients of person need.
Give them the interface they need, don’t make it over complex. But if they need both

© Martin Fowler 1997 10


qualified associations and separate properties, then that is a reasonable option. I would
normally always use qualified associations for the value, but it may not make as much sense for
the type.

You can also consider the interface/implementation differences here. In this paper I want to
concentrate on the conceptual – which maps to the interface of software rather than its
implementation. But it is worth mentioning that you can provide a qualified association
interface while using separate object in the implementation. You are only using separate
properties in the interface if a client of person can obtain a contact property object. Often it is
useful to hide the separate property to simplify the interface for the client.

One of the big advantages of the Separate Properties is that it allows you put information
about the property in the property. Such information might include who determined the
property, when it was determined, and the like. The Observation pattern in [Fowler AP §3.5]
build upon this theme in some depth. Much of what I’ve described there in terms of
observations is worth considering if you need separate properties. (I see the observation
pattern as a use of separate properties.)

You might be wondering at the contrast between separate properties (a pattern) and qualified
associations (a UML modeling construct). You can also think of qualified associations as a
pattern, a pattern of association. Indeed I did do this in [Fowler AP §15.2]. I have found it
helpful to think of modeling constructs as patterns, for it helps me think about the trade-offs
in using them. This is particularly useful when you are comparing them to something that is
more clearly a pattern, such as separate property. Of course things that begin as patterns can
be turned into modeling constructs, particularly if you use UML stereotypes. The historic
mapping pattern [Fowler AP §15.3] is a good example of that. I represent that using the
«history» stereotype. Is it a pattern or a modeling construction? Maybe it’s a floor wax and a
desert topping too.

Dynamic Properties with Multi-valued associations

My examples above have concentrated on cases where there is a single value for each key in
the dynamic properties. But you can also have cases where there are multiple items in the
dynamic properties. With Person you might consider a friends property which is multi-valued.
There are two ways to deal with this, one that is simple and unsatisfying, another that is
satisfying but (too) complex.

The simple approach is just to say that the value of a dynamic property can be a collection.
We can then manipulate it like any other object with the same interface (Listing 11). This is
nice and simple, since we don’t have to do anything to the basic dynamic property pattern.
(The example here is with a typed dynamic property, but it will work with all of them.) It’s
unsatisfying however because it is not really the way we would like to deal with multi-valued
properties. If friends were a fixed property, we would want an interface along the lines of
Listing 12. I don’t like exposing the vector in these cases. By doing so the person class loses
the ability to react when we add or remove elements. It also removes our ability to change the
type of collection we are using.
Person aPerson = new Person();
ContactType friends = new ContactType(“Friends”, Class.forName(“Vector”));
Person martin = new Person(“Martin”);
martin.setValueOf(“Friends”, new Vector());
Person kent = new Person(“Kent”);
martin.getValueOf(“Friends”).addElement(“Kent”);
Enumeration friends = martin.getValueOf(“Friends”).elements();

© Martin Fowler 1997 11


Listing 11. Using a collection value in a typed dynamic property
class Person {
public Enumeration getFriends();
public void addFriend(Person arg);
public void removeFriend(Person arg);

Listing 12. Operations for a fixed multi-valued property

So can we get an interface along the lines of Listing 12, when we have dynamic properties?
Well if we try hard enough we can, as you can see in Figure 7. But it is a complex model. With
some clever coding we can hide much of that complexity behind the interface (Listing 13 and
Listing 14) and make it reasonably convenient to use (Listing 15). But the client still needs to
know which properties are single valued and which are multi-valued and all the checking for
the right usage can only occur at run time. All this complexity is painful – a lot more painful
than using fixed properties. I would be very reluctant to go this far.

Contact Type [ 1
Type
valueType
isMultiValued: Boolean
types
1 1..[
[ [
1 [ 1
Person Contact Property Object
value

[ values
{if Contact Type is multivalued then use a
multivalued contact property, otherwise use a
single valued contact property} [
Single Valued
Contact Property
{value must have as one of its
types the value type of the
contact type} Multi Valued [
Contact Property

{each object in the


values set must have
as one of its types
the value type of the
contact type}

Figure 7. Satisfying but overly complex support of multi-valued dynamic properties


class Person
public Object getValueOf(ContactType key);
public Enumeration getValuesOf(ContactType key);
public void setValueOf(ContactType key, Object newValue);
public void addValueTo(ContactType key, Object newValue);
public void removeValueFrom(ContactType key, Object newValue);
class ContactType
public Class getValueType();
public boolean isMultiValued();
public boolean isSingleValued();
public ContactType(String name, Class valueType, boolean isMultiValued);

© Martin Fowler 1997 12


Listing 13. Operations for Figure 7
class Person
public Object getValueOf(ContactType key) {
if (key.isMultiValued())
throw IllegalArgumentException(“should use getValuesOf()”)
//return the value
}
public void addValueTo(ContactType key, Object newValue) {
if (key.isSingleValued())
throw IllegalArgumentException(“should use setValueOf”);
if (! key.getValueType().isInstance(newValue))
throw IllegalArgumentException (“Incorrect type for property”);
//add the value to the collection

Listing 14. Checking for usage of operations of Listing 13


fax = new ContactType(“fax”, Class.forName(“PhoneNumber”), false);
Person martin = new Person(“martin”);
martin.setValueOf(“fax”, new PhoneNumber(“123 1234”);
martinFax = martin.getValueOf(“fax”);

friends = new ContactType (“friends”, Class.forName(“Person”), true);


martin.addValueTo(“friends”, new Person(“Kent”));

Listing 15. Using the operations of Listing 13

This complexity appears because we have both multi valued and single-valued properties.
There is an inherently different interface to dealing with these, hence the complexity. Of
course we can get situations with only multi-valued properties. A common pattern for this is
the Typed Relationship pattern (Figure 8). Here a person may have number of different
employment relationships with a number of different companies (or even several with the
same company).

Employment
Type

Person Employment Company


1 [ [ 1

Figure 8. An example of a typed relationship


class Employment {
public Employment (Person person, Company company, Employment Type type);
public void terminate()
…}
class Person {
public Enumeration getEmployments();
public void addEmployment (Company company, EmploymentType type);

Listing 16. Java interface for Figure 8

As we think of this, it should soon occur to you that this is really very similar as using a
Defined Dynamic Property that is multi-valued, but expressed using a Separate Property rather
than a Qualified Association. (Or is that sentence just too much of a mouthful?) Indeed Figure
9 shows how you can use a Defined Dynamic Property interface in this situation. This view of
things is true, and so a typed relationship doesn’t add anything that new to this pattern

© Martin Fowler 1997 13


language. But typed relationship is a very common pattern in modeling circles, and many may
not realize its connection with the dynamic properties patterns.

Typed Relationship
How do you represent a relationship between two objects?
(How do you represent multi-valued dynamic properties?)
Create a relationship object for each link between the two objects. Give the
relationship object a type object to indicate the meaning of the relationship.
(The type object is the name of the multi-valued property.)

The strengths of typed relationship are that it works well with bi-directional relationships, and
that it provides a simple point to add properties to the relationship. (The latter, of course, is a
feature of separate properties.) You can add a sophisticated knowledge level to this pattern,
along much the same lines as typed dynamic properties. However you should consider the
interface implications. Typed relationships force users to be aware of the employment object,
as indeed does any use of separate properties. Indeed people tend to see the property object as
a full fledged object in its own right, rather as some property of the person (or company). But
the qualified association can often provide a simpler interface for many purposes. So whenever
you see, or you are considering using, a typed relationship; you should also consider the
qualified association form. You can use it in either or both directions, and use it either in
addition to the typed relationship, or in addition to it.

The two models are not quite identical however. If you use Figure 9 you are indicating that an
employer can only be an employer once for a particular employment type. Figure 8 has no such
constraint in the diagram as it stands, although most modelers would imply such a constraint,
unless the employment had additional attributes. Often, of course, the employment does have
the additional attributes. A common example is a date range (as in accountability [Fowler, AP
§2.4].

[ employees
Employment Type

employer
Person Employment Type Company
[

Figure 9. Using qualified associations for the same situation as Figure 8


public Person
public void addEmployer (Company company, EmploymentType type);
public Enumeration getEmployersOfType (EmploymentType type);

Listing 17. Interface for Figure 9

© Martin Fowler 1997 14


Employment
{a maximum of one Type
employment for each
combination of Person,
Company, and 1
Employment Type}

Person Employment Company


1 [ [ 1

Figure 10. Typed relationship, showing the constraint that is often assumed.

Different Kinds of People

So far we are assuming we only have one kind of person, and any properties we define for a
person are valid properties for all people. However you do get situations where you have
different types, and different properties for different types. A manager may need a property for
department managed, an executive may need a property for executive washroom key number
(in a not very 90’s company).

Don’t worry, I hear the cries of “use inheritance stupid”. Indeed this is one of the situations
that is often used for subtyping. Actually it gets rather more involved than that, particularly
when you start thinking of the various roles a person may play. I’ve written a whole paper on
the subject of modeling roles [Fowler roles]. The roles patterns consider cases where we are
interested in variations in operations and in variations of fixed properties. But in this case I
want to explore the overlap of different kinds of object with the notion of dynamic properties.
This overlap begets the dynamic properties knowledge level pattern (a name that is getting a little
too large for my taste).

To use the pattern we give the Person a type object of Person Type. We can then say that the
person type’s association to contact type indicates which properties are available for people
who have that person type. If we try to use, or ask for, a property on a person the person type
can be used to check that the usage is correct.

© Martin Fowler 1997 15


[ [ value type
Person Type Contact Type Type
[ 1
1..[ 1 1..[

[ [ [
1 [ value
Person Contact Property Object
[ 1

{All contact properties must


{value's types must
have a contact type that is one
include the contact
of the Person Type's Contact
type's value type}
types}

Figure 11. Dynamic Property Knowledge Level


class Person {
public Object getValueOf(ContactProperty key);
public boolean hasProperty(ContactProperty key);
public void setValueOf(ContactProperty key, Object newValue);
class PersonType {
public boolean hasProperty(ContactProperty key);
public Enumeration getProperties();

Listing 18. Operations for Figure 11


class Person {
public Object getValueOf (ContactProperty key) {
if (!hasProperty(key))
throw IllegalArgumentException(“Innapropriate key”);
//return the value

Listing 19. Checking for an appropriate key with a dynamic property knowledge level

As we start to use a knowledge level like this, the separate property becomes more and more
important. In this case we soon start to stop thinking of it as a property, rather as some object
in its own right. The dividing line between what is a property and what isn’t is very blurred,
and it really depends upon your view of things.

Dynamic Property Knowledge Level


How do you enforce that certain kinds of objects have certain properties when you
use dynamic properties?
Create a knowledge level to contain the rules of what types of objects use
which types of properties

Some Summary Points on Dynamic Properties

Various kinds of dynamic properties make up the bulk of this paper. But I have to reiterate
that dynamic properties are something I like to avoid if at all possible. Dynamic properties

© Martin Fowler 1997 16


carry a heavy burden of disadvantage: the lack of clarity of the interface, the difficulty in using
operations instead of stored data. It is just that sometimes you have little choice but to use
them, and it is on these occasions that this paper should come in useful to give you some
alternatives and the trade-offs between then.

Dynamic properties appear most where there are difficulties in changing the interface. People
who work with distributed object systems like them, at least in principle, because it allows
them to alter an interface without compromising clients – and in a distributed system it may
be very difficult to find who your clients are. But you should still be wary of doing this. Any
time you add a new key to your keys for the dynamic properties you are effectively changing
the interface. All the dynamic properties are doing is replacing a compile time check for a run-
time check. You still have the same issues of keeping your clients up to date.

Another common use of dynamic properties is in databases. Here it is not just due to the
problem of interface, but also (if not primarily) due to problems of data migration. Changing a
database schema does not only cause a potential change to programs using the schema, it also
may force you to do a complicated data conversion exercise. Again dynamic properties allow
you to change things without changing the database schema, and thus not needing to do any
data conversion. In large databases this can be a compelling advantage.

A property you don’t know about

There is a last but important kind of property that I want to add to this paper. This is the case
of an object having a property without realizing it. This occurs when the property is implied by
another object and the way it relates to you.

Consider an object that manages database connections. It creates a bunch of database


connections and hands them out to other objects when requested. When a client is done with
the connection it can return it to the manager to be available for someone else. You could do
this by adding an isBusy property to the connection. Figure 12 shows an alternative using an
extrinsic property. Whether the connection is free or busy is determined by which collection in
the connection manager it lies in. If you had a connection, you could not ask it whether it is
free or busy, instead you would have to ask the connection manager whether a particular
connection is free or busy. You can tell this because the composition associations are one way.
The connection has no knowledge of the connection manager. In a sense the free/busy status
isn’t a property of connection at all. Yet at least in some sense it is, which is why I mention it.

Connection

[ free [
busy

Connection Manager

getConnection()
releaseConnection (Connection)
isBusy (Connection)
isFree (Connection)

© Martin Fowler 1997 17


Figure 12. Using an external collection property

In a pure conceptual modeling sense this pattern does not make much sense. But there are
practical implementation reasons why you may want to use it. If you want all changes to this
property to go through a connection manager, then this approach makes this clear. In
particular this is a natural style when you want the connection manager to give you a free
connection and you don’t care which one.

Another reason to use an extrinsic property is if the connection class is provided by someone
else and you can’t change its interface. You can add the new property without changing the
connection class at all.

Extrinsic Property
How do you give an object a property without changing its interface?
Make another object responsible for knowing about the property.

The big problem with the extrinsic property is that it leads to an awkward and unnatural
interface. Usually if you want to know something, you just find the appropriate object and ask
it. Here you need to find the object that holds the external collection, and ask it about the
appropriate object. In some circumstances, such as this one, it seems reasonable. But most of
the time I would prefer to let objects know about their own properties (in which case I call
them intrinsic properties).

Final Thoughts

As I finish this paper, I feel the need again to urge you not to use what I’ve been writing about
here unless you really do need it. The advantages of fixed properties are great. If you need
something else, then I hope this paper gives you some ideas and some guidance. But fixed
properties are always your first choice.

References

[Fowler, AP] Fowler, Martin. Analysis Patterns: Reusable Object Models, Addison-Wesley
1997

[Fowler, roles] Fowler, Martin. Dealing with Roles, http://www.awl.com/cseng/titles/0-201-


89542-0/awweb.htm

[POSA] Buschman et al, Pattern Oriented Software Architecture, Wiley 1997

© Martin Fowler 1997 18


Application Facades
Deep in the bones of Object-Oriented programming is notion of building a set of classes that mimics the
objects in the “real world”. That is we try to analyze the way people think about the world and let the classes
in our programs model the way an expert in a domain thinks. Many of the books on OO analysis and design
talk about developing this domain model. To do anything with the domain model we need to put information
into and out of it, typically through a Graphical User Interface (GUI). There is not so much written about that
part of object-oriented design.

This article serves many purposes, but the first purpose is to address this issue of the relationship between a
GUI and the underlying model. I hold to the principle that user interfaces should lie on the outside of the
system and be invisible to the classes that model the problem. This keeps the often varying UI functionality
away from the domain classes. The domain classes will model the domain, the UI classes handle the UI —
simple and separate responsibilities.

I go further than this, and divide the UI classes into two: a presentation class and an application facade class.
The presentation class is the class that handles all the UI work. The application facade class is responsible for
talking to the domain model and getting the information to the presentation class in exactly the form that the
presentation class requires. In this way the presentation class needs to know nothing about what is going on in
the model, it only handles the UI work.

UI
framework

application
presentation domain
facade

testing

Figure 1 The general structure of packages and dependencies

Figure 1 shows a UML [UML] class diagram of the general structure of packages and dependencies I use. The
key points are:
• The presentation package does not see the domain package
• The application facade package does not see the UI framework
• The testing package does not need to see the presentation package.
The benefits we get from this approach are:
• We have split the UI classes into two sections with clear responsibilities for each. This makes each class
simpler and easier to understand and maintain.
• We can choose to separate the tasks of coding the presentation and application facade classes. Those who
code the application facade need to understand the domain package but need know nothing about coding
UI classes, the presentation programmers need to know about the UI but not about the details of the
domain. If the domain classes and the UI framework are complex, as they often are, this makes it much
easier for programmers to be found and trained.
• We can test most of the system without using the UI. Testing through the UI is generally awkward and it
is difficult to set up and maintain the testing scripts. By testing through the application facade only we
make it much easier to set up an automatic testing system which is essential to any well managed project.
There is still some testing of the UI that is needed, but the task is greatly reduced as in that testing we are
only concerned with the way the UI works, not how it interacts with the domain classes.
This article will explore how to do this in practice, with examples in Java. I discussed the principles of this in
chapter 12 and 13 of [Fowler], but did not provide any code examples. This article will should help dispel that
problem. For the domain model I chose to take some of the ideas of observation and measurement from
chapters 3 and 4 of [Fowler]. So this article also illustrates some examples of implementing those patterns.

This article also uses much the same material as that in the Java example in UML Distilled.

An Example Problem
Consider how a hospital’s computer systems might get at various observations they have made about a patient.
You could have a patient class with attributes for all the different types of observations (height, blood type,
heart rate, etc) but there would be thousands of such attributes: too many to have as attributes of a patient
class. So we can get around this by using the Observation and Measurement patterns from [Fowler]. For the
purposes of our discussion we want to be able record quantitative (height, 6 feet) and qualitative (blood group
A) statements about the patient. We also want to be able to assign qualitative statements depending on a
measurement. Thus is we record a person is breathing at a rate of 23 breaths a minute we should be able to
automatically make the qualitative statement that that is a fast breathing rate.
Phenomenon
Phenomenon Type
range : Range
0..1 *
1
1

* *
<<abstract>>
Measurement Category Observation
Observation
amount : Quantity isPresent : Boolean
measurement category
<<incomplete>>
* <<incomplete, dynamic>>

1
Patient

Quantity Range
amount : Number Unit upper : Magnitude
unit : Unit lower : Magnitude

Figure 2 Conceptual UML diagram for the domain of this example

Figure 2 shows a conceptual model to support this kind of behavior. Before we dive into it I need to stress
that word conceptual. This model is not what the classes look like, rather it is an attempt to model the concepts
inside a doctor’s head. It is similar to the classes, but as we shall see we have to change them a bit in the
implementation. I have used several patterns here from [Fowler], specifically Quantity, Measurement, Observation,
Range, and Phenomenon with Range. I’ll discuss how the model works here, but I won’t discuss the justification
for why I’m doing that way, that I will leave to the book.

Say we want to record that Martin is breathing at 23 breaths per minute. We would do this by creating a
measurement object linked to the patient object that represents Martin. The phenomenon type of this
measurement object would be called “breathing rate”. The amount in a measurement would be handled by a
quantity object with amount of 23 and unit of “breaths per minute”.

To say that Martin’s breathing is fast we would create a category observation, again with Martin as the patient.
The category observation would be linked to a phenomenon of “fast breathing rate” which in turn would be
linked to the phenomenon type of “breathing rate”. If the “fast breathing rate” phenomenon has a range, we
should be able to automatically tell if it applies to a breathing rate of 23.

The way the Figure 2 works a single observation object can be both a measurement and a category
observation at the same time (since the generalization arrows carry different labels). Also a measurement can
begin life as a plain measurement and become a category observation as well later (indicated by the
{dynamic} constraint). The combination of the {abstract} constraint on observation and the {incomplete}
constraints on its subtypes implies that an observation can be either a measurement, or a category observation,
or both; but it may not be neither. This is a conceptual picture that we will not be able to directly implement
as Java does not allow us quite this flexibility in typing.

A model along the lines of this is very suitable for a hospital example because it will scale to the thousands of
phenomena that are observed in a hospital setting. For an individual use, however, it is not so suitable. An
individual use may want a simpler screen entirely, along the lines of that in Figure 3. Here the user does not
want to bother with knowing about observation objects, they just want to assign a value to some patient
attribute.

Figure 3 A sample screen showing a simpler view of patient information

Our task is to implement the model in Figure 2 yet provide a UI of the form of Figure 3. We will do this by
creating an application facade that converts from Figure 2 to a form ready for Figure 3 and a presentation
object that gives the display in Figure 3. I’m not making any claims about the practical usefulness of a screen
like Figure 3, the screen is purely a sample to discuss the software principles.

Implementing Quantity
Faced with this kind of situation many people would represent a heart rate with a number. I prefer to always
include units with this kind of dimensioned value, hence my use of the Quantity pattern. Implementing the
Quantity pattern is fairly straightforward in any object-oriented language.
public class Quantity {
private double _amount;
private Unit _unit;

Although we use a double for the internal amount we can provide constructors for different initialization
options. (Note that by convention I use a leading underscore on all fields.)
public Quantity (double amount, Unit unit) {
requireNonNull(unit);
_amount = amount;
_unit = unit;
};

public Quantity (String amountString, Unit unit) {


this (new Double(amountString).doubleValue(), unit);
};
public Quantity (int amount, Unit unit) {
this (new Double(amount).doubleValue(), unit);
};

protected void requireNonNull(Object arg) {


if (arg == null) throw new NullPointerException();
};

The quantity class needs a unit class, which for the purposes of this example need only know its name. A class
that has a name is a common need in these circumstances, so I have an abstract class, DomainObject, for it.
public DomainObject (String name) {
_name = name;
};

public String name () {


return _name;
};
protected String _name = "no name";
};

public class Unit extends DomainObject

Registrar
Another core behavior we will need is to get hold of specific objects without using global variables for
example the unit “breaths per minute”. I need unit to be an Entry Point [Fowler] for my objects so I can just
refer to the “breaths per minute” unit by going something like Unit.get(“breaths per minute”).
I can implement this in two ways: either by having a static variable in the unit class, or by having a Registrar
object that manages these entry points. I prefer the Registrar as it is easier to manage. The Registrar is a
Singleton [Gang of Four] which manages several entry points.
public class Registrar {

private static Registrar _soleInstance = new Registrar();

Each entry point is a Hashtable. Since the Registrar manages several entry points it keeps each entry point as
the value in a Hashtable indexed by some useful name, usually the name of the class that is acting as the entry
point.

public class Registrar {


private static Registrar _soleInstance = new Registrar();
private Dictionary _entryPoints = new Hashtable();
private void addObj (String entryPointName, DomainObject newObject) {
Dictionary theEntryPoint = (Dictionary) _entryPoints.get(entryPointName);
if (theEntryPoint == null) {
theEntryPoint = new Hashtable();
_entryPoints.put(entryPointName, theEntryPoint);
};
theEntryPoint.put(newObject.name(), newObject);
};
private DomainObject getObj (String entryPointName, String objectName) {
Dictionary theEntryPoint = (Dictionary) _entryPoints.get(entryPointName);
assertNonNull (theEntryPoint, "No entry point present for " + entryPointName);
DomainObject answer = (DomainObject) theEntryPoint.get(objectName);
assertNonNull (answer, "There is no " + entryPointName + " called " + objectName);
return answer;
};
private void assertNonNull(Object arg, String message) {
if (arg == null) throw new NullPointerException(message);
};

I use Lazy Initialization [Beck] if a client wants to store a value into an entry point collection that I have not
used yet. To make it a little easier to use the registrar I put some static methods on the class.

public static void add (String entryPoint, DomainObject newObject) {


_soleInstance.addObj(entryPoint, newObject);
};

public static DomainObject get (String entryPointName, String objectName) {


return _soleInstance.getObj(entryPointName, objectName);
};

However to make it easier for programmers I use methods on the appropriate classes to get values in and out
of the registrar:
public class Unit extends DomainObject {

public static Unit get (String name) {


return (Unit) Registrar.get("Unit", name);
};

public Unit persist() {


Registrar.add("Unit", this);
return this;
};

You will see that I do the same thing for other entry point classes in the system. I would be inclined to make
persist and get part of an interface. Unfortunately if I did that then the return type of get would have
to be defined to be something like Object and I could not override it to something more specific within a
class. This would result in a lot of casting, so I just duplicate those two methods on any entry point class. Of
course a programmer could use the Registrar directly, but then I have to remember the collection name.
I try not to clutter up my memory with stuff like that.

Phenomenon and Phenomenon Type


Now we will turn to phenomenon and phenomenon type. An example of these classes might be blood group,
which we would describe by a single phenomenon type of ‘blood group’ with phenomena of ‘blood group A’,
‘blood group B’, ‘blood group O’, and ‘blood group A/B’. A phenomenon type need not have phenomena.
We might not choose to put ranges on people’s height, in that case the phenomenon type of ‘height’ would
have no phenomena. So it makes sense to have a simple construction for phenomenon type.
public class PhenomenonType extends DomainObject {
public PhenomenonType (String name) {
super (name);
};

A phenomenon may also exist alone, such as the phenomenon ‘shock’.


public class Phenomenon extends DomainObject {
public Phenomenon (String name) {
super (name);
};

Of course the interesting case is when we have to link them together. Typically we may want to do this by
giving an array of names to a phenomenon type:
PhenomenonType sex = new PhenomenonType("gender").persist();
String[] sexes = {"male", "female"};
sex.setPhenomena (sexes);

We now need to think about how the conceptual association between phenomenon type and phenomenon
should be implemented. For a full discussion see the Implementing Associations pattern [Fowler]. In this case I
am going to implement it by Pointers in Both Directions. Many people shy away from these ‘back pointers’, but I
find that if they are used appropriately they do not cause trouble. One source of trouble lies in keeping them
up to date and in sync. To deal with this I always ensure that the updating is controlled by one side of the
association — in this case the phenomenon. Since we only do this at creation time, the behavior is in an
alternative constructor for phenomenon.
public class Phenomenon extends DomainObject {
private PhenomenonType _type;
public Phenomenon (String name, PhenomenonType type) {
super (name);
_type = type;
_type.friendPhenomenonAdd(this);
};

public class PhenomenonType extends DomainObject {


private Vector _phenomena = new Vector();
void friendPhenomenonAdd (Phenomenon newPhenonenon) {
// RESTRICTED: only used by Phenomenon
_phenomena.addElement(newPhenonenon);
};

The phenomenon constructor really needs privileged access to phenomenon type here, a good use of C++’s
friend construct. We don’t have friends in Java. I could make phenomenon type’s field be of package
visibility, but I prefer to keep my data private. So I create a special method using the word “friend” to
communicate its special purpose.

With this behavior in place I can now implement setPhenomena():


public void setPhenomena (String[] names) {
for (int i = 0; i < names.length; i++)
new Phenomenon (names[i], this);
};

I don’t use arrays that much in C++ or Java, so it gave me a nostalgic thrill to write a classic C for loop.

Creating Observations
Now its time to think how we going to create an observation, and in particular how we are going to deal with
that awkward to implement classification of observation. Well I’m going to duck it. I’m going to have an
observation class and a measurement class. The observation class will have the link category observation
behavior folded into it. Simple and it will work for this situation. And by ducking a more complicated
implementation I am actually passing on an important lesson. Don’t try to come up with a clever way to do
something if a simple way works fine. So this approach has limitations. Always ask yourself if you can live
with the limitations — if you can you should. You can always make it more complicated later.
public class Observation extends DomainObject {

protected Phenomenon _phenomenon;


private boolean _isPresent;
private Date _whenObserved;
public Observation (Phenomenon relevantPhenomenon, boolean isPresent, Patient patient,
Date whenObserved) {
_phenomenon = relevantPhenomenon;
_isPresent = isPresent;
patient.observationsAdd(this);
_whenObserved = whenObserved;
};

In this case I’m not doing any two-way pointer stuff. Observation keeps the pointer to phenomenon, but
patient keeps the pointers to observation. I use a vector for the set of observations that a patient has, as I
don’t know the size in advance. I find I rarely know the size of things in advance, so I use arrays rarely.
Vectors are on the whole easier to use, although the downcasting gets up my nose after a while.
public class Patient extends DomainObject {
private Vector _observations = new Vector();
public void observationsAdd (Observation newObs) {
_observations.addElement(newObs);
};

First Steps in the Facade


Now we have enough to begin to consider setting up a facade. The sample window in Figure 3 is based on
your vital signs, so I will call it a VitalsFacade. When I construct a facade I give it a subject: a reference into the
domain model. In this case the subject is the patient.
package vitalsFacade;
import observations.*;

public class VitalsFacade {


private Patient _subject;
public VitalsFacade (Patient subject) {
_subject = subject;
};

All the other classes were in the observations package, so it needs to import them.

We can begin the facade by providing some simple queries for the patient’s name and gender. The name is
very easy.
public String name() {
return _subject.name();
};

The gender is a little bit more complicated. We may have more than one observation of gender. We will
assume that we are not going to have to deal with contradictory observations (in reality we do have to deal
with them, but I can cut it out of the scope of this exercise). So we need to find the latest observation of a
phenomenon whose phenomenon type is “Gender”, and then return the string that describes the
phenomenon. We need to return a string for that is all the presentation class can understand. As well as
navigating through the domain model, the facade is responsible for converting the types to the simple types
that the UI classes understand.

We could put all of this behavior on the facade, but it is better to delegate much of it to the patient.
Class VitalsFacade {
public String gender() {
return _subject.phenomenonOf("gender").name();
};

The patient will take this and find the latest observation of the requested phenomenon type. If there is none it
will just hand back null.
class patient {
public Phenomenon phenomenonOf(String name) {
return phenomenonOf(PhenomenonType.get(name));
};

public Phenomenon phenomenonOf(PhenomenonType phenomenonType) {


return (latestObservation(phenomenonType) == null ?
null :
latestObservation(phenomenonType).phenomenon());
};

To find the latest observation the patient first finds all the observations that exist for a given phenomenon
type, which it supplies as an enumeration.
public Enumeration observationsOf(PhenomenonType value) {
Vector result = new Vector();
Enumeration e = observations();
while (e.hasMoreElements()) {
Observation each = (Observation) e.nextElement();
if (each.phenomenonType() == value) result.addElement(each);
};
return result.elements();
};
public PhenomenonType phenomenonType() {
return _phenomenon.phenomenonType();
};
public Enumeration observations() {
return _observations.elements();
};

We could speed this up by keeping our observations in a hashtable indexed by phenomenon type. If I ever
have to performance tune this I will profile it to see, but for this exercise I’m more interested in the slow and
simple approach. Once we have the enumeration of the appropriate observations we can find the latest.

public Observation latestObservation(PhenomenonType value) {


return latestObservationIn (observationsOf(value));
};

private Observation latestObservationIn(Enumeration observationEnum) {


if (!observationEnum.hasMoreElements()) return null;
Observation result = (Observation) observationEnum.nextElement();
if (!observationEnum.hasMoreElements()) return result;
do {
Observation each = (Observation) observationEnum.nextElement();
if (each.whenObserved().after(result.whenObserved())) result = each;
}
while (observationEnum.hasMoreElements());
return result;
};

Handing back null is actually rather awkward. It means the method gender will break if it gets a null sent
back to it. To fix this I would need to put a conditional in place
public String gender() {
return (_subject.phenomenonOf("gender") == null) ?
null :
_subject.phenomenonOf("gender").name();
};
And I have to do this everywhere I use Patient.phenomenonOf(). That is downright boring, and I
don’t like boring programming, not just because its boring, but also because it tends to be very error prone.
Fortunately there is a savior — the Null Object pattern (which will be published in the PloPD 3 book). To use
a null object all I need to do is create a subclass of phenomenon called null phenomenon, and override the
behavior of phenomenon to do suitable default things.
class NullPhenomenon extends Phenomenon {

public String name () {


return "";
};
}

I can now return a null phenomenon instead.


public Phenomenon phenomenonOf(PhenomenonType phenomenonType) {
return (latestObservation(phenomenonType) == null ?
new NullPhenomenon() :
latestObservation(phenomenonType).phenomenon());
};

The nice thing about this is that no client of Patient.phenomenonOf() is even aware that a null
phenomenon class exists. The class is not declared public and is invisible to the client programs. There are
cases when we might need to see if we have a null phenomenon, we can do this by adding a isNull()
method to phenomenon. Using null objects can do a lot to simplify code, use it whenever you are standing on
your head with your arms crossed trying to deal with null responses to questions.

Testing the Facade


Now we actually have enough to test the facade. My approach to testing is to test frequently after each step,
and to build up my test code so that I have a solid set of regression tests to run at any time. I’ve actually run a
bit long here without testing, so its time to catch up.

The basis of testing is a tester class what will get run when we test, so it needs a main method. The main looks
rather complicated, this is because of Cafe’s habit of printing to the standard output, and then closing the
standard output screen before you can see what was printed. With this code I get to read it and dismiss it with
a return, even if I get a runtime exception.
public class Tester {
public static void main (String[] argv) {
try {
System.out.println (new Tester().test());
} catch (Exception e) {
System.out.println ("Exception while executing: " + e.toString());
};
try {
System.in.read();
} catch (java.io.IOException e) {};
};

The main action lies in the test method.


TestResult test() {
setup();
testPhenomena();
return _result;
};

OK, so I lied the test method is just three method calls, but to start delving into the depth let me explain what
this test result class is. Essentially it is just a mechanism to storing up details of failed tests and printing them
out at the end.
public class TestResult {
private Vector _failures = new Vector();

We add details about failures with a descriptive string.

public void addFailure (String message) {


_failures.addElement (message);
};

When we are done we print either the list of failures or the comforting “OK”.

public String toString() {


if (isFailure())
return "Failures\n" + failureString();
else
return "OK";
};

public boolean isFailure() {


return ! _failures.isEmpty();
};

public String failureString() {


String result = "";
Enumeration e = _failures.elements();
while (e.hasMoreElements()) {
result += "\t" + e.nextElement() + "\n";
};
return result;
};

To use all of this we begin by setting up our genders in the setup method.
Public void setup() {
PhenomenonType sex = new PhenomenonType("gender").persist();
String[] sexes = {"male", "female"};
sex.setPhenomena (sexes);

We then create a person and make him male


new Patient("Adams").persist();
new Observation
(PhenomenonType.get("gender").phenomenonNamed("male"),
true,
Patient.get("Adams"),
new Date (96, 3, 1));

Then we test to see if we are reading what we are supposed to be reading.


Public void testPhenomena() {
try {
VitalsFacade facade = new VitalsFacade (Patient.get("Adams"));
if (!facade.name().equals("Adams")) _result.addFailure("adams without name");
if (!facade.gender().equals("male")) _result.addFailure("adams not male");
} catch (Exception e) {
String message = "Exception " + e.toString();
if (e.getMessage() != null) message += " " + e.getMessage();
_result.addFailure (message);
e.printStackTrace();
};

This way we capture the results of many tests and print the results of them all. This is a pretty simple
framework, and on a real project I would expect to see something rather better. But this one is enough for my
needs here.

So far its not much of test, there is only a minimal amount of behavior going on. But the point is to test like
those people in Chicago allegedly used to vote — early and often. A simple testing framework makes life
easier. As you go on you can add more tests, but you never throw tests away. Not unless you like driving at
night with your lights off.

Updating through the facade


So far we are only looking at using the facade in a simple case, to get a value of a phenomenon where there is
only one in our test case, and we are not trying to update. So for a more complicated example lets take the
level of consciousness phenomenon type. This is a simple classification of how conscious someone is. There
are four values: alert (talking normally), verbal (responds to verbal stimuli), pain (responds to painful stimuli -
such as tweaking the ear) and unresponsive (even to ear tweaking). In the model this simply works as a
phenomenon type with four phenomena.
With the facade the first route we can try is to work with methods on VitalsFacade. For level of
consciousness we will want to get the current value, update the current value, and also find out what the legal
values are so we can display them in a pop-up menu.
public String levelOfConsciousness ()
public void levelOfConsciousness (String newValue)
public Enumeration levelOfConsciousnessValues ()

With the case of gender we just asked the patient directly for its information. We can do the same here, but as
things get a bit involved it can be useful to store a value in the facade. It generally makes it easier to see what
is going on. So we store the current value in a string.
private String _levelOfConsciousness;

We put the information into the string when we load the facade.
public void load() {
_levelOfConsciousness = levelOfConsciousnessRetrieve();

private String levelOfConsciousnessRetrieve() {


return _subject.phenomenonOf("level of consciousness").name();
};

So far this very similar to the gender case we looked at before. To carry out an update we begin updating the
value in the facade. When we do this we want to check we are getting a legal value for the level of
consciousness. We need a way to find out what the legal values are. We could do this by just asking
phenomenon type for its phenomena, but we also need a way to get from the strings of these values to the
phenomena. To serve these two needs we would really like a hashtable, keyed by the strings displayed in the
pop-menu with values as the phenomenon types. Phenomenon type can easily give us such a table.
class VitalsFacade {
private Hashtable levelOfConsciousnessTable() {
return PhenomenonType.get("level of consciousness").mappingTable();
};
Class PhenomenonType {
public Hashtable mappingTable() {
Hashtable result = new Hashtable();
Enumeration e = phenomena();
while (e.hasMoreElements()) {
Phenomenon each = (Phenomenon) e.nextElement();
result.put (each.name(), each);
};
return result;
};

To check we are getting a legal value, we just ask the table for its keys
public void levelOfConsciousness (String newValue) {
if (! levelOfConsciousnessTable().containsKey(newValue))
throw new IllegalArgumentException("Illegal level of consciousness");
_levelOfConsciousness = newValue;
};

We throw a runtime exception here, rather than a matched exception, because we don’t really expect an illegal
update value. Any window using this interface should really restrict the choices to the four legal values we
give. In Design By Contract [Meyer] terms the fact that newValue is one of the four is really part of the
pre-condition of levelOfConsciousness(String), and thus it is not the responsibility of
levelOfConsciousness to do any checking. Thus callers of levelOfConsciousness should not expect any
checking. Its difficult to show that explicitly in Java, as we can’t use compiler directives (as in C++), let alone
proper operation pre-conditions as they have in Eiffel. I suppose I could something of the kind
if (PRE_CONDITION_CHECKS_ON) {

and rely on the compiler to optimize away any problems. The reality is that I’m still undecided about how to
handle pre-conditions in Java.

A useful thing to consider here is what we might do if we wanted to show something other than the standard
names for the four phenomena. If we wanted to show something else the facade can build the hashtable itself
with the alternative display strings. Each facade could potentially have its own display strings, and use the
hashtables to map back to the internal phenomena.

Anyway back to the main plot. Once we have the new value in the facade’s field we then need to save it into
the domain model.
public void save() {
if (_date == null) _date = new Date();
levelOfConsciousnessUpdate();

private void levelOfConsciousnessUpdate() {


if (_levelOfConsciousness == null) return;
new Observation ((Phenomenon)
levelOfConsciousnessTable().get(_levelOfConsciousness),
true, _subject, _date);
};

We use the table again to get the actual phenomenon we want. Each time we create a observation we need a
date. We can explicitly set a date into the facade (we will do this for testing) or the computer assigns the
current date.

So again we need to test. The test routine now has four distinct stages
TestResult test() {
loadPhenomena();
setupAdams1();
setupAdams2();
testPhenomena();
return _result;
};

LoadPhenomena sets up the various phenomenon types and other knowledge objects that are loaded
permanently into the registrar. SetupAdams1 and setupAdams2 do two stages of changes to our sample
patient.
private void setupAdams1() {
new Patient("Adams").persist();
new Observation
(PhenomenonType.get("gender").phenomenonNamed("male"),
true,
Patient.get("Adams"),
new Date (96, 3, 1));
VitalsFacade facade = new VitalsFacade (Patient.get("Adams"));
facade.date(new Date (96,3,1,4,0));
facade.levelOfConsciousness("pain");
facade.save();
};
private void setupAdams2() {
VitalsFacade facade = new VitalsFacade (Patient.get("Adams"));
facade.date(new Date (96,3,1,6,0));
facade.levelOfConsciousness("verbal");
facade.save();
};

This gives us two observations to choose the latest from.


private void testPhenomena () {
try {
VitalsFacade facade = new VitalsFacade (Patient.get("Adams"));
facade.load();
if (!facade.name().equals("Adams")) _result.addFailure("adams without name");
if (!facade.gender().equals("male")) _result.addFailure("adams not male");
if (!facade.levelOfConsciousness().equals("verbal"))
_result.addFailure("adams not verbal");
} catch (Exception e) {
String message = "Exception " + e.toString();
if (e.getMessage() != null) message += " " + e.getMessage();
_result.addFailure (message);
e.printStackTrace();
};
};

As we continue this example we will see these set up and test routines steadily grow.
Adding a Measurement
So far we have looked at qualitative observations. Now it is time to look at the quantitative observations.
Although the conceptual model gives me the outline of how I expect to do them, I haven’t yet coded up the
Measurement class.
public class Measurement extends Observation{
private Quantity _amount;
private PhenomenonType _phenomenonType;

Measurement will need a different constructor, one that provides a quantity and a phenomenon type rather
than a phenomenon. In this case I am setting some of the fields of the superclass. I could use a superclass
constructor for this, but its not really a constructor, and using a constructor would communicate the wrong
thing to the reader of this code. So I’ve added an initialize method to observation for those fields that are
really observation’s responsibility to deal with. The initialize method is marked protected to communicate the
fact that it is intended for subclasses only.
Class Measurement
public Measurement (Quantity amount, PhenomenonType phenomenonType, Patient patient,
Date whenObserved)
initialize (patient, whenObserved);
_amount = amount;
_phenomenonType = phenomenonType;
checkInvariant();
_phenomenon = calculatePhenomenonFor(_amount);
};
private void checkInvariant () {
assertNonNull (_phenomenonType, "Null phenomenon type");
assertNonNull (_amount, "Null amount");
};
Class Observation
protected void initialize (Patient patient, Date whenObserved) {
patient.observationsAdd(this);
_whenObserved = whenObserved;
};

Similarly to working with observations, we need to get the latest measurement for a phenomenon type for a
particular patient. Again I’ve used the Null Object pattern to give me a null quantity if I don’t have a
measurement.
public Quantity latestAmountOf(PhenomenonType value) {
Measurement latestMeasurement = (Measurement) latestObservation(value);
return (latestMeasurement == null) ?
new NullQuantity() :
latestMeasurement.amount();
};

In the facade, I will again store the display value in a variable and pull it in when I load the facade. I will start
work with heart rate.
Class VitalsFacade {
private String _heartRate;
public String heartRate() {
return _heartRate;
};

private String heartRateRetrieve() {


_value = _facade.subject().latestAmountOf
(PhenomenonType.get("Heart Rate")).amountString();
};
class Quantity {
public String amountString() {
return String.valueOf(_amount);
};

Class NullQuantity {
public String amountString() {
return null;
};
When updating the GUI will allow users to type in whatever numbers they like. Of course they might not just
type in numbers, they might add letters too. So the facade should check that its update string is properly
numeric. If there is a problem it will just set the value to null.
public void heartRate(String newRate) {
_heartRate = (isNumeric(newRate) ? newRate : null);
};

private boolean isNumeric(String value) {


for (int i = 0; i < value.length(); i++) {
char eachChar = value.charAt(i);
if (Character.isDigit(eachChar)) continue;
if ((i == 0) & (eachChar == '-')) continue;
if (eachChar == '.') continue;
return false;
};
return true;
};

There is room for improvement in the numeric checking, but I’ll leave that as an exercise for the reader. What
I would have preferred to do was to try creating a number and handle any resulting exception.
try {
Float.valueOf(value);
} catch (NumberFormatException e) {
return false;
}
return true;

Sadly, however, if you go Float.valueOf(“8m1”) it does not throw an exception, it merely creates the
number 8. It makes a certain sense, but was not what I wanted.

Now I have a numeric string in _value, so I am ready to create the measurement.


private void heartRateUpdate () {
if (_heartRate == null) return;
new Measurement (new Quantity (_heartRate, Unit.get("beats/min")),
PhenomenonType.get ("Heart Rate"),
_subject,
_date);
};

In all of this I have to have some policy about when and what should be updated. Should I only update
observations that have changed, or should I create observations for all the non-null values? For this example I
am creating an observation for each non-null item on the window, whether or not it has changed since the last
time. This is complicated by the fact that the changes to the domain model may not be visible from this
facade. If I have a measurement of 82 beats per minute now, and another measurement of 82 beats per
minute in ten minutes; I cannot tell if there is two measurements or one measurement from this UI. If I was
looking through another UI at a plot of heart rate over time I would see a difference. Different facades would
use different policies. You just need to make sure the effects on the domain model are what a user who is
aware of the domain model would expect.

I can now add tests for this new behavior.


private void setupAdams1() {
new Patient("Adams").persist();
new Observation
(PhenomenonType.get("gender").phenomenonNamed("male"),
true,
Patient.get("Adams"),
new Date (96, 3, 1));
VitalsFacade facade = new VitalsFacade (Patient.get("Adams"));
facade.date(new Date (96,3,1,4,0));
facade.levelOfConsciousness("pain");
facade.heartRate("92");
facade.save();
};

private void setupAdams2() {


VitalsFacade facade = new VitalsFacade (Patient.get("Adams"));
facade.date(new Date (96,3,1,6,0));
facade.levelOfConsciousness("verbal");
facade.heartRate("87");
facade.save();
};

private void testPhenomena () {


try {
VitalsFacade facade = new VitalsFacade (Patient.get("Adams"));
facade.load();
if (!facade.name().equals("Adams")) _result.addFailure("adams without name");
if (!facade.gender().equals("male")) _result.addFailure("adams not male");
if (!facade.levelOfConsciousness().equals("verbal")) _result.addFailure("adams
not verbal");
if (facade.heartRate() == null) _result.addFailure ("Heart Rate is null");
if (!facade.heartRate().equals("87")) _result.addFailure("incorrect heart rate");

Creating Ranges
The next step is to infer a phenomenon from a measurement. I might want to know if the heart rate value I
have put in is fast, average, or slow. A professional doctor or nurse would not need a computer to tell them
that, of course. Indeed they would probably be irritated by the computer saying that. But after all you are
probably not a doctor or nurse and there are phenomena where they would find such an indication useful.

We know from the conceptual model that we can do much of what we want to do by giving a phenomenon a
range. We could do this by giving a phenomenon an upper and lower value, but I prefer to use the Range
pattern [Fowler]. This suggests making a class that handles all of the range like behavior. In some languages I
can make a single range class, but since Java is both strongly typed and does not have paramaterized types it’s
easier to make a specific quantity range class.
public class QuantityRange {
private Quantity _start;
private Quantity _end;
private boolean _isStartInclusive;
private boolean _isEndInclusive;

When you do a range with continuous variables, like real numbers, then Booleans that allow expressions such
as 12 < x ≤ 15 are very useful. If you are dealing with discreet things, such as integers, then you don’t need
them.
public QuantityRange (Quantity start, boolean isStartInclusive, Quantity end,
boolean isEndInclusive) {
_start = start; // null implies no lower bound
_end = end; //null implies no upper bound
_isStartInclusive = isStartInclusive;
_isEndInclusive = isEndInclusive;
};
public QuantityRange (Quantity start, Quantity end) {
this (start, true, end, true);
};
public static QuantityRange unlimited() {
return new QuantityRange (null, null);
};

Once you have a range, you can use it to figure out whether a quantity lies within its bounds.
public boolean includes (Quantity value) {
if (_end != null) {
if (value.isGreaterThan(_end)) return false;
if (!_isEndInclusive && value.equals(_end)) return false;
};
if (_start != null) {
if (value.isLessThan(_start)) return false;
if (!_isStartInclusive && value.equals(_start)) return false;
};
return true;
};

Of course to do this you need to add the appropriate operations to quantity.


public boolean equals(Quantity arg) {
return _unit.equals(arg.unit()) && (_amount == arg.amount());
};

public boolean isLessThan(Quantity arg) {


requireSameUnitsAs(arg);
return _amount < arg.amount();
};

public boolean isLessThanOrEqualTo(Quantity arg) {


requireSameUnitsAs(arg);
return isLessThan(arg) || equals(arg);
};

public boolean isGreaterThan(Quantity arg) {


requireSameUnitsAs(arg);
return !isLessThanOrEqualTo(arg);
};

public boolean isGreaterThanOrEqualTo(Quantity arg) {


requireSameUnitsAs(arg);
return !isLessThan(arg);
};

private void requireSameUnitsAs(Quantity arg) {


if (!_unit.equals(arg.unit())) throw new IllegalArgumentException();
};

You could argue that these should have been developed earlier, since we knew we would probably need them.
But I prefer not to code unless I need to, because sometimes you code things you think you will need that
you end up not needing. An exception to this is when you have long build times, or complicated inter-team
communications. Then it is worth getting the interfaces sorted out earlier.

I put the tests for quantity range in the class itself, since its pretty well self contained.
public static void main () {
String result = "";
Unit cm = new Unit ("cm");
QuantityRange range1 = new QuantityRange (new Quantity (100,cm), new Quantity
(200,cm));
if (range1.includes(new Quantity(201, cm))) result += "201 within range\n";
if (range1.includes(new Quantity(200.0001, cm))) result += "200.0001 within
range\n";
if (!range1.includes(new Quantity(200, cm))) result += "200 not within range\n";
if (!range1.includes(new Quantity(199, cm))) result += "199 not within range\n";
if (!range1.includes(new Quantity(101, cm))) result += "101 not within range\n";
if (!range1.includes(new Quantity(100, cm))) result += "100 not within range\n";
if (range1.includes(new Quantity(99.999, cm))) result += "99.999 within range\n";
if (range1.includes(new Quantity(99, cm))) result += "99 within range\n";
QuantityRange range2 = new QuantityRange (new Quantity (250,cm), false, new Quantity
(400,cm), false);
if (range2.includes(new Quantity(249.99, cm))) result += "249.99 within range\n";
if (range2.includes(new Quantity(250, cm))) result += "250 within range\n";
if (!range2.includes(new Quantity(250.0001, cm))) result += "250.0001 not within
range\n";
if (!range2.includes(new Quantity(399.9999, cm))) result += "399.9999 not within
range\n";
if (range2.includes(new Quantity(400, cm))) result += "400 within range\n";
if (range2.includes(new Quantity(400.0001, cm))) result += "400.0001 within
range\n";
if (range2.includes(new Quantity(401, cm))) result += "401 within range\n";

if (result == "") result = "OK";


System.out.println(result);
};

This is an even simpler kind of testing framework than the one I’m using in general. It is a useful approach if
you don’t want extra classes. Putting tests in a class like this also helps a reader understand what the class
does.

Determining a Phenomenon for a Measurement


With ranges in place we can now set up some phenomena for heart rate. First we need to give phenomenon a
range.
private QuantityRange _range;
public void range (QuantityRange arg) {
_range = arg;
};
Then set three ranges for heart rate when we load the phenomena in the tester.
private void loadPhenomena() {
PhenomenonType sex = new PhenomenonType("gender").persist();
String[] sexes = {"male", "female"};
sex.setPhenomena (sexes);
PhenomenonType loc = new PhenomenonType("level of consciousness").persist();
new Phenomenon("alert", loc);
new Phenomenon("verbal", loc);
new Phenomenon("pain", loc);
new Phenomenon("unresponsive", loc);
setupHeartRates();
};

private void setupHeartRates() {


Unit bpm = new Unit("beats/min").persist();
PhenomenonType heartRate = new PhenomenonType("Heart Rate").persist();
new Phenomenon ("slow", heartRate).range(new QuantityRange
(null, false, new Quantity (60, bpm), false));
new Phenomenon ("normal", heartRate).range(new QuantityRange
(new Quantity (60, bpm), true, new Quantity (80, bpm), true));
new Phenomenon ("fast", heartRate).range(new QuantityRange
(new Quantity (80, bpm), false, null, false));
};

The system now knows what ranges exist, so the next step is to do the assignment. The obvious place to do
this is when we create a measurement.
public Measurement (Quantity amount, PhenomenonType phenomenonType, Patient patient,
Date whenObserved)
initialize (patient, whenObserved);
_amount = amount;
_phenomenonType = phenomenonType;
checkInvariant();
_phenomenon = calculatePhenomenonFor(_amount);
};

The measurement does this by asking the phenomenon type which phenomenon includes the range.
public Phenomenon calculatePhenomenonFor(Quantity arg) {
return _phenomenonType.phenomenonIncluding(arg);
};

The phenomenon type asks each phenomenon if it includes the range, returning the first one that does. If
none do, it returns null, which is appropriate for the measurement anyway.
Class PhenomenonType {
public Phenomenon phenomenonIncluding (Quantity arg) {
Enumeration e = phenomena();
while (e.hasMoreElements()) {
Phenomenon each = (Phenomenon) e.nextElement();
if (each.includes(arg)) return each;
};
return null;
};
class Phenomenon {
public boolean includes (Quantity arg) {
return (_range == null ? false : _range.includes(arg));
};

The approach works whether or not we have defined ranges for the phenomena. The interaction diagram
below sums up the messages that are going on.
a Vitals Facade a Measurement a Phenomenon a Phenomenon
Type
new

calculate phenomenon

phenomenon including
* includes

Figure 4 An interaction diagram for assigning a phenomenon to a measurement

As far as the UI is concerned the string that describes the phenomena is just another attribute of the facade,
one that is not connected with the number. The facade provides a separate pair of operations for the UI to
use to get at the information.
private String _heartRateName;
public String heartRateName() {
return _heartRateName;
};

To load the stored attribute, the facade uses the same approach as for level of consciousness.
private String heartRateNameRetrieve() {
return _subject.phenomenonOf("Heart Rate").name();
};

Even the facade is unaware of measurement’s cleverness. I like it when bits of programs don’t know what
other bits are doing.

Refactoring the Level of Consciousness


Adding the breathing rate is pretty easy, just copy the code for heart rate and change a few names. Easy to say
and easy to do, but it leaves a bad taste in my mouth and gives me an uneasy feeling. Also the vitals facade
class is getting a little bit too complicated for my liking. Kent Beck says you should “listen to your code”. Of
course when he says things like that my first thought is that he’s been living near San Francisco too long. The
serious point is that when it starts getting too awkward to use the code because the code is getting in the way,
then its time to take a scalpel to the code, in this case it’s time for vitals facade to get on the operating table.

The underlying problem is that vitals facade is getting too complex. It’s got these fields each of which has
several methods working on it. The methods tend to work on only one field. That’s a sign for breaking up the
class by creating satellites. This refactoring step takes one or more fields and puts it in a separate class which
is linked to the original. Those methods that touch the moved fields get moved too. We will begin by making
a satellite of level of consciousness. First we define the new class and move over the field. I’m also going to
give the new class a pointer back to its facade.
class LocAttribute {

private String _value;


private VitalsFacade _facade;

LocAttribute(VitalsFacade facade) {
_facade = facade;
};

Next we take the methods over. I’ll start with the accessors for the UI.
void value (String newValue) {
if (! tableOfValues().containsKey(newValue))
throw new IllegalArgumentException("Illegal level of consciousness");
_value = newValue;
};

String value() {
return _value;
};

Enumeration legalValues () {
return tableOfValues().keys();
};

private Hashtable tableOfValues() {


return PhenomenonType.get("level of consciousness").mappingTable();
}

I’ve renamed them as I’ve gone. As far as the UI classes are concerned I don’t want to change anything, so I
want to still have the same accessors present in the facade, but these will now be simple delegates.
public String levelOfConsciousness () {
return levelOfConsciousnessAttribute().value();
};
public void levelOfConsciousness (String newValue) {
levelOfConsciousnessAttribute().value(newValue);
};
public Enumeration levelOfConsciousnessValues () {
return levelOfConsciousnessAttribute().legalValues();
};

I need to decide how I will represent the link from vitals facade to its satellites. I shall use a hashtable.
private Hashtable _attributes = new Hashtable();

The facade loads up the hashtable when it is created.


public class VitalsFacade {
public VitalsFacade (Patient subject) {
_subject = subject;
setupAttributes();
};
void setupAttributes() {
_attributes.put ("LevelOfConsciousness", new LocAttribute (this));
};

The accessors then use a common method to get hold of the attribute.

private LocAttribute levelOfConsciousnessAttribute() {


return (LocAttribute) _attributes.get("LevelOfConsciousness");
};

That handles the communication between the UI and facade with satellite. The UI does not know that the
world has changed. Now to re-stitch the facade to the domain model. The facade will still do loads and saves,
but in each case it will pass on the load messages to the satellites.
public void load() {
date = null;
loadAttributes();

void loadAttributes () {
Enumeration e = _attributes.elements();
while (e.hasMoreElements()) {
LocAttribute each = (LocAttribute) e.nextElement();
each.load();
};
};

Exactly the same thing happens with a save. On a load the locAttribute pulls in values from the domain
model.
public void load() {
_value = _facade.subject().phenomenonOf("level of consciousness").name();
};

The save is quite similar.


public void save() {
if (_value == null) return;
new Observation ((Phenomenon) tableOfValues().get(_value), true,
_facade.subject(), _facade.date());
};

Spinning off a satellite like this is quite easy. There is an immutable single valued link from the satellite to its
host. You don’t always need the back pointer from the satellite to the host, but in this case it seems
worthwhile, both for the subject and for the date. Having the tests is essential here because I can now run
them to make sure I didn’t break anything.

Refactoring the Heart Rate


The level of consciousness was easy, now its time for the heart rate. In this case we have both the heart rate
and the breathing rate to consider, and they do look very similar. I feel a superclass coming on. I’ll shout
“down boy” to that feeling for the moment. First spin off the satellite, then do the generalization. The steps
are familiar, first create the satellite.
class HeartRateAttribute {
private String _value;
private VitalsFacade _facade;
HeartRateAttribute(VitalsFacade facade) {
_facade = facade;
};

Move the accessing methods for the UI. IsNumeric gets moved too, but it looks just the same.
String value() {
return _value;
};
void value (String newValue) {
_value = (isNumeric(newValue) ? newValue : null);
};

The facade methods become simple delegates


public String heartRate() {
return heartRateAttribute().value();
};
public void heartRate(String newRate) {
heartRateAttribute().value(newRate);
};

private HeartRateAttribute heartRateAttribute() {


return (HeartRateAttribute) _attributes.get("HeartRate");
};

And finally the methods to load and save the attribute


public void load() {
_value = _facade.subject().latestAmountOf
(PhenomenonType.get ("Heart Rate")).amountString();
};

public void save() {


if (_value == null) return;
new Measurement (new Quantity (_value, Unit.get("beats/min")),
PhenomenonType.get ("Heart Rate"),
_facade.subject(),
_facade.date());
};

Even easier the second time. The only thing to be careful of is the loading and saving loops in vital facade.
They need to cast to something that understands load and save. This calls for an interface.
interface FacadeAttribute {
void load();

void save();
};

class LocAttribute implements FacadeAttribute {


class HeartRateAttribute implements FacadeAttribute {

That makes the load and save loops much better. I could have used a superclass here, but I felt that all I really
wanted was the typing of that load and save method, so an interface seems the easiest.
void loadAttributes () {
Enumeration e = _attributes.elements();
while (e.hasMoreElements()) {
FacadeAttribute each = (FacadeAttribute) e.nextElement();
each.load();
};
};

In my mind this desire to generalize the measurements is like a dog eager for attention. Well now its time for
walkies. What is different between the heart rate attribute class and the breathing rate attribute class? It’s the
values for the phenomenon type and for the units. So I don’t actually need to do inheritance here, I can just
create one class which takes those values as parameters. The parameters will get set in the constructor.
class MeasurementAttribute implements FacadeAttribute{
private String _value;
private VitalsFacade _facade;
private PhenomenonType _phenomenonType;
private Unit _updateUnit;
MeasurementAttribute ( VitalsFacade facade,
PhenomenonType phenomenonType,
Unit updateUnit) {
_facade = facade;
_phenomenonType = phenomenonType;
_updateUnit = updateUnit;
};

I change the load and save routines to use the new fields.
public void load() {
_value = _facade.subject().latestAmountOf(_phenomenonType).amountString();
};
public void save() {
if (_value == null) return;
new Measurement (new Quantity (_value, _updateUnit),
_phenomenonType,
_facade.subject(),
_facade.date());
};

So now I can set up the heart rate and breathing rates easily.
void setupAttributes() {
_attributes.put ("BreathingRate",
new MeasurementAttribute ( this,
PhenomenonType.get ("Breathing Rate"),
Unit.get("breaths/min")));
_attributes.put ("HeartRate",
new MeasurementAttribute ( this,
PhenomenonType.get ("Heart Rate"),
Unit.get("beats/min")));
_attributes.put ("LevelOfConsciousness", new LocAttribute (this));
};

Was it better to do it in two steps instead of one? My argument is that it is, because you can test after each
step and spot any mistake more easily. I’ll confess that in reality I didn’t, and regretted it. One day I’ll learn.

Now we can put our attention to the heart rate name and breathing rate name attributes. We could do these as
separate satellites, they are completely separate in the facade after all. But we do know that they are linked in
the domain model, so I’m prepared to use the information. First I add a method to measurement attribute to
give the name.
String name() {
return _facade.subject().phenomenonOf(_phenomenonType).name();
};

And then turn the facade method into a simple delegate


public String heartRateName() {
return heartRateAttribute().name();
};

That was so easy I’m tempted to do the same for level of consciousness, but I will wait until I have a need,
like building another choice box style attribute. Don’t let that stop you though.

Checking the Validity of a Measurement


There are some restrictions on our measurements. We shouldn’t enter negative heart rates, and numbers over
(say) a 1000 are probably too large. We should put some checking in for those. In those cases the checks
should be done by the domain model, by the phenomenon type class. The valid ranges will vary with the
phenomenon type, so it seems the right place to look for something.
Class PhenomenonType {
private QuantityRange _validRange;
public void validRange (QuantityRange arg) {
_validRange = arg;
};
public boolean validRangeIncludes (Quantity arg) {
if (_validRange == null) return true;
return _validRange.includes(arg);
};

We can check the valid ranges when we create the measurement.


public Measurement (Quantity amount, PhenomenonType phenomenonType, Patient patient,
Date whenObserved)
throws OutOfRangeException{
if (! phenomenonType.validRangeIncludes(amount)) throw new OutOfRangeException();
initialize (patient, whenObserved);
_amount = amount;
_phenomenonType = phenomenonType;
checkInvariant();
_phenomenon = calculatePhenomenonFor(_amount);
};

Now we have altered the interface of measurement creation to throw the exception. It is right here to throw a
matched exception, the client should be prepared to handle the exception. So what should we do? The easiest
thing is for the measurement attribute to set its value to null.
public void save() {
if (_value == null) return;
try {
new Measurement ( new Quantity (_value, _updateUnit),
_phenomenonType,
_facade.subject(),
_facade.date());
} catch (OutOfRangeException e) {
_value = null;
return;
};
};

That gives subtle but clear feedback on what went wrong.

The Shock Check Box


For the shock check box we have a slightly different case. The UI will want a Boolean attribute to work with
in this case. Vitals facade will oblige, and delegate to a satellite.
public boolean hasShock() {
return shockAttribute().value();
};
public void hasShock (boolean newValue) {
shockAttribute().value(newValue);
};

private ShockAttribute shockAttribute() {


return (ShockAttribute) _attributes.get("Shock");
};

We build the satellite in the usual way.


class ShockAttribute implements FacadeAttribute {
private Boolean _value;
private VitalsFacade _facade;

ShockAttribute (VitalsFacade facade) {


_facade = facade;
};

We can’t use the same interface for finding the value of the phenomenon, for shock is a phenomenon without
a phenomenon type. What the facade wants to do is to ask the patient if he is in shock.
public void load () {
_value = _facade.subject().isPresent(Phenomenon.get("Shock"));
};

The patient finds the latest observation of that phenomenon to answer the question.
public Boolean isPresent (Phenomenon value) {
return (latestObservation(value) == null ?
null :
new Boolean(latestObservation(value).isPresent()));
};

The patient can answer null, which means “I have no information”. The check box, however, wants true or
false, so the facade has to decide how to translate that information when asked. In this case it treats null as
false.
Class ShockAttribute
public boolean value() {
return (_value == null) ? false : _value.booleanValue();
};

We don’t have unknown problem when updating.


Class ShockAttribute
public void save () {
if (_value == null) return;
new Observation ( Phenomenon.get("Shock"),
_value.booleanValue(),
_facade.subject(),
_facade.date());
};

Adding the UI
Now it’s time to actually put the UI code in place. I could have built the UI incrementally as I did the facade,
but I wanted to wait before learning all about awt. The UI is a single class VitalsWindow. To refresh your
memory here’s what it looks like.
Figure 5 The vitals window

The window has fields for all of its interesting components, that is all the components that change during the
life of the window. The static labels, including the patient’s name, do not change once the window is created,
so I will set them up during creation.
package vitalsWindow;
import vitalsFacade.*;
import java.awt.*;
import java.util.*;
class VitalsWindow extends Frame {
private TextField breathingRate = new TextField ();
private Label breathingRateName = new Label ();
private TextField heartRate = new TextField ();
private Label heartRateName = new Label ();
private Choice levelOfConsciousness = new Choice ();
private Checkbox shock = new Checkbox("in Shock");
private Button updateButton = new Button ("Update");
private Button closeButton = new Button ("Close");

Setting up the window involves several stages in construction.


public VitalsWindow (VitalsFacade facade) {
_facade = facade;
loadChoices();
loadData();
setLayout(new BorderLayout());
setTitle ("Vital Signs: " + _facade.name());
add("North", nameLabel());
add("Center", readingsPanel());
add("South", buttonsPanel());
resize(500,200);
};

The window is given a facade to open on. All presentations would have such a link, their only link into the
rest of the system. My first step then is to set up those components that have fairly static choices, in this case
the pop up menu for level of consciousness.
private void loadChoices() {
loadLevelOfConsciousnessChoices();
};

private void loadLevelOfConsciousnessChoices() {


Enumeration consciousnessValues = _facade.levelOfConsciousnessValues();
while (consciousnessValues.hasMoreElements()) {
levelOfConsciousness.addItem((String) consciousnessValues.nextElement());
};
};

I would like to set the values of the choice all at once, but choice does not support that behavior, so its one at
a time.

The next step is to load the initial data into the component fields from the facade.
private void loadData () {
_facade.load();
breathingRate.setText (_facade.breathingRate());
breathingRateName.setText(_facade.breathingRateName());
heartRate.setText (_facade.heartRate());
heartRateName.setText(_facade.heartRateName());
levelOfConsciousness.select(_facade.levelOfConsciousness());
shock.setState(_facade.hasShock());
};

Now with all the data present, I can do the layout. The top level layout of the window uses the border layout.
The patients name goes at the top (“North”), the rest of the display goes in the middle (“Center”), and the
action buttons go at the bottom (“South”).

The patient’s name is easy. It is the only component in the top section, and it goes in centered horizontally.
private Label nameLabel() {
Label newLabel = new Label (_facade.name());
newLabel.setAlignment(Label.CENTER);
return newLabel;
};

The majority of the measurements go in the middle, and I use a grid layout with three columns for that.
private Panel readingsPanel() {
Panel newPanel = new Panel();
newPanel.setLayout(new GridLayout(0,3));
newPanel.add(new Label ("Gender: "));
newPanel.add(new Label (_facade.gender()));
newPanel.add(new Label (""));
newPanel.add(new Label ("Breathing Rate: "));
newPanel.add(breathingRate);
newPanel.add(breathingRateName);
newPanel.add(new Label ("Heart Rate: "));
newPanel.add(heartRate);
newPanel.add(heartRateName);
newPanel.add(new Label ("Consciousness: "));
newPanel.add(levelOfConsciousness);
newPanel.add(new Label (""));
newPanel.add(new Label (""));
newPanel.add(shock);
newPanel.add(new Label (""));
return newPanel;
};

The two buttons go at the bottom


private Panel buttonsPanel() {
Panel newPanel = new Panel();
newPanel.add(updateButton);
newPanel.add(closeButton);
return newPanel;
};

Once you get the hang of the layout managers, they are in fact very easy to use. You can easily set up roughly
where everything needs to go and the manager takes care of the details. You don’t get fine positioning, but I
usually don’t want to bother my ugly little head with that anyway.

Once the window is created it needs to do something. Really there is only two things it needs to do, as
indicated by the buttons.
public boolean action (Event theEvent, Object arg) {
if (theEvent.target == closeButton) {
closeAction();
return true;
};
if (theEvent.target == updateButton) {
updateAction();
return true;
};
return false;
};

If the user hits close, we just want to forget the whole thing.
private void closeAction() {
System.exit (0);
};
I wouldn’t recommend that response if the window is part of a larger application, but it’s fine for my limited
purpose.

The update is nearly as simple, since all the hard work is delegated to the rest of the system.
private void updateAction() {
_facade.breathingRate(breathingRate.getText());
_facade.heartRate(heartRate.getText());
_facade.levelOfConsciousness (levelOfConsciousness.getSelectedItem());
_facade.hasShock(shock.getState());
_facade.save();
loadData();
};

The use of loadData at the end is to ensure that the window is synchronized with the domain model.

There is an awkward interface point as the window stands. If I change the measurement number for breathing
rate or heart rate I need to change the string that indicates if is still fast. I can only do this by touching the
model. For this case I will take the simple option and clear that text field when I change the number. It will
get filled again when I update.
public boolean keyDown (Event theEvent, int key) {
if (theEvent.target == breathingRate) {
breathingRateChanged();
};
if (theEvent.target == heartRate) {
heartRateChanged();
};
return false;
};
private void breathingRateChanged() {
breathingRateName.setText("");
};
private void heartRateChanged() {
heartRateName.setText("");
};

Summing Up
That was a lot of material, what are the key points to remember?

Firstly the principle of separating the application into well defined layers. Clear separate layers for
presentation, application facade, and domain model make the code easier to maintain and test. Most of this
application can be operated without the UI. This makes it easier to work with and test.

Its worth spending effort to get the behavior into the right place. That does not mean that the behavior has to
start in the right place. Make a sensible first shot, but be prepared to refactor the code to improve it later.

Java is an application development language. The tools are somewhat primitive at the moment (I had terrible
trouble with Café’s debugger) but it is a full power language, much more than just something for creating
applets.

On the subject of applets, this technique should also be useful there. A good way of working across a network
is to load up a facade on the server and send it over to the client. There the presentation classes can
communicate with the facade and, when necessary, send it back to the server to communicate with the
domain model (I refer to this as stretching the facade in [Fowler]). You will need to put more state in the facade
for this case. This is a technique I’ve seen several times in networked systems, and I think it would work well
over the net.

References
[Beck] Beck K, Smalltalk Best Practice Patterns, Prentice Hall 1997
[Gang of Four] Gamma E, Helm R, Johnson R, and Vlissides J, Design Patterns: Elements of Reusable
Object Oriented Software, Addison-Wesley, 1995

[Fowler] Fowler M. Analysis Patterns: Reusable Object Models, Addison-Wesley, 1997

[Fowler, UML] Fowler M, UML Distilled: Applying the Standard Object Modeling Language, Addison-
Wesley, 1997.

[UML] Booch G, Jacobson I, and Rumbaugh J. The Unified Modelling Language for Object-Oriented
Development (version 0.91) Rational Software Corporation <http:\\www.rational.com>
Martin Fowler

UML Diagrams for Analysis Patterns

Martin Fowler

This is mostly an apology. I had best intentions of developing UML versions of my analysis patterns.
However it is a lot of work and I've been too busy with other projects. Chapter 2 is due to the kind
efforts of Michael Feathers. Igor Janicijevic has also stepped in adding diagrams for chapter 3, chapter 4,
and chapter 5. Jennifer Hansen provided diagrams for chapter 6. I'd also like to thanks others who had a
go, but for various reasons we couldn't get everything fully sorted out.

If anyone else reading this fancies having a go at some chapters I would be welcome for the help. I'll
happily check the diagrams, post them on this page, and give you the credit.

http://www.martinfowler.com/apsupp/uml.html05/12/2003 15:36:59
Using an Agile Software Process with Offshore Development

About Contact
Home Blog Articles Books ThoughtWorks
Me Me

Using an Agile Software Process with Offshore


Development
Martin Fowler

Last Significant Update: September 2003

For the last two years ThoughtWorks has operated a lab in Bangalore India to support our software
development projects in North America and Europe. Traditional approaches to offshore development are
based on plan-driven methodologies, but we are very firmly in the agile camp. Here I discuss our
experiences and lessons learned in doing offshore agile development. So far we've discovered that we can
make it work, although the benefits are still open to debate.

● Lessons Learned
❍ Use Distributed Continuous Integration to Avoid Integration Headaches

❍ Have Each Site Send Ambassadors to the Other Sites

❍ Don't Underestimate the Culture Change

❍ Use Test Scripts to Help Understand the Requirements

❍ Use Regular Builds to Get Feedback on Functionality

❍ Use Regular Short Status Meetings

❍ Use Short Iterations

❍ Use an Iteration Planning Meeting that's Tailored for Remote Sites

❍ When Moving a Code Base, Bug Fixing Makes a Good Start

❍ Separate teams by functionality not activity

❍ Expect to need more documents.

● Costs and Benefits of Offshore Development


● The Future of Offshore and Agile
● Further Reading

One of the fundamental tenets of any agile software methodology is the importance of communication
between the various people involved in software development. Furthermore agile methods put a large
premium on improving communication through face-to-face communication. As the agile manifesto states
"The most efficient and effective method of conveying information to and within a development team is
face-to-face conversation." Extreme Programming emphasizes this with its practice of a single open
development space where the team can work closely together. Cockburn's book spends a lot of time

http://www.martinfowler.com/articles/agileOffshore.html (1 of 10)05/12/2003 15:37:00


Using an Agile Software Process with Offshore Development

talking about the importance of physical proximity in agile methods.

Another trend that's been grabbing the software development world recently is the move to offshore
development, where much of the development work is done in lower paid, ahem more cost effective
countries. Offshore development seems opposed to agile development in a couple of ways. For a start it
immediately goes against the notion of physical proximity, since by definition offshore developers are a
long way away. Secondly most offshore organizations favor the plan-driven approach where detailed
requirements or designs are sent offshore to be constructed.

So the fundamental question is whether agile techniques can be used in an offshore setting. If so how does
it compare to using an plan-driven methodology (the term I'll use here for non-agile)?

The experiences I'm writing about here are based on work done over the last couple of years by
ThoughtWorks. We opened an office in Bangalore India in 2001 and have done several projects which
have used a Bangalore based team. We've also done some offshore development with our Melbourne
office. In these projects we've committed to using as much of an agile approach as possible, since we
believe that agility is an approach that's in the best interests of our customers. In this essay I'll describe
some of the lessons we've learned so far.

To help provide some context, it's worth talking a little about the way in which we've setup the Bangalore
office. We expected the office to be used primarily as an offshore development environment, so we
recruited mostly application developers. The majority were hired directly out of college and we seasoned
the mix with some more experienced developers. It was very important to us that we retained our very
high hiring standards (typically we only offer jobs to about 1 in 200 applicants), and we continued the
model in India. As a result we have a very talented group of developers but with a mix of experience
levels. We also brought over several more experienced US developers, to mentor the newer developers on
both software development and the agile/XP practices we've come to enjoy. Currently we have about forty
developers in Bangalore.

The Melbourne office is a very different story. Here we set up the office expecting it to work primarily on
Australian work, which is now the case. In the early days of the office we did some offshore work while
we were trying to get Australian work. The team is equally talented but we tended to hire a larger
proportion of experienced developers.

Lessons Learned

Use Distributed Continuous Integration to Avoid Integration Headaches

I've heard several stories about problems with integrating the work across multi-site teams. Even with a lot
of care put into defining interfaces, integration problems still rear their ugly head. Often this is because it's
very hard to properly specify the semantics of an interface, so even if you have all the signatures right, you
still get tripped up on assumptions about what the implementation will actually do.

http://www.martinfowler.com/articles/agileOffshore.html (2 of 10)05/12/2003 15:37:00


Using an Agile Software Process with Offshore Development

The earliest XP practice to really take hold at ThoughtWorks was Continuous Integration, and we've
become so accustomed to it that we were determined to use it with our offshore development. So from the
beginning we've put everyone on a single code base, with CruiseControl running to both build and run
tests. This way everyone is kept close to the mainline, whatever their location happens to be.

Everyone has been delighted with how well this works. It's main benefit is that problems that plague other
groups with integration just don't happen to us. The continuous integration and test process flushes out
many integration problems very quickly, as a result they can be fixed before they become hard to find.

CruiseControl's web page allows all sites to see what's going on abroad. First thing in the morning you can
check the CruiseControl web page to see what changes have been made by the other sites. It provides an
easy way to catch up on what's going on at the other end of the world.

This does require good build discipline, where developers strive hard not to break the build, and fix it
immediately if it becomes broken. It's generally accepted practice that if you commit changes to the
mainline, you should not go home until you have received the email message from CruiseControl that says
that your changes resulted in a successful build. A late night bad build is much more serious when the
remote office is running off the same build.

Although world-wide Continuous Integration is resoundingly popular, we have run into some problems.
Communication pipes aren't as wide and reliable as we'd like, so many source control operations can get
awkward from a remote site. In general we keep the build servers in the same site as the majority of
developers, but remote sites can find it takes an annoyingly long time to get a fresh update from the
mainline. The longer the communication lines are, the more they are prone to anything from glitches to
lines being down for a while. Having the repository accessible 24 hours makes it annoying to take it down
to do backups. All of these issues would mitigated by a clustered code repository, but we haven't
experimented with anything like that yet.

(Interestingly people assume that these communication problems are specifically a problem with a remote
site like India - but we've found problems often occur with the infrastructure in the west too. Continuous
Integration requires good connetivity, often better connectivity than people are used to.)

Have Each Site Send Ambassadors to the Other Sites

As I've said above, agile methods stress the importance of face to face human interaction. Even if
everyone cannot be co-located, moving some people about clearly helps a lot. From the beginning we
decided to ensure that at all times there was someone from the US team present in India to facilitate the
communication. Such an ambassador already knows the US based people and thus adds his personal
contacts to help everyone communicate.

We've now expanded this to several levels. We found it useful to send a US developer and a US analyst to
India to communicate on both technical and requirements levels. It's also valuable to send someone from

http://www.martinfowler.com/articles/agileOffshore.html (3 of 10)05/12/2003 15:37:00


Using an Agile Software Process with Offshore Development

India to the US team. The plane fares soon repay themselves in improved communication.

One of the benefits of a business-oriented ambassador on the offshore team is that it helps provide
business context to the offshore team. Building software off just a list of requirements misses out a lot
business context - developers are told what to do without being told why it's important. The why often
makes a big difference in doing the what properly.

An important part of the ambassador's job is to communicate gossip. On any project there's a lot of
informal communication. While much of this isn't important, some of it is - and the trouble is that you
can't tell which is which. So part of an ambassadors job is to communicate lots of tidbits which don't seem
important enough for more formal communication channels.

We usually rotate the ambassadors every few months. This makes it easier for the ambassadors, who don't
want to be away for too long. It also allows more people to get to know the remote team by spending time
as an ambassador. In choosing ambassadors it's very important to pay attention to individual needs and
preferences. Some people don't want to spend several months thousands of miles away from home, so they
shouldn't be ambassadors.

We've also found that it's important for project managers to spend some time as ambassadors. Much of a
project manager's job is to help resolve conflicts and flush out problems before they become serious.
Experience working on both side of the telephone line is really important for them to do that effectively.

Don't Underestimate the Culture Change

One of the hardest parts of introducing agile methods into an organization is the cultural change it causes.
Indeed we've found that this is the major reason why organizations have problems with adopting agile
methods. Many companies operate with a command and control model which assumes that seniors make
decisions and lower level people carry them out. To make agile methods work you need much more
autonomy and decision making by the doers.

We find this to be a big problem in western companies, but the problem is amplified in Asia since Asian
cultures reinforce deference to superiors. (A training course I saw from a major Indian contracting
company defined management as "the science of control".) In this environment people are often
discouraged from asking questions, talking about problems, warning about unfeasible deadlines, or
proposing alternatives to perceived instructions from superiors.

The bad news for this is that getting teams to be more pro-active is an uphill battle, and one that inevitably
takes a lot of time. You can never assume that problems will be raised, even when they are spotted.
Getting people used to a distributed control style of management takes longer than you think.

But there is good news. Once people realize they have the freedom, and the responsibility, of making
decisions - they seem to really relish it. Several of our Indian team told me how their friends in other
companies cannot believe how much autonomy they are given. This autonomy is a great motivator,

http://www.martinfowler.com/articles/agileOffshore.html (4 of 10)05/12/2003 15:37:00


Using an Agile Software Process with Offshore Development

allowing people to be both more productive and able to grow into greater responsibility. For me one of the
most interesting things we will discover is what the longer term effects are of this cultural impact, both in
Asia and in the West.

Even talking about these cultural issues can cause problems. Some (western) industry analysts who saw a
draft of this article said that this section was patronizing and offensive. One of our developers in
Bangalore said I'm being far too mild. Another commented that it's an issue, but questioned as to whether
it was worse that it is in many western companies. But there seems to be some consensus that there are
cultural forces in Asia that reinforce command and control, and that this is changing.

(This is a particularly sharp issue for ThoughtWorks. We have a pronounced anti-authority attitude that's
striking even in the US. We decided from the beginning that we would retain that same culture in India.
I'm glad to say that we certainly seem to be succeeding.)

Use Test Scripts to Help Understand the Requirements

With greater distance, you need to put more ceremony into communicating requirements. We've been able
to do that while still sticking to many of the techniques that we use in single-site development.

Increasingly I've found that more mature XP teams use acceptance tests as ways of communicating
requirements. Such teams get test scripts written out before the start of an iteration to help clarify the
requirements and give the development team a concrete target to aim at. One style that's worked well is for
a US based customer to write a short narrative (a couple of pages) to flesh out a feature (story in XP
lingo). An Indian based analyst/tester then creates test scripts for this story. This can be done either for
automated or manual testing, although we very much prefer automated tests. As the scripts are developed
the US and Indian analysts coordinate by email and IM as well as regular (2-3 times a week) conference
calls to review the test scripts.

We've found that this has very much helped both the Indian analyst and the US customer really understand
the requirements. Writing out the tests forces the Indian analyst to really understand what's needed and to
ask questions of the US customer as questions turn up. The developers find it easier to ask questions of the
Indian analyst rather than dig through the test scripts, so having an Indian analyst/tester is still important.
Search engines are good, but humans are often easier to work with.

Use Regular Builds to Get Feedback on Functionality

When people consider the requirements gathering in agile methods, they often fail to see the importance of
the feedback loop. Often the requirements process is seen as analysts providing requirements, which
developers go off and implement. At some later point the analysts check to see if the developers have
implemented what they were asked for. On an agile project, the close proximity between customer and
developer allows the customer to monitor progress much more frequently, which allows them to spot
misunderstandings more quickly. Furthermore a partially developed system can also educate the customer,

http://www.martinfowler.com/articles/agileOffshore.html (5 of 10)05/12/2003 15:37:00


Using an Agile Software Process with Offshore Development

for often there's a difference between what's asked for and what's needed - and usually that's not apparent
until there's some working software.

Having regular integrated builds allows a US customer to pull down last night's work and try it out. While
this isn't quite as immediate as co-location, it still allows the customer to correct any misunderstandings
quickly; as well as allowing them to refine their own understanding of the requirements.

To make this work, it's critical to sort out the environment issues so that you properly duplicate the
environment on both sides of the ocean. There's nothing worse than onshore people pulling down a build,
finding problems, and the offshore people being unable to duplicate the problem due to environment
configuration issues. Make sure the environment is sorted out early, and ensure someone is around to fix
any environment problems if they appear.

Use Regular Short Status Meetings

Agile methods promote regular short status meetings for the entire team (Scrums in Scrum, stand up
meetings in XP). Carrying this over to remote groups is important, so they can coordinate with other
teams. Time zones are often the biggest problem here, particularly between the US and India where any
time is awkward for somebody. On the whole we've found that twice a week stand-ups seem to work well
and provide enough coordination.

With time zone problems it's important for both sides to give and take in picking the time for calls. One of
our clients would only do the calls during their business day, which forced the Indian folks to come in at
very awkward hours. Pushing all the onus on one side to accommodate isn't helpful for smooth
collaboration.

Use Short Iterations

In general agile methods use shorter iterations than a lot of other iterative approaches. At ThoughtWorks
almost all projects use iterations of one or two weeks in length. A few of the more experienced Indian
developers have worked at places which use two to three month iterations and they report that the shorter
iterations are much better.

We have found that while onshore-only projects seem to be gravitating to one week iterations, the offshore
projects feel that two weeks is a minimum due to the communication overhead.

Use an Iteration Planning Meeting that's Tailored for Remote Sites

On most of our projects we've found that a planning meeting at the beginning of each iteration that
involves the whole team really helps to get everyone coordinated on the next chunk of work. I've noticed
that most of our projects have come up with their own variation of the Iteration Planning Meeting (IPM) to
suit the local circumstances. (This kind of self-adaptation is an important part of agile processes.)

http://www.martinfowler.com/articles/agileOffshore.html (6 of 10)05/12/2003 15:37:00


Using an Agile Software Process with Offshore Development

A remote team adds its own set of constraints, particularly when you have awkward time zone issues.
However despite the pain of awkward meeting times, we still find the IPM to be extremely useful.

Before the IPM the US customer sends narratives for each scheduled feature (story) which most projects
turn into test scripts before the IPM. During this period any questions are handled by email. Just before the
IPM the development team breaks the features down into finer grained tasks. These task breakdowns are
shared with the US for feedback.

All of this pre-work shortens the phone call which now concentrates on any issues that come up from the
task breakdown. We find the calls usually last around a half to a couple of hours.

When Moving a Code Base, Bug Fixing Makes a Good Start

Two of our projects involved taking a large (hundreds of thousands of lines of code) code base and
moving substantial development of the code base to the Bangalore lab. In both of these projects the Indian
team began with a few iterations of bug fixing before they started adding new functionality.

Starting with bug fixes allowed the Indian team to become familiar with the code base, before they did
substantial work on it, since bug fixes involve more code reading than changing. Although this worked
well, there is some concern that more experienced people may consider it to be a stigma to be doing only
bug fixes. While some people may perceive this as a problem I believe that working on bug fixes or very
localized feature changes is one of the best ways to get familiar with a large new code base.

Separate teams by functionality not activity

Much of the traditional thinking on the onshore/offshore boundaries is based on the activity that people do.
So analysis and design is done onshore, construction done offshore, and acceptance testing is done
onshore. This obviously fits well with the waterfall model.

We've found that contrary to this, matters improve when we make the offshore team handle as many
activities as possible. So we prefer to see them do as much analysis and design as possible, subject to the
limitations that the requirements are coming from onshore. When we do split an effort with onshore and
offshore development teams, we do this along functionality grounds rather than activities. We break the
system into broad modules and let the offshore team tackle some of these modules. However unlike most
groups that do this, we don't make a big effort to design and freeze the interfaces between these modules:
continuous integration and weak code ownership allow the module interfaces to evolve as development
goes on.

An important part of this is to grow the analyst part of the offshore team. The more someone local to the
developers understands of the business, the more the development team can develop efficiently. So this
means that you have to focus on growing the business knowledge of the offshore analyst. This takes time,
but the local knowledge is a vital counterpart to the business knowledge onshore.

http://www.martinfowler.com/articles/agileOffshore.html (7 of 10)05/12/2003 15:37:00


Using an Agile Software Process with Offshore Development

Expect to need more documents.

Agile methods downplay documentation from the observation that a large part of documentation effort is
wasted. Documentation, however, becomes more important with offshore development since the face to
face communication is reduced. This work is, in a way, a waste since it wouldn't be needed if the whole
team was co-located. But given the offshore model, you need to do them - so they are part of the price of
doing things offshore. That's a price in the time for people to write them, the added time because it's
harder for people to understand many things from a document, and also a price in frustration when people
are using them.

As well as documents, you also have more need for more active collaboration tools: wikis, issue tracking
tools and the like. On the whole it seems that it's often better to favor tools that impose less structure, that
way the team can fit them better into how they want to work (one of the reasons that wikis can work so
well.)

Whether it's documents or anything else, remember that other people's templates won't work for you, and
you won't come up with the right scheme at the beginning. Make sure there's plenty of communication
about the form of the documents and how well they are working. Expect to evolve the structure of
documents as you learn what works best for your team.

There are two keys to successful documentation on agile projects. The first is finding the
point of "just enough" documentation. This is difficult to determine and will vary by project.
Fortunately, the iterative nature of agile development allows you to experiment until you get
it right. The second key to successful agile documentation is to not get attached to it or have
unrealistic hopes of keeping it updated. Documentation must be created to serve a specific
purpose, and after it has served that purpose you'll all probably have more important things
to do than keep updating the documents. It may seem counterintuitive, but it's often better to
produce fresh documentation the next time some is clearly required. A side benefit of
starting over each time you need to document part of your project is that it's great incentive
to keep your documentation efficient!
-- [Simons]

Costs and Benefits of Offshore Development


There's still many differences of opinion, both within the general enterprise software world and within
ThoughtWorks, about the costs and benefits of using offshore development. The reason why most people
look to offshore is to reduce costs, noting the significantly lower rates that you find from offshore vendors.
However it's foolish to look only at rates. Rates are only one component of costs, and in any case you have
to look at the entire return on investment. Most people in the software industry know, or should know, that
productivity differences between developers are far greater than salary differences - and even the rate
differentials offered by offshore aren't necessarily greater than that. Offshore work also introduces extra

http://www.martinfowler.com/articles/agileOffshore.html (8 of 10)05/12/2003 15:37:00


Using an Agile Software Process with Offshore Development

costs and risks that may offset the rate differential.

The biggest consequence is the effect on communication. Offshore makes communication harder both due
to the distance, which makes it difficult to meet face to face, and the timezone offset. Both of these
increase the likelihood of building the wrong functionality as mis-communications occur over
requirements. While techniques such as using ambassadors tries to reduce it, there's still going to be some
effect. Also the distance between development and business also reduces the motivation of the
development team,since they have no personal relationship to build on.

Of course a high ceremony organization that uses documents as the primary communication mechanism
will not suffer as much from this. Essentially their communication has already taken all the damage from
lack of direct contact, so the offshore effect is less notable. Agile methods try to restore the direct contact
in order to improve communication. Our experience is that even if an agile approach suffers from the
communication difficulties of offshore, it's still better than a documentation-driven approach.

Another trend may work to help with this problem. Increasingly companies are moving other business
process functions offshore. If a company moves its accounting function to India, then software to support
them can be built in India more easily than it could be in the west. If this kind of movement of business
work offshore continues, then Indian development could become the onshore alternative.

Another benefit of offshore that's coming up is the use of 24 hour development to reduce time to market.
The benefit that touted is that by putting hands on the code base at all hours of the day, functionality gets
written faster. I must admit this seems a somewhat bogus argument to me, since I don't see what adding
people does in India that it wouldn't do by adding them to the onshore team.

The nugget in the 24 hour development idea is that despite the tech slowdown it's still not easy to get
talented developers. So often you can't get enough talented developers in the onshore location, so an
offshore team is valuable for their talent rather than any lower cost.

Among all these differences my point of view is clear: I'm sitting on the fence!

The Future of Offshore and Agile


As I write this, offshore development is very fashionable, but it's still too early to really understand its true
strengths and pitfalls. Certainly anyone doing because they think they'll get cost savings similar to the rate
differences is seriously deluding themselves. Some people talk about all software development moving to
the third world in the same way that the steel industry did, others think that after a period of fascination the
offshore industry will dry up. My crystal ball just shows me what's in front of me, in a slightly distorted
way.

One conclusion is clear, anyone who thinks that onshore developers will triumph because they are more
skilled is very wrong. We've found that we can hire just as talented developers in India as we can in North

http://www.martinfowler.com/articles/agileOffshore.html (9 of 10)05/12/2003 15:37:00


Using an Agile Software Process with Offshore Development

America and Europe.

The weak spots of offshore development come from culture and distance with the business. Because agile
development works best with close communication and an open culture, agilists working offshore feel the
pain much more than those using plan-driven approaches. But it's still less pain than the plan-driven
methods themselves!

We may never really understand the pros and cons offshore development. Software development is an
activity who's output is impossible to measure. As such we'll never have hard numbers to prove one
approach better than another. What we will see is growing qualitative feedback on the benefits of agility
and offshore development - these qualitative assessments will determine if either, or both, will survive.

Further Reading
Matt Simons, one our project managers who has been the most involved with our Bangalore lab, has
written several articles on his experiences. One that's easily available is Internationally Agile which you
can find on informit.com (I'm afraid I haven't figured out how to get a stable link to the article itself.)

Revision History

Here's a list of the major updates to this paper

● September 2003: First published

© Copyright Martin Fowler, all rights reserved

http://www.martinfowler.com/articles/agileOffshore.html (10 of 10)05/12/2003 15:37:00


Canadian Workshop on Scaling XP/Agile Methods

About Contact
Home Blog Articles Books ThoughtWorks
Me Me

Canadian Workshop on Scaling XP/Agile Methods


Jonathan Rasmusson

Jim McDonald

Last Significant Update: March 2003

As XP and other Agile methods gain popularity, questions are beginning to surface regarding how to scale
XP beyond teams of 10-12 people. In mid February 2003 a workshop dedicated to the subject was held in
Banff Alberta Canada. In this article we report on the keynote speeches from Ken Schwaber, and Martin
Fowler, as well as other leading practitioners.

● Questions raised
● Ken Schwaber
● Reports from the field
● Martin Fowler
● Where's the proof?
● Summary

http://www.martinfowler.com/articles/canScaling.html (1 of 6)05/12/2003 15:37:02


Canadian Workshop on Scaling XP/Agile Methods

Questions raised
In preparation for the conference participants were asked to submit their views on how to scale XP and
Agile methods for large teams. Depending on whom you ask, the definition of large can vary anywhere
from 20-200 plus developers.

Specific questions posed to conference participants were:

● How scalable are the agile methods?


● What has been the experience of early adopters?
● What experiments can we conduct to expand the use of those methods?

Having participated in several XP projects, we were keen on hearing how others viewed scaling XP as
well as share our own experiences with XP on large teams.

Ken Schwaber
The first keynote speaker was Ken Schwaber. Ken and Jeff Sutherland are the authors and founders of the
Scrum agile methodology. Ken started by describing his experiences working with Scrum on large
projects and several techniques he had successfully used in the early stages of the project life cycle.

Ken explained on one project how the team was very concerned with getting the overall architecture of the
system proven in the early stages of development. Early project iterations (sprints in Scrum terminology)
contained stories focused on proving the system architecture peppered with several real business cases.
After several iterations, during which the architecture was continuously refined and tested, the team had a
good sense of whether the architecture was sufficient for the demands of the business.

Scaling was then achieved by starting new teams with the founders of the original architecture team. With
most of the architectural issues addressed, the new teams could focus on implementing business logic on
top of the then stable architecture.

Ken also emphasized the importance of having a Scrum master who did not manage the team - rather it
was very important that the team managed itself. Ken found teams were much more effective when they
were self-organizing and could decide for themselves how best to complete the work they were given.
This was a challenge for managers who were used to a command and control style of leadership and was
initially very counterintuitive.

An interesting point Ken touched on was how outsiders would initially perceive Agile methods. As with
all things new that have achieved some element of success, people will naturally ask how this can work for
them. Is this the "silver bullet" they have been looking for? Ken wondered if XP and Agile were to suffer a
similar fate to CMM (Capability Maturity Model).

http://www.martinfowler.com/articles/canScaling.html (2 of 6)05/12/2003 15:37:02


Canadian Workshop on Scaling XP/Agile Methods

CMM had many great people behind it, articulating things that companies could do to improve their
chances of success on software projects, and demonstrate software process maturity. However, CMM has
never been embraced and successfully implemented to the degree the authors had originally intended. It
was reported that 2/3 of CMM project implementations were broken. Further, many in industry took on a
cynical view of CMM when the level of certification a company could achieve was often dependant on
who they hired to perform the certification.

Will Agile methods suffer a similar fate? Sure the early adopters have had success, but these teams are
often filled with highly skilled, motivated, people who are passionate about writing software. Arguably,
teams filled with these types of people would have been successful regardless of the methodology used in
name or practice.

In our opinion, this has less to do with Agile, and more the inescapable fact that people have a first order
effect on projects. This becomes apparent when you look at the converse of building these sorts of teams
(less skilled, unmotivated, people who are not passionate about writing software). For these teams, no
methodology used in name or practice will make them successful.

While Ken agreed that excellent developers help make the process hum, in his experience it has been
equally true that people who have been categorized as average, or even poor, often rise to excellence given
a supportive, creative, team oriented environment as provided by Agile. He has seen previously disparate
groups of average professionals accomplish truly great things that he previously thought only the top tier
people could perform.

Reports from the field


The middle part of the conference was reserved for other practitioners and researchers to share their
thoughts and experiences with large projects.

Philippe Kruchten (Rational) described how large teams (200+ persons) using RUP had successfully
delivered large projects in the past. In the earlier project stages, a team consisting of senior practitioners is
used to complete the initial high-level architecture and set the development practices.

As the project moves into the construction phase, more teams are added (seeded with founders of the
elaboration team). When broken up appropriately, each team can work fairly autonomously (in an iterative
cycle). In those instances where one team needs components built from another, sync points and
milestones can be coordinated between the two. Handling large projects this way gave teams the illusion
they were decoupled enough to gain the advantages of small Agile teams.

Gerard Meszaros of ClearStream Consulting shared his experiences working with large teams building
digital switches at a large telecommunications company. They used frequent releases and had significant
architectural change throughout the life cycle of the project. However, the system had reached critical
mass before they were able to do this.

http://www.martinfowler.com/articles/canScaling.html (3 of 6)05/12/2003 15:37:02


Canadian Workshop on Scaling XP/Agile Methods

Gerard also raised an interesting point regarding the current industry literature regarding XP and Agile
practices. In his opinion, most of today's literature is targeted towards people who already know how to
develop software. If XP is going to be brought beyond the early adopters, a very different set of literature
will be required. To repeat the analogy used: "Today we have the cook books for people who know how to
cook. What we do not have today are cook books for people who do not know how to cook."

A large Canadian energy company shared their experiences regarding Agile adoption within their
company. Using a combination of Scrum and XP, they have had great success in managing projects. With
managements backing, they now have a team dedicated to showing other groups within the company how
Agile can be used to increase their chances of success. Further comments regarding XP and Scrum were
the ability it provided teams to adapt and modify the practices to meet each individual teams needs. They
preferred this to the one size fits all form of project management they had used in the past.

The authors (Jonathan Rasmusson and Jim McDonald) were also given the opportunity to share our own
experiences with XP and large teams. Because we had mostly worked with XP, we looked at the core
practices and broke them into two groups - those practices we thought could scale, and those that would
not.

We believe the XP practices related to the mechanics of writing coding could be scaled. We see little that
will prevent large teams of developers from writing tests, refactoring, and pair programming. People have
been successfully practicing these techniques for many years (before XP or Agile) on both large and small
projects. These are simply good practices.

However, those practices that were communication centric will be challenging to scale. For instance daily
standup meetings would become awkward with teams of 20+ people. Iteration planning meetings, where
all the developers and analysts gather to plan the upcoming iteration, would be tough to manage due to the
organizational and communication overhead with coordinating so many people. The greatest challenge we
see with scaling XP, is the same challenge we see every large project faces - how to effectively
communicate and coordinate large numbers of people.

We also start to question the question itself. Why do people want to scale XP? With success on small
teams, it seems very counter intuitive to us to want to scale. Rather, we would prefer to first look for
alternatives on how large projects could be scaled down to the size where we know XP works well.

Martin Fowler
The last day of the conference started with a keynote from Martin Fowler titled "Why Scaling Agile is the
Last Thing You Want To Do". The title of his keynote changed the tone of the conference. Up until that
point, much of the conference was dedicated towards trying to answer the question around how to scale
XP. Martins keynote however turned the question on its head and asked the audience if this is something
we really want to do.

http://www.martinfowler.com/articles/canScaling.html (4 of 6)05/12/2003 15:37:02


Canadian Workshop on Scaling XP/Agile Methods

His talk was broken into two parts. The first part was an experience report regarding a ThoughtWorks
project involving a large team using a XP type of process on a complex leasing application. The second
part further expanded on the title explaining why we should look for alternatives before trying to scale XP.

Martin started by reminding us why building complicated business applications is challenging. Business
logic is an oxymoron. There is nothing logical about most aspects of business (especially leasing).
Capturing the business rules, hidden assumptions, special cases and abstracting these into a solid, war
crafted domain model one of the most challenging parts of software design.

Requirements gathering is also very tough on large projects. Martin provided an interesting comparison
between writing requirements documentation and writing books. Writing a book requires a very large
investment of time and energy. Even after peer reviews and feedback from professional editors, the author
still is not always successful at communicating his/her intended message to the audience. His point was
that if authors have a hard time doing this with books, imagine what it must be like to capture the
requirements around a complicated business application given far fewer resources.

One practice that worked very well on the project was the rotation of people to different parts of the
application. This was initially frustrating for the project analysts as a developer just was beginning to
understand the problem domain when they would moved to another part of the system. As the project
progressed however, the benefits of moving people to other parts of the application began to pay off.
Eventually, most developers knew enough portions of the application that they could fill in many roles.
There was less dependence on a small number of people to do work in specific parts of the application.
The developers themselves became stronger both technically and in the business domain. Having a more
global view of the application gave them insight into how best implement new features while maintaining
the overall system architecture.

The latter part of Martins keynote focused on why we should look for alternatives to scaling agile. Some
projects do require large teams. The amount of work needed to be complete is often too large for a small
team to handle within a reasonable period of time. Examples of this are projects from the
telecommunications industry and large military applications. For these teams, the question of how to scale
Agile is very real.

Martin's experience however was that many teams were unnecessarily large. These teams should look for
alternatives (like scaling the team size down) before trying to scale Agile. Martin asked the audience to
raise their hand if they had ever been on a project that could have kept about the same level of productivity
after removing the weakest half of the team. The majority of the room raised their hands. This seemed to
reflect that many in the audience had similar experiences and worked on projects where the teams had
been much larger then necessary. Hence, instead of first looking at ways to scale XP and Agile, Martin
recommended teams first look for ways of scaling down projects that are unnecessarily large.

Where's the proof?


One of the questions attendants seemed to have difficulty answering was what experiments would provide

http://www.martinfowler.com/articles/canScaling.html (5 of 6)05/12/2003 15:37:02


Canadian Workshop on Scaling XP/Agile Methods

empirical evidence that XP/Agile can be utilized on large projects. The academic/research community has
taken on the challenging task of coming up with experiments and empirical evidence that Agile methods
can scale to large teams.

While we empathize with the researchers desire to prove that Agile works, we see several challenges in
proving it. Jonathan sees the challenge as trying to objectively measure software quality and productivity.
Without definite, quantifiable measures around quality and productivity, how can one conduct
experiments around software engineering practices? Jim believes that the path to truly understanding Agile
is through the study of sociology and studying the difficulty in quantifying and describing how humans
interact. With communication playing such a pivotal role in Agile projects, he feels research in these areas
would shed more understanding into why Agile works.

Summary
The conference itself was a great success and all attendants enjoyed the opportunity to share their thoughts
and ideas on how best to tackle the challenging problems put forward by the research community. It seems
XP and other Agile processes are starting to gain the attention of the academic world and are beginning to
be taken seriously. Regardless of any advice provided by early adopters, it seems clear that like any new
tool, XP will be applied and misapplied in the upcoming years.

Revision History

Here's a list of the major updates to this paper

● March 2003: First published

© Copyright Martin Fowler, all rights reserved

http://www.martinfowler.com/articles/canScaling.html (6 of 6)05/12/2003 15:37:02


The XP 2002 Conference

About Contact
Home Blog Articles Books ThoughtWorks
Me Me

The XP 2002 Conference


Martin Fowler
Chief Scientist, ThoughtWorks

This year the XP conference was again in Sardinia, this time in the town of Alghero.

Last Significant Update:

At the end of May 2002, the XP community once again descended on the Mediterranean island of
Sardinia. In this article I look at the plenary speeches from Ken Schwaber, David Parnas, Enrico
Zaninotto, Bill Wake, and the Standish Group's Jim Johnson. They lead me into some thoughts on the
essence of agile development, the role of mathematical specifications, the complexity of irreversibility,
metaphor, and the best way to drastically cut software costs.

| Japanese |

You can find the actual slides used for the talks at http://xp2002.org/.

● Remember the Spirit


● Produce Good Documentation
● Using Practices Discarded Twenty Years Ago
● Metaphors for XP Practices
● Build only the Features You Need

http://www.martinfowler.com/articles/xp2002.html (1 of 11)05/12/2003 15:37:05


The XP 2002 Conference

Remember the Spirit


The conference proper began with a talk from Ken Schwaber. Ken opened with the theme that agile
development is not just a repackaging of a bunch of old techniques, but something that is new and
revolutionary. Articles that saw agile as a variation on an old theme, such as Barry Boehms recent IEEE
Computer article, just didn't get what made agile special.

Schwaber characterized Scrum as a product development methodology that went beyond just software. He
said that XP provided engineering practices that were missing in so many IT organizations, and the
resulting blend of XP and Scrum was the most pure of the agile processes.

Giancarlo Succi and Michele Marchesi, the two organizers of the three XP conferences in Sardinia. Sadly this year is the last
on Sardinia before it moves elsewhere.

In his experience there two kinds of projects that were interested in agile, those that were in trouble and
those that were curious. He found the former better because they would follow agile advice, while the
latter would mostly say "but" to various ideas. He criticized the common approach of taking some ideas
from agile methods, saying that it was like taking a fine spring out of a well crafted Swiss watch.

Schwaber suggested several markers for true agility:

● Manager feels it's okay to proceed without all the requirements


● Business people are excited about delivering software
● Engineers are heard when they have problems
● A sense of buzz in the building
● The team makes the decision of how to do the work
● People don't talk about the usual roles

He said that agile is a power shift, one that returns IT to the business. In business terms ROI (return on

http://www.martinfowler.com/articles/xp2002.html (2 of 11)05/12/2003 15:37:05


The XP 2002 Conference

investment) is the only real measure of success. The great danger to agile was the that people focused too
much on the practices and forgot the bigger picture, the revolutionary aspect of agile development.

The interplay between practices and philosophy is one that's dogged the agile and XP communities for a
while. I think this is particularly the case with XP since it contains both some important philosophical
approaches to the way software is developed, as well as some very concrete practices for doing it. This led
to a real question as to what really is the essence of XP - is it the practices or the underlying philosophy?
This is particularly noticeable since as you get more experienced in XP the actual following of the
practices becomes less important. But at the same time you have to do the practices to get any sense of
what XP is really about, (this is a conundrum I explored in Variations on a Theme of XP).

In many ways I think the "agile" label helps us to think about the separation more easily. The real value of
the get together at Snowbird was that those there found so much agreement on philosophy even though
there were differences in the practices. That's why the values in the manifesto speak so well. I agree with
Ken that the shift to Agile in its essential elements (predictive to adaptive, process-oriented to people-
oriented) is more of a discontinuity than it is a progression, although it can be hard to see the boundary.

But I'm not too concerned about focusing on practices - indeed I think it's essential. Good development
practices are vital to fulfilling the promise of agile development. XP's offerings here, such as its
techniques for evolutionary software design, are vital if we are to maintain flexibility in the future.
Without all the parts, there isn't a Swiss watch to admire.

Produce Good Documentation


Agile conferences have never been shy to invite those who many would consider to be opponents of the
agile cause, such as Mark Paulk of the CMM giving a talk at XP Universe last year. This year XP 2002
welcomed David Parnas, who took a more critical stand against XP.

He said that a big problem with XP was that it focused on problems that have plagued software
development for forty years. XP's focus on code had its benefits, but failed to address other important
software development problems. Software's biggest problems were the poor response to unexpected events
and poor definition and control of interfaces.

http://www.martinfowler.com/articles/xp2002.html (3 of 11)05/12/2003 15:37:05


The XP 2002 Conference

David Parnas called for specifications which were both mathematically precise and comprehensible, so that domain experts
could find defects.

A focus of his criticism was XP's approach to design, which he said would lead to delayed problems. This
is an issue of economics, saving money now at the expense of costs later on. It was good to focus on
simplicity, but there's a difference between short-sighted simplicity and visionary simplicity. True long-
term simplicity requires planning, planning requires reviews, and reviews require documentation because
feedback from code comes too late.

But he wasn't advocating the kind of documentation that most projects do. He considers most project
documentation to be worse than useless and panned the "Undefined Modeling Language". XP's test cases
are not enough because they cannot be complete. He favored a mathematical approach that was well
defined, but said the formal methods community isn't on the right path because these mathematical
specifications must be easier to read than code, which isn't something that can be said about common
formal methods such as Z or VDM.

He said such a mathematical approach needs to based on functions and relations. Identify the variables that
need to be monitored and controlled and form derivations of the controlled variables from the monitored
variables. These variables can then be placed in tabular form that can be read by domain experts, with one
table per controlled variable. He cited a project for an avionics system where pilots found several hundred
errors based on such a specification. Naturally time didn't allow him to explain the system in depth.

The debate about XP's approach to design is a heated one, and one that I used as the theme for my talk at
XP 2000. The idea of a rigorous yet readable specification was a theme in much of my early career in
software. My first paper at a software conference was about how a graphical design technique could be
used in a mathematically rigorous way, which was nudging towards the same direction.

http://www.martinfowler.com/articles/xp2002.html (4 of 11)05/12/2003 15:37:05


The XP 2002 Conference

My view, and I think Parnas would agree with me on this, is that the value of such a formal specification
lies in the ability in finding errors so that they can be fixed more effectively than other techniques. If your
development approach is planned design, where you expect the design to be mostly complete before
coding begins, then this is essential since otherwise errors in specification can't be found until much later
in the process.

XP attacks this problem in several directions. Its use of short iterations means that you can get rapid
feedback from code, since users start getting a system that they can work with in a few weeks. Its use of
refactoring allows short-sighted simplifications to be fixed at a lower cost than would be true without it,
and the support of aggressive testing and Continuous Integration.

The conference party: who needs a sense of rhythm when you don't have a sense of embarrassment?

The crux of the question is whether a mathematical specification of this form is more cost effective than
XP's approach and under what conditions. I've never believed that a particular approach is necessarily
appropriate for all the different kinds of software development, so what works best for avionics may not
be the right route to take for enterprise applications. My experiments with more formal approaches in the
enterprise world led to be belive that domain experts did not work with them well enough to be able to
find errors as well as iterative delivery. I was also surprised by how effective evolutionary design was in
the context of XP, although I still favor a smidgeon of planned design. Having said all that, however, I
haven't tried Parnas's particular techniques. I hope that some XP people give the techniques a try when
working with customers and see if they are worth the cost of using them. Although I think Parnas views
these techniques as ones to be used in a predictive setting, I see no reason why they couldn't be used in an
iterative environment.

Using Practices Discarded Twenty Years Ago


If David Parnas is an outsider to the XP community, Enrico Zaninotto is an outsider to the entire world of
software development, being a professor in economics. His interest was in comparing agile approaches to

http://www.martinfowler.com/articles/xp2002.html (5 of 11)05/12/2003 15:37:05


The XP 2002 Conference

recent developments in manufacturing, triggered by an experience in seeing a software development


project use techniques that been discarded by leading manufacturers twenty years ago.

Zaninotto outlined four main drivers that added complexity to a manufacturing or software development
effort.

● the number of states that the system can get into


● the interdependencies between the various parts
● the irreversibility of the various actions you can take
● the uncertainties in the environment

He described the Taylor and Ford models as handling complexity by focusing on the problem of the
number of states the system could get into. They tacked these by division of labor, standardized parts, and
the assembly line that fixed the product that could be built, thus limiting the number of states. Zaninotto
views the waterfall view of process as following this model. The limitation of the Taylor/Ford model lay
when you ran into unforeseen consequences. The approach optimizes the situation when you know what's
going to happen but becomes vulnerable to uncertainties.

Enrico Zaninotto compared XP to the Toyota manufacturing system's focus on attacking the complexity of irreversibility.

The paradigm shift for manufacturing is the Toyota system. Of the four complexity drivers, he said the
Toyota system attacks irreversibility, allowing decisions to be changed. While Taylor/Ford controls the
flows of information, embedding it into the system, the Toyota system pushes decision making to the point
of action.

The biggest difficulty with flexible systems like the Toyota system is that they may not converge. To get
things to converge the Toyota system keeps the variations within bounds and uses a high level of quality
control. Zaninotto saw this issue of convergence as the limiting point of XP. The true bounds of XP are the
bounds of where convergence still occurs.

http://www.martinfowler.com/articles/xp2002.html (6 of 11)05/12/2003 15:37:05


The XP 2002 Conference

I wasn't at my best for Zaninotto's talk, the conference dinner featured a really good band and lots of Mirto
- which lead to late and exhausting evening. And 8.30 is never easy for me at the best of times. But I was
fascinated by the talk. Speaking in a non-native language, Zaninotto read his text (which is available in
full on the XP2002 site), but in many ways the simplicity of the delivery amplified the quality of the
content. The links between the Toyota system and agile processes are a territory that Mary Poppendieck
has already mapped out, which led me to explore it further, but Zaninotto added new ideas to what I'd
already learned.

The issue of reversibility, and the notion that irreversibility is a cause of complexity, was one point that
particularly tickled me. One of the interesting things about DSDM is that one of its core nine principles is
that "All changes during development are reversible". Putting reversibility right at the top of a
methodology like that is unusual. One argument is that reversibility is a necessary protection with
incremental change. It means that the worst thing that can happen is temporary problems and a reversion
to a previous state. Of course those temporary problems could be quite serious, as in any computer defect,
but once the failure is spotted you can always fix by reversion even if you can't find the underlying defect
immediately.

When I read the recent FDD book, I noticed that in their list of core practices they included configuration
management. Configuration management was left out of XP, not because it isn't necessary, but because
XPers assume configuration management is part of basic competence. Yet it's not uncommon to run into
people who don't seem to understand how to use configuration management properly.

Another element that struck me was the interrelationship between reversibility and iterative development.
If you make a wrong decision and detect it rapidly, then you can use some form of reversibility to undo
your mistake, or you can refactor before the mistake gets out of hand. But if you can't detect it quickly,
then it gets embedded in the system and is difficult to reverse. The iterative cycle gives you the ability to
spot errors earlier, before they are hard to reverse, and refactoring further reduces the cost of removing the
error. The net result, that you aren't tied into getting things right the first time, removes a major source of
complexity. Much of the thinking of rigorous process is about coping with irreversible processes, and
techniques aimed at coping with irreversibility become excess baggage once that complexity is removed.

Metaphors for XP Practices


Bill Wake was the only established XP leader on the plenary speaking program this year, and his
contribution was lighter in tone than many of the other plenary speeches. His theme was metaphor, not as
in the XP practice of metaphor, but in the sense of metaphors for a variety of XP practices. Here's a run
down of those I noted.

http://www.martinfowler.com/articles/xp2002.html (7 of 11)05/12/2003 15:37:05


The XP 2002 Conference

Frank Westphal is one of the pioneers of XP in Germany.

● Test first is like math problems where they only tell you the even answers - the point isn't the
answer it's the doing
● Spike is like carpentry where you build one just to see how it works. Test first also plays here as
you figure out how things should fit before you make the item.
● Collective Code Ownership is like the situation room in films and TV shows like West Wing. The
point is that everyone has access to all the information and is therefore able to contribute to the
problem solving
● Pair Programming is like four handed piano music, or perhaps like tag team wrestling
● Iterations are like the escapement on a clock
● Learning XP is like learning a foreign language
● Continuous Integration is like balancing a check book. If you only do it every year it's a pain, but if
you it every week it's easy.
● Going home clean (checked in with a green bar) is like day trading where you leave your portfolios
balanced at the end of the day.
● Stand up meetings are like the starter for race, after that everyone is running in the same direction
● Iteration retrospectives are like a sports team watching a video of their last game

Metaphor is a contraversial subject in XP, I've found that when a metaphor works well, it can be
incredibly satisfying, but coming up with one that works well is very hard. Using these kinds of
metaphoric thinking as a mandatory practice is limiting because it asks you to do something that is hard,
when simpler things often do enough of a job. As a result I don't worry too much about metaphor when
working with XP, yet I don't let that stop me using a good one if it comes up.

http://www.martinfowler.com/articles/xp2002.html (8 of 11)05/12/2003 15:37:05


The XP 2002 Conference

Like most metaphors, I found a few of Bill's interesting but most just didn't work for me. Continuous
Integration == balancing a check book worked pretty well, and I would extend it by pointing out that
balancing a check book is even easier when you have automated supported (using Quicken has been very
helpful.) I also like the situation room / collective code ownership analogy - although I've never watched
West Wing.

But I've never really liked much four hand piano music - and as for tag team wrestling? At least I can play
with the mental image of Ron "The Hammer" Jeffries and Ann "Wild Woman" Anderson versus Kent
"Alpha Chimp" Beck and Robert "Black Hole" Martin. (I'd just want to make sure that Rob Mee is my tag
partner.)

Build only the Features You Need

Roofs in Alghero

Jim Johnson is the chairman of the Standish Group and as such there's little surprise that much of his talk
included the statistics that the Standish Group have been tracking for the last few years. The oft-quoted
headline is that only 28% of IT projects actually succeed fully: 49% are "challenged" and 23% fail.

Of course this kind of statistic rests very heavily on the definition of success, and it's significant that the
Standish Chaos report defines success as on-time, on-budget and with most of the expected features. Like
most of the agile community I question this. To me a project that is late and over-budget is a failure of the
estimate. A project can be late, way over budget and yet still a big success - as Windows 95 was for
Microsoft. Project success is more about whether the software delivers value that's greater than the cost of
the resources put into it - but that's very tricky to measure.

Another interesting statistic that Jim quoted was the large proportion of features that aren't used in a
software product. He quoted two studies: a DuPont study quoted only 25% of a system's features were
really needed. A Standish study found that 45% of features were never used and only 20% of features

http://www.martinfowler.com/articles/xp2002.html (9 of 11)05/12/2003 15:37:05


The XP 2002 Conference

were used often or always.

This certainly fits the anecdotal evidence of many agilists who feel that traditional approaches to
requirements gathering end up gathering way more requirements than are really needed to a usable version
of a release. I think it also suggests that most projects should be about quarter of the size that they
currently are. If you also factor in the diseconomies of scale for software, this argues that many teams
should be a lot smaller too.

In his conference closing speech Kent Beck said that he was concerned about the ossification of XP practices, and thus
encouraged XPers to experiment with the practices and report their results. He also challenged academia to find ways of
measuring XP without concentrating on the practices.

This point really came out in Johnson's comparison of two SACWIS systems. SACWIS is a child welfare
system that all the states in the US must implement. He stated that Florida began its SACWIS system in
1990 with an original cost estimate of $32 million for delivery in 1998 with a development team of around
a 100 people. When they last looked the new cost was $170 million due to ship in 2005. He pointed out
the state of Minnesota has to build the same capability with pretty much the same demographic issues as
Florida - leading to very much the same broad system requirements. Minnesota started work in 1999,
finished in 2000 with eight people costing $1.1 million.

The comparison is a startling illustration of Chet Hendrickson's statement that "inside every large system
there's a small system trying to get out". I can't claim to really judge the details of what happened to make
these two systems so different in cost and effort. The Standish group attributed the difference primarily to
Minnesota being more successful at minimizing requirements and also using a standard infrastructure. If
nothing else it's very suggestive of the amount of impact you can get by paying attention to boiling down
requirements to their essence. The agile contention, of course, is that short value-based iterations are more
likely to minimize requirements than an up-front requirements gathering exercise. It'll take a while before
we get any real data on that.

http://www.martinfowler.com/articles/xp2002.html (10 of 11)05/12/2003 15:37:05


The XP 2002 Conference

Whether you buy this agile contention or not, I think the SACWIS story suggests that the software
industry faces a very real challenge in understanding how little to build and still provide value. It suggests
that just by building only the features we need, we can drastically cut the costs of a software system. My
view is that up-front requirements processes work against you in this because too often people are looking
at requirements without costs. Requirements books I've examined hardly ever mention costs and the
importance of understanding costs as part of gathering requirements. In my view a requirements document
without costs is almost a guarantee of over-building something, particularly if it's tied into a fixed-scope/
fixed price contract that only cements the unnecessary expenses into place.

© Copyright Martin Fowler, all rights reserved

http://www.martinfowler.com/articles/xp2002.html (11 of 11)05/12/2003 15:37:05


The Agile Manifesto: where it came from and where it may go

About Contact
Home Blog Articles Books ThoughtWorks
Me Me

The Agile Manifesto: where it came from and


where it may go
Martin Fowler
Chief Scientist, ThoughtWorks

Last Significant Update: February 2002

In February 2001 a group of seventeen software pundits got together in Snowbird UT to discuss the
growing field of what used to be called lightweight methods. We decide to use the term agile to describe
this new breed of agile methods. We also wrote the Manifesto for Agile Software Development , setting out
the values and principles of these agile processes. I was one of these self-elected visionaries and have
since come across many questions about this group's origins and future. This essay describes my opinion
about the answers.

Origins
I can fairly accurately ascribe the origins of the Agile Alliance get together to a retreat held for various
leaders in the Extreme Programming community in the Spring of 2000. Kent invited a bunch of active
XPers to his rural part of Oregon to discuss various issues in XP. As well as confirmed XPers he also
invited a number of people who were interested but separate to XP: such as Alistair Cockburn, Jim
Highsmith, and Dave Thomas.

At the meeting we discussed the relationship between XP and other methods of a similar ilk - at the time
referred to as Lightweight Methods. We agreed that XP was best as a specific process: "a stake in the
ground". We also agreed there was a lot of common ground between XP and some of these other methods.
As a result of this (Uncle) Bob Martin decided to try to put together a meeting of people interested in this
broader range of methods.

A wide range of people were contacted, basically whoever we thought was interested and active in this
field. I'm sure we missed some people who would have been interested and valuable had they come, but
we did try to cover as wide a ground as we could. After much discussion we settled on a meeting at
Snowbird Utah from February 11-13 2001. Several of the people who were keen to come couldn't make it
- in the end those that did were the 17 whose names appear on the manifesto.

http://www.martinfowler.com/articles/agileStory.html (1 of 4)05/12/2003 15:37:06


The Agile Manifesto: where it came from and where it may go

The Snowbird Meeting and the Manifesto


We came to Snowbird with limited and varying expectations. Mine were very limited - I just hoped that
we would get to know each other better and that greater communication would lead to something
interesting, although I didn't expect much at that meeting. I've gone to small retreats like this (such as the
WOOD series in Snowbird in the mid 90s) and found them very valuable. Contacts are made that turn into
all sorts of stuff. Indeed I first got to know many people at those WOOD retreats, and without them would
probably not found myself part of the birth of XP.

We actually found that we quickly had a lot in common and agreed on many important aspects of software
development. So we decided to go further than just talk. We liked the idea of writing a document that
would both capture the common ground we felt we were discovering and act as a rallying cry to the
software industry.

The first part of this was to find a good name. Informally the various methods we used had been called
"lightweight methods". Few of us felt that was a good name. Some saw it as vaguely insulting, but all of
us felt that it missed the point. Light in weight wasn't the point of these methods, it was just a symptom -
as I've argued in The New Methodology.We considered a bunch of names, and agreed eventually on
"agile" as we felt that captured the adaptiveness and response to change which we felt was so important to
our approach.

It's important to remember that we have no copyright on the word "agile". I've seen a few people write
articles saying that agile methods aren't really agile according to some definition of the word agile.
Naturally this is true, like Humpty Dumpty we've appropriated the name agile to describe what we do -
and certainly that isn't the only use of the word agile. But we need some word to describe the common
views that we hold, and felt agile was probably the best to go with.

The next part was to write the document. We decided to call it a manifesto since it was a call to arms and a
statement of our beliefs. We worked primarily on our statement of values during the meeting and I'm very
pleased with the result. I think the values really capture the core of the ideas that we shared during the
meeting.

In the latter part of the meeting and in the following couple of months we worked on the principles. Once
we were separated progress was much slower but we did find a good combination of emails and wiki to do
the job. I don't think the principles have quite the same punch as the values - but they are still a good
record of what we stand for.

Since Ward (the inventor of the wiki ) does a lot with web servers, he volunteered to set up a web presence
for the manifesto. He got the domain name agileAlliance.org which we used to publish the manifesto. The
site just holds the manifesto, a short article by Jim Highsmith that gives some background, and links to the
signatories.

http://www.martinfowler.com/articles/agileStory.html (2 of 4)05/12/2003 15:37:06


The Agile Manifesto: where it came from and where it may go

The manifesto is a rallying cry: it says what we stand for and also what we are opposed to. Several items
were worded to clearly make a distinction between our views and that of many others in the software
industry. I think this is important to get past the fuzziness that has clouded so many things in the last few
years. I've seen the terms incremental and iterative abused into all sorts of strange project shapes. I hope
the manifesto will make clear what is and isn't agile.

An on-going organization
There is nothing particularly special about the seventeen of us who happened to be at Snowbird. We aren't
the only people to share the values and principles that we wrote about in the manifesto. We all expect to be
working hard in the next few years to promote these principles and values, both through the specific
processes and with a broader agenda. However we don't have any special status in the this movement, and
no desire to set up ourselves for a such a status.

Most of the seventeen had our first opportunity to get together again at OOPSLA 2001. The meeting,
which involved quite a few others who are interested in agile development, made it clear that the
seventeen manifesto authors had "launched the ship", but saw no reason to have any special say in agile
software's future.

However several people, both amongst the seventeen and new additions, wanted to see a more permanent
organization set up. So in late 2001 they formed the Agile Alliance as a non-profit organization to act as a
center for furthering agile methods. You won't be surprised to find that the arrangement of the Agile
Alliance is very chaordic. All work in the alliance is done by programs that run very independently. There
is a board which oversees the programs at quarterly intervals, but other than this checkpointing mechanism
the programs have a lot of independence as to what they do.

As I write this (February 2002) the alliance hasn't got its web site sorted out, once it does you'll be able to
find out more about them, and to join yourself.

There is a valid question as to whether an on-going organization is really necessary. I certainly question
the value of such an organization. However I've agreed to serve on the board, in order to see what
happens. We shall see what benefits it brings.

Agility and ThoughtWorks


You may wonder how agility fits in with our work at ThoughtWorks. My take on it is that the basic
essence of agility is deeply embedded in ThoughtWorks's corporate culture. That's a large part of what
attracted them to me and vice-versa. The manifesto was well received at ThoughtWorks because it's
something public that explains these values. I think it's fair to say that all of the projects we do are agile,
although only a subset of them follow a published agile methodology. We're great adaptors and
customizers informally following Alistair Cockburn's idea of a methodology per project. We've also got
quite a lot of experience using more direct XP, with a handful at least close to XP projects under our belt.

http://www.martinfowler.com/articles/agileStory.html (3 of 4)05/12/2003 15:37:06


The Agile Manifesto: where it came from and where it may go

Revision History

Here's a list of the major updates to this paper

● February 2002: Talked about the forming of the Agile Alliance non-profit.
● November 2001: Updated section on future
● August 2001: Updated section on future
● June 2001: Initial Publication

© Copyright Martin Fowler, all rights reserved

http://www.martinfowler.com/articles/agileStory.html (4 of 4)05/12/2003 15:37:06


Software Development Online: August

December 2003
Search
more search
713 USERS ONLINE

HOMEPAGE
SITE CONTENTS BY YEAR August 2001
RESEARCH REPORTS Issue Theme: Agile Methodologies
SEND US FEEDBACK
SUBSCRIBE TO SD
ADVERTISE WITH SD
MY ACCOUNT
Practices
LOG OUT
REGISTRATION FAQ COVER FEATURE Issue Theme:
The Agile Manifesto Component Success
--more--
OPEN SOURCE by Martin Fowler and Jim Highsmith
AGILE PROCESSES Facilitating change is more effective than attempting to prevent it. Learn to trust in your ability
THE SALARY SURVEY to respond to unpredictable events; it's more effective than trusting in your ability to plan for Subscribe For Free
THE JOLT AWARDS disaster. Now!
SD BEST PRACTICES
CONFERENCE COVERAGE
FUTURE OF DATABASES News from Development's Front Line
MDA EXPLAINED by SD Staff
ANTI-PIRACY MEASURES
Industry gurus and neophytes gather at Software Development West to debate the latest trends in
process, programming and Web services.

BEYOND OBJECTS
Components and Web Services
by Clemens Szyperski
Why are emerging transaction standards so close to what we've seen before?

Products
HELLO, WORLD!
Learn to Manage, Online
by Mike Donoghue
http://www.sdmagazine.com/articles/2001/0108/ (1 of 5)05/12/2003 15:37:11
Software Development Online: August

CAREER & TRAINING Get your nose out of the textbook and start smelling success.
UML DESIGN CENTER
PROJECT MANAGEMENT
SECURITY
BEYOND OBJECTS
People
CONFERENCE COVERAGE
PRODUCT REVIEWS PROFILE
TEST CENTER Individualism vs. the Company Line
by Dianne Tanner
SCOTT AMBLER Bruce Perens sounds off on the influence of open source on software development and his
GRADY BOOCH controversial role at Hewlett-Packard.
WARREN KEUFFEL
BERTRAND MEYER THE CTO DIARIES
CLEMENS SZYPERSKI
ROBERT MARTIN
The Show Must Go On
by Steve Adolph
Though our last-minute salvage job was the stuff of programmer legends, this event was no
AGILE MODELING
triumph.
DEVTALK
SUBSCRIBE
Departments
SD WEST 2004
SD BEST PRACTICES EDITOR'S NOTES
Alexandra Weber Morales
AUTHOR GUIDELINES Peering Into the Future
EDITORIAL CALENDAR Bill Joy and other Sun honchos string together open source, file swapping and smart devices in
AUTHOR BIOGRAPHIES the JavaOne Keynote.

FEEDBACK
HOME Letters to the Editor
CAREER CENTER
Our readers take exception to XP's characterization in a recent article and comment on their open
HOT TOPICS
INTERFACE
source motivation and software testing.
MODELING AND DESIGN
OFFSHORE OUTSOURCING
TIME WARP
PROJECT MANAGEMENT Laurie O'Connell
READER REVIEWS AI: By Any Other Name
TESTING & Q.A. 15 years ago in Software Development, synthetic cerebration takes the stage.
WEB SERVICES
NEW AND NOTEWORTHY
Rick Wayne
EDITORIAL CALENDAR
Do-It-Yourself Products
POSTED PRESS RELEASES
MEDIA KITS
Software Development highlights ILOG's JConfigurator, ZeroG's PowerUpdate, Poet Software's
ADVERTISING CONTACTS FastObjects j2, Aligo's M-1 server and the Apache XML Project's Batik 1.0.
DEVELOPING WITH COMPONENTS
THINKING OBJECTIVELY
Scott Ambler
http://www.sdmagazine.com/articles/2001/0108/ (2 of 5)05/12/2003 15:37:11
Software Development Online: August

Debunking Modeling Myths Subscribe to


To put your project on the path to success, avoid these common design misconceptions. Software
Development's
INTERFACE email newsletters
Warren Keuffel Agile Modeling
Playing by the Rules (Monthly)
What happened to the promise of programming without programmers? Online Update
(Monthly)
DevTalk
(Monthly, HTML
only)
Web Services
(Monthly)
SD Show Daily
(Occasional)
SD People and
Projects
(Monthly)
SD Secure Start
(Monthly)

your email
Submit

(more information)

http://www.sdmagazine.com/articles/2001/0108/ (3 of 5)05/12/2003 15:37:11


Software Development Online: August

http://www.sdmagazine.com/articles/2001/0108/ (4 of 5)05/12/2003 15:37:11


Software Development Online: August

MarketPlace
Stop struggling to get new clients and projects!
Free, innovative marketing and sales advice exclusively for IT professionals and
consultants. Articles, audio tips, and a free weekly newsletter packed with unique, proven
strategies to grow your IT business.
Accelerate your Java™ development! Announcing Borland® JBuilder® X
With the leading cross-platform Java IDE on your side, speed your Web, XML, mobile,
database app dev with 2-way visual designers. Empower your productivity with Struts,
Web Services designers, UML™ code visualization, refactoring and more! Download a free
JBuilder X trial now! (URL)
U.S. Engineers and IT Professionals
National Technological University's degrees in Engineering and Information Technology
best serve students in the United States. Advance your career with a technical degree
from an accredited university. Learn more about NTU today!
Building Enterprise-Class Applications Just Got Easier
Build enterprise-class applications smarter, faster, and better with BEA WebLogic
Workshop 8.1. Find out how simple it is without downloading any software. Start your
free, no-obligation hosted trial.
Parature Online Support Software
Industry’s most powerful online support portal to manage and deflect up to 80% of your
incoming service inquiries. The #1 web-based help desk software that features self-
service, ticket management, contact management, online surveys, forums and more.
Wanna see your ad here?

Travel: Hotels • Las Vegas Hotels • Popular Hotels | Finance: Compensation Claims | Electronics Digital
Cameras • Digital Camera • Sony Digital Camera • Camcorders | Miscellaneous: SEO Company : SEO Guy
• Systems Management Software

Copyright © 2003 CMP Media LLC, SD Magazine's Privacy Policy, Comments: webmaster@sdmagazine.com
SDMG Web sites: BYTE.com, C/C++ Users Journal, Dr. Dobb's Journal, MSDN Magazine, Sys Admin, SD Expo, SD Magazine, Unixreview, Windows
Developer Network, New Architect

web1

http://www.sdmagazine.com/articles/2001/0108/ (5 of 5)05/12/2003 15:37:11


Planning and Running an XP Iteration

Planning and Running an XP Iteration


Cara Taber
ThoughtWorks

Martin Fowler
Chief Scientist, ThoughtWorks

Last Significant Update: January 2001

Since the begining of the new millenium, we've been running an interesting XP project. It's interesting not just
because it was one of the first XP projects at ThoughtWorks, but also due to its size: around 50 people are
involved. Here we talk about how we run this project by focusing around the activities that need to be done
for a single iteration, and how the various subteams work around that iteration.

The original version of this article was published in the Cutter IT Journal.

● Introduction
● Team Structure
● Planning Cycle
● Analysis Cycle
● Iteration Planning Meeting
● Domain Development Cycle
● SWAT Development Cycle
● Quality Assurance Cycle
● Successes
● Challenges
● Guidelines for a Project Manager
● Revision History
● Biographies

Introduction
ThoughtWorks, Inc. is a Chicago based system integration and consulting company of around 300. We
specialize in building demanding business applications using technology that is both new and strategic for the
industry. We also work on complex business applications that usually require stitching together various
components and augmenting these components with complicated and changing business logic. We've done a
lot of work in the leasing industry, which is not known for simple and logical contractual agreements. If
you've ever read a leasing agreement, you'll get the picture.

http://www.martinfowler.com/articles/planningXpIteration.html (1 of 12)05/12/2003 15:37:13


Planning and Running an XP Iteration

For quite a while now, we've been working on a particularly demanding leasing application, built with
Enterprise Java. It's a big application, the kind of thing where existing vendors have spent over a decade
developing their systems. Before completely revamping our project approach, we spent 18 months gathering
requirements, creating prototypes, and beginning development. We ran into many of the problems that are
typical for these kinds of projects. The requirements were poorly understood and changing. Simply
controlling a project that size is demanding both for the development and for the customer relationship.
During this time we came into contact with the ideas of Extreme Programming (XP) and felt that it was a
decent fit for the nature of our project. XP was also a good fit for the culture of our company. So eight months
ago we began working in an XP style.

Although the fit is decent, it's by no means perfect. XP is designed for projects involving a maximum of a
dozen developers. We have a team of fifty people, half of whom are developers. XP also encourages frequent
production releases. Since we are in the game of replacing complicated existing systems, we knew that we
faced a long time before we could release something the customer would use for real deals. We also realized
from the beginning that these factors meant we couldn't do XP by the book. (But then we never do things by
the book even if we wrote it!) So an important part of our process involves changing it a little bit every month
with the participation of the entire team to re-design our XP approach to suit our needs.

When we started with XP, we mapped out a release plan. This took 18 months of story cards (roughly
equivalent to a feature) and allocated them to iterations. XP runs a project by dividing into short iterations,
each of which has to deliver production quality software that contains newly implemented story cards. We use
one month iterations (slightly longer than vanilla XP). Every month the customer can see the system growing
with new features.

This essay discusses how we are currently doing this project. We intend to change it periodically as we
change our process, and get round to updating the article. We'll also discuss some of the changes we've made
and why we made them.

Team Structure
We've got a 50-person team. The project management office consists of two account managers who are
primarily responsible for client and sponsor face time. The day-to-day planning work is done by a release
manager and iteration manager. The release manager concentrates on the long range release plan, which is
very volatile and has a horizon of six months to a year. The iteration manager focuses on the iteration plan,
which is the details of what happens in a single iteration.

The split between release and iteration managers reflects the style and preferences of the two individuals that
do it. Originally they alternated as "odd" and "even" iteration managers, but we found that Matt was better at
the track the ongoing iterations and Cara was better at the broader release plans. So they adjusted their roles to
suit their strengths and interests. We don't think our solution is one that necessarily everyone should follow.
An important part of XP is that people sign up for what they are interested in doing, this applies to managers
as well.

In XP terms, our "customer" is a 12-person team of in-house domain experts and clients who will receive the

http://www.martinfowler.com/articles/planningXpIteration.html (2 of 12)05/12/2003 15:37:13


Planning and Running an XP Iteration

beta release of the application.

There are roughly 25 developers on the project, divided into two teams. The domain team is solely
responsible for coding the new functionality in a given iteration. The SWAT team is responsible for bug fixes,
the build process, automation of testing, and all other development tasks not related to the new functionality.
We split the team like this to maintain a coherent design and to prevent people from stepping over each other.
We also didn't want more than 13 people adding new functionality to the code base at a given time. At each
iteration, a few developers rotate between the teams; every developer has been on both teams.

Our quality assurance staff is an 8 person team responsible for daily regression testing, determining what
story cards will be delivered at the end of an iteration, and the preparation of the release notes for each
delivery.

From the domain developer's point of view, the iterative process is very simple. Each iteration begins with a
new batch of stories which they implement, hand off to QA, then start the next iteration. However there's a lot
of work surrounding this simple story. Each part of the team has it's own cycle that it works on. Most teams
spend a typical month working on some material from 3 given iterations: the current iteration, the previous
iteration and next iteration.

To illustrate our XP approach, we're going to focus on what needs to happen for a particualr iteration. We've
picked number 6 to make it easier to talk about, but what we describe is what we do now rather than what we
did on 6. (We didn't want to update all the numbers every time we update the article.). Iteration 6 was
scheduled for June, but part of the work also occurs in May and July. (It's a helpful coincidence that we
started at the beginning of the year, but that's not mandatory!) As we talk about the projects we always focus
on the iteration that the domain team is working on, so we say things like "in the first week of iteration 5, the
planners get the list of story cards for iteration 6." There's cycle tables here for each team showing the
activities they do during iterations 5, 6, and 7. To see the flow of activities better in the table, we've shaded all
the activities for iteration 6 so you can easily see which activities occur and whether they occur before or after
the actual development of the iteration. We've included a seperate cycle table for each team, and you can look
at the consolidated cycle table to see the activities for all the teams in one place.

Planning Cycle
The first hazy plans for an iteration occur somewhere in the mists of time as the release plan. The release plan
is never static and shifts and changes as we learn about what the customer wants and what the developers can
do. In the release plan there is a bundle of stories, chunks of functionality, for iteration 6. The release plan
may be shifting, but that doesn't stop it from being an essential tool. It gives us a way of seeing what may be
acheivable, evaluating options, and assessing the effects of events that hit us.

Early in May, shortly after iteration 5 begins, the release manager starts looking in earnest at the content of
iteration 6. The customer team works with the release manager to decide which stories will actually make it
for presentation to the developers in June. With iteration 5 started, we know what will and what won't get
worked on during iteration 5. With that information in hand, you know what story cards will not be worked
on in the current iteration, and you are ready to evaluate what should be worked on next. The release manager

http://www.martinfowler.com/articles/planningXpIteration.html (3 of 12)05/12/2003 15:37:13


Planning and Running an XP Iteration

now starts coordinating getting everything together for iteration 6.

This primarily involves coordinating the prioritization effort with the customer to develop the next list of
story cards to be worked on. The customer can select any story cards they wish as long as the estimated
developer weeks on the cards add up to the number of available developer weeks for an iteration. This is
called the velocity. In this case, we scheduled 28 weeks of ideal developer time, which is based on the amount
we got done in iteration four.

Dispose Asset
Create A/R record for sales price with or without tax
calculation. Create journal entries for A/R record.
Create expenses for A/R records to ahndle disposal
costs and appropriate journal entries. Change asset Analyst: Terri
status to "disposed". Create journal entries for 2 weeks Developer: Biren
releiving (fixed asset and accumulated) inventory and QA: Shelly
calculated gain or loss. Set stop dates on book and tax
depreciation. Create transaction history record. Asset
must be active - in inventory.
Example of Story Card

The customer has the opportunity to outline new functionality not currently scheduled in the release plan, pull
in functionality slated for later, push out functionality scheduled for the iteration, or reprioritize the
functionality within a card. In terms of story cards, this is a customer's opportunity to, based on their current
business needs and strategies, create new story cards, move them around in the plan, move them out of the
plan entirely or split them into several cards which will get prioritized differently. We also involve developers
by asking them to re-estimate the stories that we considering for the iteration. With a better sense of the
project and more focus on the stories these estimates have become very accurate - to the point that we now
mostly are dead on with our estimates of what will fit in the next iteration.

This planning results in the release plan being laid out again. The process of selecting the next month's
functionality usually takes about a week. As soon as this is finished, the analysis cycle begins.

In preparation for the iteration 6 planning meeting, the release manager must determine the exact number of
developer days available during the month. This means, taking into account people's vacation and training
days, the number of domain developer days available during the month and converting that number based on
the previous iteration's velocity into the number of ideal developer days available for the upcoming iteration.

At the begining of iteration 6, the iteration manager hands over the planning work of the iteration. In the
iteration planning meeting the developers come up with an iteration plan. The iteration manager then tracks
the iteration plan and coordinates the closing of the iteration and the delivery of the iteration to the customer.

Planning Cycle

http://www.martinfowler.com/articles/planningXpIteration.html (4 of 12)05/12/2003 15:37:13


Planning and Running an XP Iteration

Iteration 5 Iteration 6 Iteration 7


Get list Get list Get list
Plan Plan Plan
of story of story of story
resources Deliver Close resources Deliver Close resources Deliver Close
cards cards cards
for Iteration Iteration for Iteration Iteration for Iteration Iteration
for for for
Iteration 4 5 Iteration 5 6 Iteration 6 7
Iteration Iteration Iteration
6 7 8
6 7 8
Manage Iteration 5 Manage Iteration 6 Manage Iteration 7
Prepare Prepare Prepare
Prepare Prepare Prepare
for Work with for Work with for Work with
Iteration Iteration Iteration
Delivery Analysts to Delivery Analysts to Delivery Analysts to
6 7 8
of articulate Iteration of articulate Iteration of articulate Iteration
planning planning planning
Iteration 6 funcionality. Iteration 7 funcionality. Iteration 8 funcionality.
meeting meeting meeting
4 5 6
Week 1 Week 2 Week 3 Week 4 Week 1 Week 2 Week 3 Week 4 Week 1 Week 2 Week 3 Week 4

Analysis Cycle
Two weeks before the beginning of iteration 6, the domain experts meet to discuss the upcoming
functionality. After reaching consensus on the details of how the new functionality should work, they divide
up the responsibility of articulating that functionality in a work product we call a narrative. A narrative is
written for each story card slated for the iteration. A narrative is similar to a use case, but is less formal.
We've chosen to articulate the new functionality in a more prose description than usually seen in a use case.

At the end of the narrative, a sketch of the relevant test scenarios is laid out. At a minimum, the test scenarios
must be articulated sufficiently to allow a developer to estimate the detailed programming tasks related to the
story card. These test scenarios are expanded to the final tests to necessarily and sufficiently test the
functionality of the story card. Time permitting, these test scenarios are expanded as much as possible prior to
the iteration 6 planning meeting. In practice, test scripts are generally finalized mid-way through iteration 6.

The domain experts meet again prior to the iteration 6 planning meeting to review the narratives and sign up
for the story card. Signing up for a card means agreeing to presenting the narrative during the iteration
planning meeting, being the point of contact for the development staff during the iteration, ensuring the
quality and completeness of that cards test scripts, and handing off the functionality to the QA team at
iteration close.

Analysis Cycle
Iteration 5 Iteration 6 Iteration 7
Working with Developers on Iteration Working with Developers on Iteration Working with Developers on Iteration
5 6 7

http://www.martinfowler.com/articles/planningXpIteration.html (5 of 12)05/12/2003 15:37:13


Planning and Running an XP Iteration

Prepare Prepare Prepare


for Articulate for Articulate for Articulate
Close Close Close
Delivery Iteration 6 Delivery Iteration 7 Delivery Iteration 8
Iteration Iteration Iteration
of funcionality. of funcionality. of funcionality.
5 6 7
Iteration Write Narratives Iteration Write Narratives Iteration Write Narratives
4 5 6
Week Week Week Week Week Week
Week 1 Week 4 Week 1 Week 4 Week 1 Week 4
2 3 2 3 2 3

Iteration Planning Meeting


The iteration planning meeting is the whopper meeting that gets the entire team on board with exactly what
functionality will be worked on during the iteration. All the developers and analysts attend (QA find it comes
at a very bad time in their cycle, so just a QA representative comes along). We sit in one big room with poster
sized story cards stuck to the wall. There are a few ground rules: use the mike, no cell phones, no laptops, and
no whining!

We provide everyone with copies of the narratives and a scope document. The scope document is divided into
the broad areas of functionality for the system. For each area it shows which story cards have been done,
which are slated for this iteration, and which are slated for later iterations. We've found this very helpful in
clarifying what exactly is in or out of this iteration.

After bagels and coffee, the point of contact analyst leads a discussion about the functionality outlined in the
narrative of the first card on the agenda. We discuss the scenarios. Analysts clarify the functionality and
developers articulate what it will take to code the functionality. The developers outline a complete list of
development tasks for each card. As the developers call out the tasks, they are written on big sticky notes and
stuck to the card.

After lunch, we finish the functionality discussion, breaking the story card into tasks. The development staff
meets as a group to estimate each task. For most of the project, the total number of developer days on the
targeted cards exceeds the estimated capability of the team. So the customer picks entire cards or several
tasks, under advisement from developers, to pull from the iteration. During the negotiation of what will be
pulled out, the individual tasks or whole cards physically get pulled off the wall.

Although this pulling has been a regular feature of the project, it hasn't happened in the last few iterations.
This is because our release planning has improved and we now estimate pretty accurately how many stories to
bring to the iteration planning meeting. This both helps planning and the smooth running of the meeting. A
key part of this has been involving developers in the pre-iteration planning process to give more accurate
estimates. Also practice has made a big difference: you get better at estimating as you do more of it. So don't
let early innacuracies put you off.

Write dispose asset transactor 1 day Biren


Make journal entries 2 days Biren

http://www.martinfowler.com/articles/planningXpIteration.html (6 of 12)05/12/2003 15:37:13


Planning and Running an XP Iteration

GUI - create asset disposal


3 days Caleb
screen
Calculate gain/loss 2 days Biren
Create pessimistic session bean 1 day Biren
Generate disposal charge 1 day Biren
Update statuses 1 day Biren
Coded Functional Tests 2 days Caleb
Example task list

Once the functionality has been selected, developers, sign up for tasks. Developer sign up has some basic
rules; each developer should stick to tasks on just a few cards and no card should have too many different
people signed up for its tasks. Each story has an analyst and QA person sign up before the meeting. A
developer also signs up for a card, that involves coordinating those developers who've signed up for tasks on
the card.

The result is a well articulated and reasonable list of functionality that will be developed during the iteration,
a list of developer estimated development tasks sufficient and necessary to code that functionality, and
resources allocated to each story card and task. Everyone on the team has participated in this process and is
familiar with the plan for the next month's development of new functionality outlined on posters that remain
on the wall throughout the entire iteration.

Historically our iteration plans have been stunningly accurate. We rarely fail to complete stories that were
signed up in the iteration plan, and this confidence carries through to everyone involved. The iteration plan is
seen as a very stable prediciton of what will appear in a month's time.

We wrap up the day-long suffering (these meetings can be extremely painful) with a keg.

How to present the functionality to the developers is something that we still feel we have much to learn about.
A key principle is that the presentation and narrative are by no means the final word. During the iteration
developers and analysts have frequent contacts on the details of the function. At the iteration planning the
developers don't need all the information, but they do need enough to break the stories down into tasks and
thus form the iteration plan. This step requires some initial design work.

The big problem is that the analysts need to be sure that they have told the developers everything of
importance, but the developers want a minimum of information as there's only so much you can absorb in a
day. So we face the difficulty that the developers want more brevity, but the analysts are concerned that they
could leave out something important that will affect the expectations of the client.

We've tried doing things without narratives and having the release manger present the narratives instead of
the analysts doing it. Neither worked well. Our latest attempt is to have preliminary meetings where a subset
of the narratives are looked over by an interested subset of the developers. This helps work out many of the
issues in advance.

http://www.martinfowler.com/articles/planningXpIteration.html (7 of 12)05/12/2003 15:37:13


Planning and Running an XP Iteration

Domain Development Cycle


The domain developers are responsible for adding the iteration's new functionality into the code base.
Throughout the iteration they work closely with the domain experts and with each other to design and
complete the development tasks they signed up for during the planning meeting. The domain experts are on-
site and available to work face to face with developers. Collaboration among the developers occurs in several
ways. Every other day the developers meet for a quick stand up meeting to discuss what they are currently
working on and resolve development issues as a group.

Although one developer bears the responsibility of completing a task, as a rule the developers pair program
throughout the iteration. Factored into the estimate and the work of completing any development task is
writing unit tests. Code check in practice is that code doesn't get checked in unless there are unit tests (that
pass) and that the new code doesn't break the unit tests. The iteration's time frame is centered around the
domain developers activities. What we call the current iteration is whatever iteration's work the domain
developers are working on. The only duty of a domain developer during the iteration is coding that iteration's
functionality.

Domain Developers Cycle


Iteration 5 Iteration 6 Iteration 7
Develop Iteration 5 functionality Develop Iteration 6 functionality Develop Iteration 7 functionality
Week Week Week Week Week Week Week Week Week Week Week Week
1 2 3 4 1 2 3 4 1 2 3 4

SWAT Development Cycle


The SWAT team is responsible for all development duties that take place during an iteration that are not
related to the new functionality. It is SWAT's job to take care of as many other development tasks as they can
to ensure that the domain development staff can stay fully focussed on coding new functionality. This
includes bug fixes from previous iterations' development, automating testing, streamlining the build process,
performance tuning, upgrades, etc.

At the close of an iteration, the SWAT team branches the iteration's build and fixes only the most critical bugs
to get our delivery build. Once the iteration closes, very little functionality is changed. It is risky having too
much new functionality developed on the code branch. It's better having the domain development team work
on any unfinished functionality in the next iteration and deliver it one iteration late.

SWAT Developers Cycle


Iteration 5 Iteration 6 Iteration 7

http://www.martinfowler.com/articles/planningXpIteration.html (8 of 12)05/12/2003 15:37:13


Planning and Running an XP Iteration

Bug fixes, automate Bug fixes, automate Bug fixes, automate


Prepare Prepare Prepare
functional tests for functional tests for functional tests for
build for build for build for
Iteration 4. On-going non- Iteration 5. On-going non- Iteration 6. On-going non-
Iteration Iteration Iteration
functional development functional development functional development
4 5 6
tasks tasks tasks
Week Week Week Week Week Week Week Week Week
Week 1 Week 1 Week 1
2 3 4 2 3 4 2 3 4

Quality Assurance Cycle


Through the iteration, the QA runs regressions tests regularly to ensure the quality of functionality delivered
in previous iterations. At the close of the iteration, developers scramble to finish functionality and get
approval of the domain expert on the card. The QA analyst assigned to the card is responsible for "passing the
card". Passing the card entails coordinating with the domain expert, the domain developer and the SWAT
team to assure that the tests for the story card articulate the functionality completely, and that the tests pass
sufficiently to be delivered to the client. Once QA has passed or failed each card in the iteration, we get a
final delivery build prepared for client release. The QA staff coordinates with project managers and domain
experts to publish a release notes document that will be delivered to the client with the delivery build. The
release notes outline to the users the new functionality and how to use it. It includes the story cards, the
narratives and the test, and progress on the iteration and overall project. QA coordinates the actual delivery
date. With the assistance of the iteration manager, QA also presents the new functionality and trains the users.
Quality Assurance Cycle
Iteration 5 Iteration 6 Iteration 7
Add Iteration 4 tests to regression test Add Iteration 5 tests to regression test Add Iteration 6 tests to regression test
suite. Run regression tests suite. Run regression tests suite. Run regression tests
Test Prepare Test Prepare Test Prepare
Iteration Iteration Deliver Close Iteration Iteration Deliver Close Iteration Iteration Deliver Close
4 4 Iteration Iteration 5 5 Iteration Iteration 6 6 Iteration Iteration
delivery release 4 5 delivery release 5 6 delivery release 6 7
build notes build notes build notes
Week 1 Week 2 Week 3 Week 4 Week 1 Week 2 Week 3 Week 4 Week 1 Week 2 Week 3 Week 4

Successes
Overall, we've found this XP approach to be fruitful.

● The estimation of how much we can get done in a given iteration has been extremely accurate. Nearly
all the cards we set out to code during an iteration are finished that iteration.
● All the cards have substantial and demonstrable progress made during that iteration. Every month we
make consistent, quick, demonstrable progress. The results are simple; we produce.
● Communication within the team and to the client and sponsors has vastly improved. The planning
meeting gets everyone on the same page and clearly articulates iteration goals to both the team and the
client and sponsors.

http://www.martinfowler.com/articles/planningXpIteration.html (9 of 12)05/12/2003 15:37:13


Planning and Running an XP Iteration

● The customer gets to actively participate in what gets done. The customer can change their minds and
we still produce.
● Since realistic expectations of both the team members and the application are set each month, there
isn't any anxiety about assessing where the project really is.
● Our project approach itself undergoes iterative process improvement. The whole team initiates these
improvements.
● Team morale has skyrocketed when we first adopted this process. It's since plateaued, but it hasn't
dropped .

One of the biggest benefits we've seen from this project is how well we've grown senior developers. It's been
noticeable that many people who were junior developers a year ago are now strong technical leads. We
attribute this to the fact that every developer is able to take responsibility from the start and that we encourage
rotation between different parts of the app. The rotation has some frustrations, particularly for analysts who
have to explain how things should work again to a new developer, but the result is that we now have several
technical leaders who can lead development, which makes the technical leadership of the project much more
stable, even as the project has lost several of the early senior deveopers.

Challenges
● The timeline of the project is geared to facilitating the most rapid development of new functionality.
This means that the domain developers' time is ' well managed while the rest of the team's time is not
as well planned for. This is especially true of the domain expert's time. The customer bears the
responsibility and burden of determining what functionality is most important and must clearly
articulate the desired functionality. This is not an easy task and we don't estimate how long it will take
to articulate the desired functionality.
● The iteration planning meetings can be horrendous - long and arduous. We've come to terms with the
fact that people will always complain about an eight hour meeting even if it is productive. Generally,
these have improved over time. The most useful tip we've learned (aside from bribery with food and
drink) is that ensuring the quality of the story cards and the narratives is time well spent. This has led
us to completely redraft the story cards written last winter.
● As a system grows, it becomes more and more difficult to maintain a big picture of what functionality
is there and how it all works together, particularly for the analysts. We've tried a number of things, but
haven't found something yet that has worked well.
● Communication will always be a challenge with a 50 person team. Our project approach relies heavily
on the verbal communication. While suiting our culture, it perhaps not the best communication
approach given the size of our team.
● Ours is certainly a developer-centered process, and the analysts have found this a challange. In
particular XP doesn't really give much advice as to how analysts should develop and organize stories,
particularly for such a complicated domain. We're learning slowly, but this is an on-going problem
● XP requires a very high level of quality at all times. To truly follow the spirit of XP the customer
should be able to ask you to release the software at the end of any iteration and you just go ahead. In
our case we have a lot of clean up that we need to do to reach release quality.

We now face a new problem. In the next six months we have to deliver to our first live users while at the

http://www.martinfowler.com/articles/planningXpIteration.html (10 of 12)05/12/2003 15:37:13


Planning and Running an XP Iteration

same time coninuing to evolve a generic product. We have to figure out how to divide our work between site
specific delivery and the ongoing generic development. We've put together a process, and we'll see how it
works out. We know our initial process won't be right, but we also know that we'll learn from experience -
and we trust ourselves to succeed.

Guidelines for a Project Manager


● Don't just say how things are going to be
● Ask the right questions
● Listen carefully to the answers
● Coordinate the expertise of your team and your client
● Help the customer articulate what should get done first
● Ask your team how much can get done
● Make sure that the right people are contributing to decisions
● Trust the expertise of your team
● Your job is not to determine how, when and what will get done.
● Afford the people responsible for carrying out a task the opportunity to participate in the estimation
and design of the task.
● Developers cannot be expected to meet a schedule they don't agree with. Ask for their participation.
Ask them to take responsibility for helping to layout a realistic plan.
● The customer must take responsibility for what functionality they receive, when and how it
specifically works to meet their needs. Help them to make the difficult decisions necessary to be
explicit about what they want and how much they want it.
● Your job is to coordinate the negotiation between customer and developer to determine the most
effective functionality for the customer's business and outline a reasonable, doable development plan
to implement that functionality.

Revision History

Biographies
Cara Taber has been with ThoughtWorks for 3.5 years. During that time she has been a developer, designer,
analyst and project manager. Before ThoughtWorks, she studied esoteric mathematics at a prestigious
institution from which she received the title of Ph.D. drop-out. Hoodwinked into project management, she
hopes that someday she will be allowed to code again. Her latest strategy is to work her way back into the
good graces of the development staff by supplying the monthly iteration planning meeting with a margarita
machine. She claims to live in Austin, TX, but most weeks can be found in ThoughtWorks' Chicago office.

Martin Fowler is the Chief Scientist for ThoughtWorks, an internet application development and consulting
company. For a decade he was an independent consultant pioneering the use of objects in developing business
information systems. He's worked with technologies including Smalltalk, C++, object and relational
databases, and EJB with domains including leasing, payroll, derivatives trading and healthcare. He is
particularly known for his work in patterns, the UML, lightweight methodologies, and refactoring. He is the

http://www.martinfowler.com/articles/planningXpIteration.html (11 of 12)05/12/2003 15:37:13


Planning and Running an XP Iteration

author of Analysis Patterns, Refactoring, Planning Extreme Programming, and the award winning UML
Distilled'

Revision History

Here's a list of the major updates to this paper

● January 2001: Updated web edition


● September 2000: Original article written for Cutter IT Journal - published in November 2000

© Copyright Martin Fowler, all rights reserved

http://www.martinfowler.com/articles/planningXpIteration.html (12 of 12)05/12/2003 15:37:13


Variations on a Theme of XP

About Contact
Home Blog Articles Books ThoughtWorks
Me Me

Variations on a Theme of XP
Martin Fowler
Chief Scientist, ThoughtWorks

Last Significant Update:

One of the attractive things about XP is that it gives quite definite statements about what you should do to
be doing XP. Furthermore that set of practices is carefully designed to fit together. Taking anything out
has serious consequences. Yet one of the principles of XP and other light methods is that they be self
adaptive: that is you should change the process as you are developing the project. How does this notion fit
in with the rigid practices of XP?

● Why Buy a Methodology?


● The Variability of Methodologies
● Variability and Methodologies
● What is XP?
● XP and Self-Adaptivity
● Varying the Concrete XP
● XP and the Boundaries
● Further Reading

Suppose I create a methodology (not that I would ever do such a thing). Let's call it Martin's Methodology
or MM for short. Someone else claims they are doing MM. How can I tell if they are? (The cynic in me
says that they are always doing MM if they are successful, and never doing it if they fail!) Does it matter if
I can tell?

This is an old issue with software processes, and now these questions are being asked about XP and other
light methods. With XP it's a particularly interesting question because XP has a very rigid set of practices
and a sharp set of boundary conditions. Yet people, including us at ThoughtWorks, are applying XP
outside of those boundaries. At what point are we leaving XP behind?

Furthermore a key part of light methods is their self-adaptivity: the fact you are supposed to change a
method as you apply it. How does that square with the rigidness of XP?

http://www.martinfowler.com/articles/xpVariation.html (1 of 7)05/12/2003 15:37:15


Variations on a Theme of XP

Why Buy a Methodology?


To help answer these questions I think we have to back up a bit and ask ourselves: what is a Methodology
for? Why would anyone want to use a Methodology? I'll posit that the answer to this is because the
customer of the Methodology is someone who is concerned about how to develop software properly and
expects that by following a Methodology they are taken a proven path that increases their odds of success.

One might also say that by following a Methodology they are protecting themselves from the
consequences of failure by saying "I did everything I could - I followed a respected Methodology".
Although it's common to decry that latter reason, it's true that in many disciplines you are expected to
follow a certain process for doing a task, and if you don't follow the consequences you may well be more
liable for problems down the line.

In either case people want some steps to follow to increase their chances of success. This is reasonable.
After all we've been developing software for a few decades now. Surely we should be able to learn from
the experience of others.

The Variability of Methodologies


To be brutal about it most methodologies are statements that a methodologist makes based on what he did
once. That is if he's lucky - I suspect most of them are based on what they wished they'd been able to do.
At best you might have a few people combining ideas: but whether anybody has actually done the
resulting set of things is another matter.

Software is also incredibly variable. For a start one of the key variables in software is people. Different
methods will work differently with different people. Company cultures also have a big effect. There's also
the style of the software. I don't belive a process designed for telephony is appropriate for information
systems, is appropriate for games.

To be fair a large proportion of methodologists do recognize this. They know that they can't give a simple
sequence of steps that people should follow and get perfect results. There is always some adapting, some
tailoring to be done. But how do we guide the tailoring? How does the customer of a methodology know
what's reasonable tailoring and what breaks the methodology?

This is particular a question for those who follow Light Methodologies. One of the key features of these
Methodologies is that they are what I call self-adaptive: that is you are expected to change the
methodology as you use it over time. In this state the boundaries of acceptable variation are even more
fluid. Not just is there variation between one project's use of a methodology, there is variation in a single
project over time.

This is the methodologists dilemma. How do you describe the variations within a methodology so you can

http://www.martinfowler.com/articles/xpVariation.html (2 of 7)05/12/2003 15:37:15


Variations on a Theme of XP

be comfortable that people who really try to follow your advice will get the benefits you are expecting, yet
allow them to adapt your advice to better match their specific circumstances.

Variability and Methodologies


As we look at the issue of flexibility with methodologies, it's worth bearing in mind that there are various
styles of methodologies out there. Each of these bring a different set of issues to the matter of variations.
So here's a set of methodology classifications to think about. Bear in mind that the terms I use here are
ones I'm coining for this article and that the lines between them are very fuzzy.

First off is a concrete process. A concrete process gives you a fixed set of practices that you should
follow. A concrete process will allow for little or no variation. The strength of a concrete process is that
makes it very clear what you should do to follow it. The obvious limitation of a concrete process is that
you can't change it. Well actually you can. All the time people take a concrete process and adopt it with
local modifications. The problem is that the methodology gives you no guidance in how to do that.
Furthermore as soon as you start varying you are strictly outside the process, although you may well be
close enough that a fan of the process would say you are within a process - particularly if you are
successful.

Since a concrete process is so fixed, a lot of processes come with explicit guidelines of how to vary it. I'll
call such a process a tailorable process. Tailorable processes usually have a significant part of the process
description that addresses what variations are acceptable and when it's appropriate to use those variations.
As such they gain over concrete processes because they do provide advice on variations. However it's not
perfect because it's often very hard to understand how to do this correctly. You have to understand both
the base process and all the variations before you can decide what to do.

At this point it's worth thinking about the size of a process. It's not easy to understand what size means in a
process, but one way is to think about how much stuff you have read to get a handle on the process. A
common pattern is to have large tailorable processes. The idea is to tell you everything you should do, and
then tell you what you can leave out. However to do this you need to understand the large process before
you can figure out the small. If you need a smaller process, this can be a lot more work than you'd want to
do.

There's many processes that are tailorable like this, perhaps the best known one out there at the moment is
the Rational Unified Process. This is more tailorable than most, so much so that it's referred to as a
process framework. The way this is explained is that anyone who uses RUP will use a particular process
that is an instance of RUP, and need not use or understand the full flexibility of RUP. So it's quite possible
to use a concrete process and RUP (a tailorable process) at the same time. In my view if you do that, and
don't really look at RUP, then it's the concrete process that you're using. But RUP may help with advice on
variations that the concrete process lacks, as well as helping you communicate with folks who use other
concrete instances of RUP.

http://www.martinfowler.com/articles/xpVariation.html (3 of 7)05/12/2003 15:37:15


Variations on a Theme of XP

Some processes don't give you very concrete steps at all, rather they concentrate on teaching a philosophy
of software development that underlies process. Such a philosophical process is inherently flexible
because there are many ways you can carry out a project that fits the philosophy. Because they don't go
into details on steps and variations, they can do this without being as large as a tailorable process or
process framework. However because they lack the concrete steps they are often harder to follow, they
don't clearly tell you what you need to do on Monday. Jim Highsmith's ASD is an excellent example of a
philosophical process.

Although folks would often not call them a process, a relevant group of knowledge is collections of best
practices. A good example of a best practice collection is McConnel's collection of best practices in his
excellent book Rapid Development. Such a collection is a group of relatively independent good things to
do that you can apply pretty much in any order. Unlike philosophical processes they are concrete pieces,
but it's very much up to you decide which best practices to apply on your project.

The nice thing about best practices is that you don't have to understand a complicated web of steps to take
advantage of them. Instead you can pick the practices that you think will give you the most value. Since
I've always distrusted Methodologies, I liked this approach. But one of the things that XP made clear to
me was the fact that practices are not independent pieces. XP's power comes not so much from individual
practices, but the interaction between the ones that Kent chose. If you look at the XP practices as
individual practices you miss much of the point of XP. From this I learned that the interaction between
practices is every bit as important as the practices themselves, and it is that interaction that a concrete or
tailorable process is good at capturing.

So all of these approaches have are imperfect in some way. A concrete process is in theory not variable at
all and in practice gives you no guidance on varying it. Tailorable processes work well in theory, but to
tailor them you have to understand an awful lot of material. Philosophical process give you a good
underpinning, but don't really give concrete advice on what to do. Best practice collections tell you
individual things to do, but don't talk the interactions between the practices.

What is XP?
To look at variability and XP we have to first recognize which of the categories XP fits into. For many it's
clear that XP is a concrete process. It has twelve practices that must be followed and if you spend much
time on any XP discussion group you'll quickly see that the advocates of XP put a lot of effort getting
people to do all twelve practices. As such many have picked up quite a reputation for excessive zealotry in
putting forth their view.

But much of XP's appeal has come from people who are drawn to the underlying philosophy of XP rather
than the concrete practices. XP's attention to adaptivity, people-orientation, light weight, and emergent
behavior is a compelling mix. There are plenty who want to use XP, but are outside of the bounds of the
concrete process.

http://www.martinfowler.com/articles/xpVariation.html (4 of 7)05/12/2003 15:37:15


Variations on a Theme of XP

One of the unusual things about XP that I particularly like is the fact that it does set itself very definite
bounds. It assumes a co-located team of up to a dozen or so developers. These bounds are pretty clear, but
there is much about XP that appeals to projects that fit outside these bounds. What happens if you have a
project with thirty developers or a project with a lot of people telecommuting? The principles of adaptivity
and people-orientation are still valid. Why not get as close to XP as possible?

So you get debate, debate between those who prefer the narrow view of XP and those that prefer the wider
view. The debate is intensified by the fact that XP has gained a lot of brand awareness. People are keen to
say they use XP because they know that saying that communicates a lot about the values and principles
that underlie their work, values that matter even if you have a large or distributed team.

XP does not have a steering committee that makes official pronouncements on what is or isn't XP. It is
more like a community with only informal arrangements, and the community is still somewhat undecided
on this question. Kent has stated he prefers XP to be a concrete process - a "stake in the ground". As he is
the accepted alpha male of the XP community that preference carries a lot of weight. So the predominant
view is that XP means the concrete process.

XP and Self-Adaptivity
So we take XP as the sharply defined process, the stake in the ground. How do we square this with the
need for self-adaptivity?

The clue to the answer comes with a statement made by Kent Beck when someone posed a question to him
about setting up maturity levels for XP.Most people reacted to this question with horror that there could be
any notion of CMM-like maturity levels for XP. Kent, as he often does, replied with a thoughtful
seriousness that frequently surprises people. He said that there were three maturity levels for XP:

● Level 1 is where you are doing all of the practices exactly by the book
● Level 2 is where you have adapted XP for your local conditions
● Level 3 is where you don't care whether you're doing XP or not

Here we see the self-adaptivity coming in- you must adapt XP to still be doing XP. As I put it: if you're
still doing XP in iteration 6 the way you were in iteration 1 then you're not doing XP.

But notice the maturity steps here. The levels assume that before adaptation, people do XP by the book.
The point here is that its hard to see how XP works without doing it. The combination of practices that
makes up XP work in a way that is very difficult to appreciate unless you've done them together so you
can see how they interact and work together. Reading and surmising about the effects is a poor substitute
for actually being there. I can certainly attest to the fact that there is a big difference between how I
thought XP would work, and what I saw when I worked on C3.

This is why so many of the advocates of XP put so much emphasis on doing XP by the book before

http://www.martinfowler.com/articles/xpVariation.html (5 of 7)05/12/2003 15:37:15


Variations on a Theme of XP

engaging in speculation as to how XP could be improved. Often this comes over, with some reason, as
closed-minded zealotry. But a lot of the time it is because XPs advocates remember their own early
skepticism and their inclination to do things differently. Only when they did XP did they realize that it
works in ways that surprised them. Once you've been surprised yourself, you're inclined to think that
others will be surprised, and thus reluctant to listen to someone who hasn't gone through that experience.

Varying the Concrete XP


This implies a different way to thinking about how to make a process be variable, one that uses a concrete
process as its basis. Rather than begin by figuring out how to use complicated yet tailorable process, begin
with a concrete process even if it's clearly not the best for your needs. Run with this sub-optimal yet
concrete process. Doing this will lead you to learn important things about the process that otherwise you'd
miss. Once you've done that, then start varying. Use tips from other processes to help you do that.

So this is the crux of how variation works in XP. You can only really understand how to tailor a
methodology if you really understand how it works. For a complex heavy methodology, this takes a lot of
work. A light methodology, with just a few practices and a strong leaning towards incremental
development and learning in the cycle, makes this much easier. Fundamentally it's easier to change a small
thing by adding bits, than to change a large thing by taking bits away.

But the hard part of understanding how XP, in particular, works is that it's very hard to really understand
how XP works without doing it. As such you've got to be very careful about tailoring XP until you've done
it enough to get a feel for how it works.

The best solution is to begin a project by doing XP by the book, letting it settle in for a few iterations, and
then tailoring it. However in most cases, folks aren't able to do that. Instead they need to apply practices
piecemeal, in order to solve the various problems as they can. I think that latter approach, while easier to
do, also carries a greater risk as you can miss how the practices interplay. So I think that with the latter
approach it's proportionately more important to have someone around who has seen XP click, and can thus
guide you from a position of knowledge.

Thus with XP you are still getting a set of practices and experiences to start with. But it is still only a start.
You'll need to adapt XP to your circumstances, but it's important to do that in the context of understanding
how well XP works. To my mind this means you should try XP as close to its book form as you can get
for a while, even if you don't think it will work as effectively as some modification might make it. Treat
that stage as a learning phase. After a few iterations, start adapting. I'll be surprised if your adaptations
then are the same as the initial set of adaptations that you first thought of.

XP and the Boundaries


So what's the future for XP and beyond its boundaries? At ThoughtWorks we've been using XP as the
basis for a project with around 60 people, half of whom are developers. This is clearly too big to be XP.

http://www.martinfowler.com/articles/xpVariation.html (6 of 7)05/12/2003 15:37:15


Variations on a Theme of XP

Yet we call it XP because XP has been the guiding philosophy behind what we do. There's a contradiction
there that I cannot deny. Perhaps it's better if we don't call it XP. Certainly we've had to vary the practices
a good bit to make it work, and due to the size we were never in a situation where the whole team had
experienced the "by the book" XP process.

Despite this I would prefer it if XP stays the stake in the ground behind its well defined boundaries. What
we are doing may be XP-influenced, but it's a different process. We may not name it, after all it's now
highly adapted to the particular project and will continue to adapt that way, so we hardly care whether or
not it is XP any more. I think other processes will and should appear that way and we'll see a flowering of
XP influenced processes grow. Maybe the best way of thinking about XP is that it's a seed, not a tree.

So when we choose to "buy" XP (there's no purchase cost after all), what we get is the seed. We can start
and take advantage of the experience of the XP community with a process that is small, concrete, and
therefore easier to understand that something that needs tailoring. For a few iterations we follow that
advice. But soon we have to build on it, adapting to our circumstances. As such we are still building on
experience, but we cannot consider using XP as a "cover your ass" defense. I don't think XP, and other
lightweights are suitable for that. and I don't see this as a problem. Lightweight methods don't work
anyway unless you have a truly empowered team that in the end will take control of its process. A seed is
an important part of any tree, but as any gardener will tell you, it's no guarantee of success to just throw
one in the ground..

Further Reading
● Adaptation: XP Style. from the folks at RoleModel Software
● When is it not XP? by Chet Hendrickson

© Copyright Martin Fowler, all rights reserved

http://www.martinfowler.com/articles/xpVariation.html (7 of 7)05/12/2003 15:37:15


The XP 2000 Conference

About Contact
Home Blog Articles Books ThoughtWorks
Me Me

The XP 2000 Conference


Martin Fowler
Chief Scientist, ThoughtWorks

Take a bunch of geeks to the beautiful beach of Poetta and what do they do? Stand around and talk about software!

Last Significant Update:

In late June over a hundred people gathered on the Mediterranean island of Sardinia to take part in the
XP2000 conference to discuss Extreme Programming (XP) and other flexible methodologies.

● Four War Stories


● Will XP be Unified?
● Open Minds
● A New Orientation
● Jack's View

http://www.martinfowler.com/articles/xp2000.html (1 of 8)05/12/2003 15:37:18


The XP 2000 Conference

Sardinia is not the obvious choice for an international software conference. It is a bit awkward to get to
and the delights of its beaches are lost on conference attendees who spend all their time indoors. The
important thing was that the hosts were warm, the food was excellent, and the conference was also pretty
good.

The conference was a nice size. Program Chair Michele Marchesi and his team had expected around 60
people to show, but got 160. So there were enough people to give the whole thing a buzz, but not so many
that you couldn't easily talk to the people there. The expected XP suspects were in attendance, including
Ron Jeffries, Robert Martin, Don Wells, and of course Kent Beck. There were also a few less directly
connected with XP, such as Erich Gamma, Dave Thomas, Ralph Johnson, and Alistair Cockburn.

The conference had tutorials on the first day, followed by two days of papers, panels, and invited talks.

Four War Stories

Kent Beck introduced Ron Jeffries by saying that his wife told him that she had no objection to Kent being a star if all his
groupies looked like Ron.

The first proper day of the conference opened with four invited talks, all of which talked about projects
and teams that had used adaptive processes, although only one of them used XP to the full. That one, of
course, was the oft-referenced Chrysler Payroll project, known as C3. Ron Jeffries stepped up to talk about
that, and gave a pretty complete description not just of its successes, but also what led to its cancellation.
To sum up, the project did very well in its first year or so, delivering a system that still pays around 10,000
salaried people at Chrysler every month. Later on, troubles gradually set in. Ron identified these as:

● mixed goals between the payroll department (who used the system) and the IS department (who
were paying for it)
● break down in communication between the team and the management both in payroll and IS

Robert Martin talked next, and his theme as a project for the an educational testing company. The project

http://www.martinfowler.com/articles/xp2000.html (2 of 8)05/12/2003 15:37:18


The XP 2000 Conference

was done over several years by Robert, Jim Newkirk, and various associates. The requirements were very
vague and open to change, so they dealt with this problem by short (one week) iterations and frequent
contact with the customer. Although they didn't use the full range of XP practices they found the key
elements made a success out of what could be a tricky situation, and that these kind of tight iterations can
work even in a C++ environment. This experience was the best example of the experiences which led their
company, Object Mentor, to their enthusiastic embrace of XP last year.

Ralph Johnson's example development was of the Refactoring Browser, the famed Smalltalk tool which is
a symbol of what is possible in refactoring tools. Developed as part of doctorate research at university, it
again used some XP practices to develop the tool. Again tight iterations and an evolutionary approach to
design were central, as was the active use of refactoring in the design.

The final example was that of Dave Thomas, the founder of Object Technology International (OTI). OTI
were known for many demanding early object-oriented projects which used Smalltalk and virtual machine
technology in embedded systems. His accent was on the people-orientation, automated testing, and again
the tight iterations. Contrary to many at the conference, he stressed that you can use these techniques with
fixed price projects.

The cumulative effect of the talks was that there were many ways to succeed with a lightweight
methodology. Like other methodologies, the lightweight approaches are not a panacea, but they provide
principles that can guide people towards success.

Will XP be Unified?
A recurring topic was the relationship between XP and the Rational Unified Process. Many people see a
need for the two to draw closer together, for various reasons. Dave Thomas reported that Ivar Jacobson
very much desires to see RUP embrace XP, effectively making XP an instance of RUP. Robert Martin
took the other tack: how do you make XP look like RUP to satisfy bosses who may insist on you doing
RUP? Robert has put together a pretty firm example of how you can do this in his collaboration with
Grady Booch and Jim Newkirk on the third edition of Booch's classic OO design book. He also announced
that he had been commissioned by Rational to include material in the official Rational Unified Process
documentation that would make sure that XP could be an instance of RUP.

http://www.martinfowler.com/articles/xp2000.html (3 of 8)05/12/2003 15:37:18


The XP 2000 Conference

Robert Martin announced that he has been commissioned by Rational to write material for the Rational Unified Process that
will allow XP to fit in with RUP

Here we see two questions: is it possible to fit XP and RUP together, and if so is it desirable? Robert's
approach, together with Ivar's desires seem to make the fit a matter only of time. If RUP is present, then
XP is certainly on the menu. The desirability is another matter. It seems that most XPers welcome the
approach to make it easier for people to adopt XP in the industry. However the concern is that using RUP-
XP will dilute XP leading people miss out on important practices.

In my view it makes little difference. Nothing will stop RUP including XP, and the problems of partial
usage of XP are no different with RUP than without. In the end the biggest issue revolves around people.
Adaptive processes are inherently people-oriented and they just won't work in an environment that treats
people as abstract resources. Whether XP is adopted under the flag of RUP has no effect on this more vital
issue.

Open Minds
Read many of the postings about XP on the Internet, and what you often get is a strong impression of a set
of zealots that oppose any deviation from the one true XP way. One of the best things about this
conference was that the zealotry was very much left at home. Instead I saw a conference that while
focused around XP topics, did not try to overly push the particular XP mantra.

The theme was more that although XP provide a good basis for software process, variations were both
allowed and accepted. Most people at the conference were very much partial adopters of XP at best, and
the conference topics allowed for plenty of talks which focused on just particular aspects of XP:
refactoring, testing, story gathering and like.

http://www.martinfowler.com/articles/xp2000.html (4 of 8)05/12/2003 15:37:18


The XP 2000 Conference

Alistair Cockburn is not one of the XP leaders, but he is a leading advocate of light methodologies. His approach stresses the
importance of human interaction and teaming in software development.

I, like Dave Thomas, was very relieved to see this openness. XP's attitude has helped it get people's
attention, but also provokes resistance. I've found it's practices very valuable, but I'm not the kind of
person to take the whole approach as a rigid set of rules to follow. Methodologies should be chosen and
adapted to fit the people who use them, not the other way around.

A New Orientation
There was no surprise about the last panel of the conference: the inevitable topic of how XP can be
adopted in the software industry. And the theme of the panel was that XP is just like any other new
technology trying to grow in the business world. The issue for many people was how they could use XP,
or some of XP, in their own organizations. Even if the attendees wanted to use it, could they persuade their
bosses to let them?

I think this is somewhat missing the point. One of the strong themes of adaptive methods is the fact that
they place technical responsibility of technical people, and that technical people should make technical
decisions. The question is not whether a company will allow XP, so much as whether a company will
allow technical decisions to be made by technical people. Without that the issue of XP is irrelevant. If
your company isn't like that the question becomes one of whether you can effect a change in your
company.

If that change isn't possible then you have to question why you should stay there. In a phrase I coined off
the cuff on a panel: "If you can't change your organization, change your organization!" This is not purely a
recruiting plug for ThoughtWorks (although we're always delighted to take good people from bad
companies), it's also a call to software professionals to remember that in the end nobody is more

http://www.martinfowler.com/articles/xp2000.html (5 of 8)05/12/2003 15:37:18


The XP 2000 Conference

responsible for your career than yourself, and this market is no time to be unhappy with your job.

Jack's View
Jack Bolles
ThoughtWorks

XP2000 has come and gone and was exceptional not for the topic but rather the quality of the discussion
and attendees. As our colleague Foemmel can tell you (about XMLOne), a subject's first conference can
be a lot of marketing and flag waving. Given the rather extreme nature of the topic, I expected a lot of the
latter, and was pleasantly disappointed. And with the exception of Robert Martin's "Ark of the Covenant"
speech, there was practically no marketing ;>

The crowd was thick with current and ex Smalltalkers, now working mostly in Java. There were also a fair
number of telecom people, mostly working in C. Talking to these two groups, I could see what drew them
to XP. The latter are used to a collaborative environment. When the working environment is also the
system, you tend to test your work, collaborate and communicate with other team members using the same
image. The telecom people have very tight schedules, hard to find bugs that need to be isolated and low
footprints that require careful coding standards.

Don Wells (left) has put together the sharpest looking XP site on the web.

What ties these groups together, and what kept coming up in sessions and other conversations, was the
absolute need for good communication among everyone involved in the development process. All of XP's
12 practices clearly facilitate communication. Some are between developers,some between development
and the customer, some between customers. The real gain, according to those that have embraced XP, is
when all the processes are running, communication facilitates improvements greater than the linear sum of
the parts.

One thing that occurred to me was that XP's 12 practices can be divided into two groups. The first group

http://www.martinfowler.com/articles/xp2000.html (6 of 8)05/12/2003 15:37:18


The XP 2000 Conference

consists of individual practices that (largely) don't rely on others for you to do. These include testing,
refactoring, simple design, and to a lesser extent, pair programming, sane work week, and coding
standards. The second group requires the team as a whole: small releases, continuous integration planning
game, on-site customer, collective ownership. There is no reason why a developer can't personally use the
individual practices. Setting a good example, whether it's testing your code or refactoring, tends to rub off
on people. Anecdotal evidence reports silent infiltration of XP has been used successfully.

Dave Thomas attributed many of the successes of OTI to the kinds of techniques talked about in the conference, and was
pleased that there was hardly any XP dogmatism.

It is less effective when trying to change group practices. Especially practices that involve teams beyond
the development team. Why is this? The individual practices, largely geared towards developers, are well-
known best practices that we all should be doing anyway. The team-oriented ones require customers and
managers to do things they are uncomfortable with, are not proven, and that require the perceived loss of
control (even if they never truly had control. i.e. the project schedule).

Getting everyone involved in the process has been a real challenge. There was a fair amount of hand
wringing about how to convince people to try it, especially management and customers. Martin Fowler
made the double entendre several times that, if your organization is not doing what you think it should,
you should "change your organization". Whether that meant change the way your organization works, or
change the organization you work for, was left as an exercise for the student.

But that does not belie the glaring hole in the XP literature and lore is how to get customers and managers
to "embrace change". Hopefully that will change before XP2001.

http://www.martinfowler.com/articles/xp2000.html (7 of 8)05/12/2003 15:37:18


The XP 2000 Conference

© Copyright Martin Fowler, all rights reserved

http://www.martinfowler.com/articles/xp2000.html (8 of 8)05/12/2003 15:37:18


Continuous Integration with Visual C++ and COM

Continuous Integration with Visual C++ and COM


William E. Caputo
ThoughtWorks

Oren Miller
ThoughtWorks

Last Significant Update:

The Continuous Integration principles are applicable in many different development environments. While the principles remain largely unchanged
from project to project, the implementation of this practice can vary considerably. Variables such as language, platform, team size & team
location provide unique implementation challenges. Here we will outline how we've implemented CI in a COM/Windows environment for a project
developing primarily in Visual C++.

● The More Often the Better


● What Is a Successful Build?
● Single Source Point
● Building the Code
● Self-Testing Code
● Automated Build
● Dependency Management
● What We Could Have Done Better
● Summing up

The More Often the Better


As noted in the main article, one of the least intuitive notions about integration is that less often does not result in less difficulty, it results in more
difficulty. This is especially true when developing with C++. The build time on a development machine can be lengthy if one waits more than half
a day to integrate, and every hour is not too often. As time between builds increases, it is more likely that a dependency will change requiring more
dependant files (and in VC++, dependant projects) to be rebuilt. If it takes too long to build, people are likely to avoid doing so, and the benefits of
CI are lost. As in all C++ projects, dependencies have a great impact on build time. Thus, one of the keys to successfully implementing CI with C+
+ is dependency management. More on this below.

What Is a Successful Build?


These are the actions we identified that needed to happen for us to have a successful build:

● All binaries had to be built and deployed:


❍ All the latest source files had to be checked out of the source code repository (in this case, StarTeam).

❍ Every binary had to be compiled, linked and deployed for loading.

❍ COM and COM+ objects had to be registered with the operating system.

● The database (SQL Server 2000) had to be built from scratch and populated with test data.
● All external services, started and ready to go.
● All unit test suites (which exercised the code both via COM interfaces, and native C++ interfaces) had to pass at 100%.
● Acceptance tests marked as part of our BVT had to pass at 100%.

If all of these steps completed without error or failure, we had a successful build. Otherwise, the build failed.

Single Source Point


One issue that presented additional difficulty using Visual C++ was the location of SDK libraries and binaries. These files must be installed into
the correct folders, discovered by the build process in a consistent order, and registered properly. Because of this, we found there is a minimum
standard setup that a target machine had to have in addition to being "clean."

http://www.martinfowler.com/articles/ciWithCom.html (1 of 8)05/12/2003 15:37:21


Continuous Integration with Visual C++ and COM

We found the following were best installed prior to introducing a machine to our project:

● Microsoft Visual Studio Version 6


● Visual Studio Service Pack 4
● Current Version of the Microsoft Platform SDK
● Current version of Microsoft XML Parser SDK
● Current version of Microsoft XML Parser

Since technically these SDK files are part of the "source" we had considered placing them with the rest of the code base in the repository. For
pragmatic reasons, it was easier to make all machines conform to this standard, than to extract the library code needed from these SDK's. Also, this
ensures that as updates and Service Packs are issued by Microsoft, they can be installed across all development and build machines consistently.

We did keep other third-party libraries in the repository. These were checked out and built just like our project-developed code.

Building the Code


As noted above, the first step in getting a successful build, is actually building the code. When we began implementing CI for this project several
constraints confronted us immediately:

● We had to retrofit the build process onto an existing code base.


● Developer's were all using the MS DevStudio IDE for development and building
● Development was being done using the ATL wizard which generates complex project files, and templated code that is managed by the IDE.
● The solution was needed quickly.

These constraints led to the decision to write scripts that manipulated MSDEV via its command line interface. MSDEV is the name of the
DevStudio IDE executable. It uses generated Make-like files in a proprietary format to manage its build environment.

MSDEV has a simple, yet flexible command line syntax.

msdev FileName [/MAKE "ProjectName - ConfigName | ALL"] [/REBUILD /CLEAN /NORECURSE /OUT LogFile /
USEENV]

Where FileName is the name of your project (.dsp) or workspace (.dsw) file.

For example, the following syntax deletes all intermediate files and then builds a project called
MyProject:

msdev MyProject.dsp /MAKE "MyProject - Win32 Debug" /REBUILD

From: Building a Project from the Command Line


-- [MSDN Library-MSDEV]

We quickly created a Windows Scripting Host(WSH) script that could traverse the source tree, build and execute command line MSDEV
commands, and monitor the success or failure of that execution.

Using MSDEV allowed us to build the entire source tree using a single script, and still use the IDE for configuration of project settings, and project
dependencies (thus allowing the developers to continue building from within the IDE).

We had satisfied our initial build requirements!

This was a quick solution, but there were issues, the largest being the management of dependencies, and project settings. MSDEV uses two files to
manage its projects: A workspace file (.dsw) and a Project file (.dsp). Unfortunately, the workspace file defines how projects depend on one
another, so one cannot simply include a project as a dependency in a workspace and have that project's dependencies managed without adding
them to the workspace as well. Worse, each .dsp has its own build settings, causing a large maintenance burden.

Here are some strategies that deal with these issues:

http://www.martinfowler.com/articles/ciWithCom.html (2 of 8)05/12/2003 15:37:21


Continuous Integration with Visual C++ and COM

● Keep all projects in a single workspace. This does nothing to solve the project settings, and in our case we had many workspaces due to the
fact that this was an existing code base.
● Move to using MAKE. (This seems most common from what I have heard from other VC++ programmers)
● Migrate to Ant. (this is possible in VC++ because the Microsoft compiler does time stamp checking)
● Manage dependencies using file structure, folder structure, standards and judicious use of dsw files. Run your builds intelligently so that
certain code trees get built before others.

We chose the final option because it fit within our constraints. What we found however, is that while this worked well in the short term, as we
refactored our code, we started migrating more toward the first option (fewer, larger workspaces). As time went on, we found the Ant and Make
options much more attractive. Given the option, I would recommend using Ant and/or Make from the beginning. However, if you are faced (as we
were) with an existing file structure centered on the dsw/dsp setup, the MSDEV command line option can ease your migration headaches.

So, as the code base grew we migrated to using Ant and CruiseControl to call MSDEV. This gave us more flexibility than the simple script, and the
developers could continue using the MS Visual Studio environment as they had been.

We evolved several standards that supported CI as the project progressed. Here is a list of the more important in no particular order:

● Every machine must have an environment variable pointing to the base of our code directory (we named this variable DEVROOT)
● Several folders are needed as part of the machine's PATH variable definition
● The directories settings in the DevStudio IDE must have a consistent order and membership. This is a source of problems as each user has
their own settings. We managed this via communication, and a .reg file that updated the appropriate registry key:
( HKCU\Software\Microsoft\DevStudio\6.0\Build System\Components\Platforms\Win32 (x86)\Directories )
● Each project must have a custom build step that does the following (some are optional):
❍ Copy binary to a common bin folder

❍ Copy type library to a common include folder

❍ Copy public interface headers to a common include folder

❍ Copy any static libraries to a common lib folder

❍ Registers the deployed COM and COM+ components (using regsvr32 for COM and a WSH script for COM+)

● Any project that is to be built in the automated build, must share the name of its workspace, or be a dependency of such a project. Note, that
this introduced a loop hole: By not having any projects in the workspace that shared its name, code would be skipped. We used this as a
way to exclude non-production code from building, but it can also lead to non-standard production code being skipped as well - Caveat
Emptor!
● All projects define a testing entry point on their dlls to return their test suite

Note that by keeping the registration of the components in the project settings (in fact ATL adds this by default) we satisfy another of our build
requirements, and avoid having to manage the information at a macro level. We do not use the ATL default. The command registers the copied
version of the dll. A typical COM component might have the following custom build step:

Commands:
copy $(InputPath) $(DEVROOT)\Bin
copy $(ProjDir)\*.tlb $(DEVROOT)\Include
copy $(ProjDir)\*.h $(DEVROOT)\Include\
regsvr32 /s "$(DEVROOT)\Bin\$(InputName).dll"
echo regsvr32 exec. time > "$(OutDir)\install.trg"

Outputs:
$(DEVROOT)\Bin\$(TargetName).dll
$(OutDir)\install.trg

Where DEVROOT is the environment variable defined as part of our standard.

All of these things are necessary for any project. The key points to keep in mind are:

● Remove the need to do this manually.


● Make these things easy to maintain
● Provide an alternative to relying on the memory of the developers for achieving these goals

Self-Testing Code
http://www.martinfowler.com/articles/ciWithCom.html (3 of 8)05/12/2003 15:37:21
Continuous Integration with Visual C++ and COM

We chose CPPUnit as our Unit Testing framework. Initially we simply used the existing text ui testRunner that comes with CPPUnit, as it works
well for single Visual Studio projects. As our code base grew we wrote a new runner that allowed us to better manage dependencies and provided
more flexible test discovery, thus facilitating its integration into the CI framework we had built.

Automated Build
As mentioned above we used Ant and CruiseControl to provide us with automated builds. This tied together monitoring the code repository,
building our components, building our database, testing the code, and communicating the status via a web site and email. Here is how we did it:

First off, keep in mind what Ant is not: Ant is not a complete substitute for MAKE. Specifically, Ant does not provide the time-stamp checking
that MAKE provides. As a result, if you are going to build C++ code with Ant, you will need to call a tool in your task that does this checking for
you. Since we were using MSDEV (which is a MAKE-like tool in its own right) to do our actual building, what we ended up using Ant for was the
management of the various build steps, and to efficiently walk the directory tree, calling MSDEV where appropriate.

In case you are wondering, this is not ideal. It means managing both an Ant script, and the dsp files. However, our Ant script was very simple,
consisting only of the high-level build steps like building the code, building the database, stopping and starting services, registering COM dll's etc.
The careful reader will have noted that above we mentioned that we registered the dlls from within the dsp files. We have begun migrating that to
the Ant scripts to reduce the maintenance burden on the .dsp files. Since Ant concerns itself only with high-level stuff, MSDEV manages the file-
level dependencies. This decentralizes the responsibility, and keeps the Ant configuration very stable. This was important to us, as almost all of the
developers on this project were new to Ant and Java, but had worked with VC++ for a long time.

As our code base grew we considered migrating some of the build responsibility up into the Ant scripts. CL (the Visual C++ compiler) provides
time-stamp versioning so it can be called from an Ant target and provide the same results as Make. Such a change would have increased the
maintenance of the Ant scripts, but also would have provided a reduction in the number of workspaces, and projects that had to be maintained.

CruiseControl provided our project with several benefits. Among these were monitoring changes in the code base, organizing the activities we
wanted to happen every time someone checked in, and reporting the results. Because CruiseControl is open source, we were able to customize it as
our needs dictated.

Organizing the build activites was only part of the benefits CruiseControl provided. Perhaps even more signficantly, was the continous testing,
reporting, and deployment that we able to do. Our unit tests, and our customer-written acceptance tests were also run after each successful build.
Deployment can be automated with CruiseControl as well, thus taking the guesswork out of this critical task.

If you are unfamiliar with CruiseControl I suggest you check it out. It makes these central activities of Continuous Integration much easier to
manage.

As mentioned above, we chose StarTeam as our source repository. One of the reasons for this was because the StarTeam API, while sometimes
awkward, allows complete scripting of its functionality and yet can still be integrated with Dev Studio. The modification set we developed to
interface with StarTeam has been folded into the default CruiseControl package.

Because of several differences between the debug and release builds of our application, we chose to actually run two separate build machines, one
for each configuration. Both instances of CC monitored the repository for changes, and notified developers when builds were complete. When the
release build ran correctly, a final task copied the binaries to a deployment staging area so the application could be deployed into any one of several
test and production environments.

Finally, since CruiseControl produces XML logs of its output, and uses XSLT to create its reports, it was easy for us to group information by story
card as to what tests were passing, and what were not. Thus we were able to give the customer exactly the kind of information that was most useful
to him.

More than just providing build status information, the CruiseControl data related to all aspects of our project, including project status, and feature
completion status. Up-to-date class diagrams thanks to auto-generated documentation via Doxygen was also maintenance free. Far from simply
being of interest to developers, the data generated and displayed by our CruiseControl installation provided much needed communication to project
managers, customers, testers, and even the executives - continuously and accurately.

Here is an example of what our acceptance test results looked like after CruiseControl ran the tests:

http://www.martinfowler.com/articles/ciWithCom.html (4 of 8)05/12/2003 15:37:21


Continuous Integration with Visual C++ and COM

An example of our build page (Note the builds are named, not numbered)

Dependency Management
Like most things, CI is harder to manage when using C++. The main reason is the need to manage physical dependencies (which you should be
doing anyway). If you haven't done so, I recommend you pick up a copy of Large Scale C++ Software Design., by John Lakos. This book provides
good coverage of how to manage the physical design of your application.

One thing we didn't foresee when we began setting up Continuous Integration on this project was how our physical layout for our then relatively
small code-base was going to become a bottleneck as our project grew in size. But then an interesting thing happened. By working to make our
system build continuously, cleanly, & automatically we were forced to confront many of the issues and pitfalls that Lakos outlines as problems for
larger projects.

Even more importantly, when we needed to change our physical structure, we could do so -- continuously because we were never more than about
30 minutes from feedback on our changes. Also, the pain of increasing build time, right there in front of us, gave us ample warning when our
physical design was in need of refactoring, before it became critical.

You must pay attention to your code's physical layout when implementing Continuous Integration when using C++, but you have to manage this
anyway for an application with more than a few files and components. By implementing CI, you address this issue early in the project, and have
constant feedback on the health of your physical design.

http://www.martinfowler.com/articles/ciWithCom.html (5 of 8)05/12/2003 15:37:21


Continuous Integration with Visual C++ and COM

As Martin points out in his article, "Is Design Dead?", there are some XP practices that provide direct benefit, but only if you do the enabling XP
practices. CI enables the XP principle of evolutionary design Do The Simplest Thing That Can Possibly Work. Since you have constant feedback
on the "health" of your physical design, you can limit the upfront thinking on this topic to that necessary to get Continuous Integration working,
and then refactor (a third XP principle) your physical layout as your design needs change and grow. As I mentioned above, CI encourages you to
adopt good habits early, so this can be a big win for your project

There is one dependency pitfall specific to Visual C++ and COM that I should mention: COM can cause compile-time dependencies in your code
beyond those mentioned in Lakos' book. One of the benefits of COM, and one of its big selling points is that clients of your COM interfaces
remain blissfully ignorant of your implementation -- including its physical location. So, how does this present a compile-time dependency? The
answer is via the #import statement.

Microsoft provides a language extension to C++: #import. When the pre-processor encounters this directive, it resolves and locates the given type
library, and generates two files a .tli file, and a .tlh file. The purpose of these two files is to provide the using component access to: a calling syntax
similar to VB for the methods on the contained interfaces, the CLSID's and other GUID's needed to create the resources in the type library, support
for intellisense, and other symbols exported from the .dll (e.g. enumerations).

In short, it provides a lot of syntactic sugar that can make working with COM easier - or more complex. So why use it? Well, if you want the
syntactic assistance its nice, but there are two other more insidious reasons why it can be difficult to avoid this statement: First, ATL uses this
statement a lot, and second, there is a small but measurable performance gain when using the CLSID's because you avoid a trip to the COM
subsystem when creating instances.

Because the physical file must be discovered at compile-time and because COM objects are often used by high-level components to access lower-
level components, its easy to get long dependency chains in your code.

So, what do you do?

The purported benefits of #import are convenience and performance. Convenience is a personal choice. Personally, I think the #import statement
introduces almost as many complexities as it removes, so convenience is a minimal benefit. As for performance, pre-optimization is the source of
much wasted time on a project. Use CoCreateInstance with the ProgID's when building your system. If you follow the old adage of "Make it work,
make it right, make it fast", you will turn to performance tuning after you implement a feature. When performance tuning, measure your system,
define your bottlenecks, and then if you find that extra API call is causing significant performance loss, resort to the #import statement.

If you need the benefits of the #import statement, my recommendation is that you apply the Dependency Inversion Principle. Pull your .idl files up
high in your physical hierarchy, perhaps keeping them all in one workspace for easy reference, and have your low-level interfaces inherit from
them with another MS language extension, the #importlib statement. You can use this statement inside your IDL library definitions to bring in the
high-level interface definition. Now your high-level module and your low-level interface are physical peers, equally dependant on a higher level
abstraction.

What We Could Have Done Better


No project is perfect. Why? Because every time we humans think we have everything figured out, reality steps in and reminds us of how imperfect
we are. Or as a great poet once said: "The best-laid schemes o' mice an 'men Gang aft agley". In short, we make do with what we got.

This project was no exception. Implementing Continuous Integration presented us with several challenges and some of our solutions would not
necessarily be considered ideal. Keep in mind however, that this configuration worked well enough to provide a project started with no intention of
practicing Continuous Integration the benefits thereof all the way through its first release.

The key to making that happen was recognizing that perfect solutions unattained are of less value than imperfect solutions that work right now. In
other words, shoot for perfection, but know when good enough is good enough.

That said, reflecting on what one can do better is a valuable exercise both for the improvement of an existing project, and as a means of moving
toward more general solutions. This section attempts to do that.

For starters, things would have been much easier if we had been continuously integrating from the first line of code. This can't be stressed enough,
so I will say it again: Start implementing your CI infrastructure on day 0 of your project. It will be faster and easier to do. The best part is you can
start simply, and refactor your CI implementation along with your physical layout and your code.

Another thing we felt hindered us was never being able to completely migrate to a build configuration tool such as Make or Ant. The Workspace/

http://www.martinfowler.com/articles/ciWithCom.html (6 of 8)05/12/2003 15:37:21


Continuous Integration with Visual C++ and COM

Project file setup in Visual Studio makes CI more difficult, particularly with more than a couple of developers. We settled on a hybrid approach
because people were more familiar with the IDE way of doing things, but CI is simpler if you just use a single file management solution, and dsp's
don't cut it.

Finally, while we did a decent job managing dependencies, we could have benefited from more detailed measurements on compile times. A good
dependency analyzer, and some enhancements to our Ant scripts could have given us this information. Aggressively refactoring code toward, and
judicious selection of, physical design best-practices can go a long way toward making dependency management continuous and painless.

Summing up
As you can see from this article, there is little, if any conceptual difference between doing CI on a COM/C++ project and doing CI on a Java
project. It all comes down to automating check-in, build, test, report, check-out in as tight a feedback loop as you can manage. There are several
implementation items that are unique to COM and VC++, this article tries to cover those that might cause some hang-ups the first time you try to
apply Continuous Integration to your project.

A successful build includes more than just compiling and linking. You must also ensure that COM components get registered correctly, your tests
are passing, and external dependencies like services and databases are in their proper configuration.

It is imperative that all the files needed to set up your system, are kept in a single place. A source code repository is a vital part of Continuous
Integration. It is possible that there are certain things that represent a minimal configuration that a machine must have prior to building your
system. Items like Service Packs, and SDK's may be better installed once on the build machine.

When compiling and linking your code, you need to be able to manage your files effectively, and yet still be able to build from an automated script.
Tools such as MAKE and Ant offer this functionality, but present problems when used in conjunction with the MS DevStudio IDE. Msdev.exe is a
viable alternative. You can drive this executable from batch or WSH scripts, or call from a simple Ant task. MSDEV provides some answers when
you need to balance usability of the Microsoft tool set, and your implementation.

Tools like Ant and CruiseControl can significantly reduce the ramp-up time for getting Continuous Integration going on your project. Using
CruiseControl to coordinate our builds gave us ample room for customization, and freed us from much of the detailed mechanics of getting CI up
and running.

The key to successfully implementing CI in C++ is dependency management. Continuous Integration forces you to consider your physical layout
early in the project. At the same time, CI frees you from spending too much time on this critical aspect of your design - as you will have constant
feedback regarding your build times, and the impact your physical changes have on them. An additional caveat in COM development is the impact
of the #import statement on your physical design. A good strategy is to reserve this statement as an optimization strategy.

Finally, keep in mind that no project is perfect, nor are any two CI implementations going to be identical. What counts are the principles of
Continuous Integration, and the benefits it can bring to your project. Always consider specific solutions to be a result of the forces at work in a
specific context. Keep an eye for improvements and use them to eliminate your biggest issues.

As you implement CI in Visual C++ I hope that you find the pitfalls and solutions outlined here useful. Suggestions on ways to improve this
article, obvious errors and omissions, and general feedback are always welcome.

Good luck!

References

"Ant"
http://jakarta.apache.org/ant/index.html
"CruiseControl"
http://cruisecontrol.sourceforge.org
"CPPUnit"
http://www.xProgramming.com/software.htm
"StarTeam"
http://www.starbase.com
"Doxygen"
http://www.doxygen.org
"Large Scale C++ Software Design."

http://www.martinfowler.com/articles/ciWithCom.html (7 of 8)05/12/2003 15:37:21


Continuous Integration with Visual C++ and COM

Lakos, John Addison-Wesley 1994 Large Scale C++ Software Design Book: details not given , ISBN: 020163362
""Is Design Dead?""
http://www.martinfowler.com/articles/designDead.html
"Dependency Inversion Principle"
http://www.objectmentor.com/publications/dip.pdf
""The best-laid schemes o' mice an 'men Gang aft agley""
http://www.robertburns.org/works/75.html

About the Authors

William E. Caputo
Bill is a developer and process mentor at ThoughtWorks, Inc. A Microsoft Certified Solution Developer, he has been a programmer and consultant
in several domains, including Accounting, Logistics, and Securities Trading. He is a regular participant in the online Extreme Programming
community, and the Chicago Agile Developers group. He splits his free time between several small open-source projects, and spending time with
his family.

Oren Miller
Oren is a developer who has recently joined ThoughtWorks. He comes from Stafford Trading where he has worked for three years developing real-
time trading applications.

© Copyright William E. Caputo, all rights reserved

http://www.martinfowler.com/articles/ciWithCom.html (8 of 8)05/12/2003 15:37:21


Martin Fowler

About Contact
Home Blog Articles Books ThoughtWorks
Me Me

XP (Extreme Programming)
Over the last few years I've become very interested in the software process Extreme Programming. The
process was developed by Kent Beck, a well known figure in the OO community. XP is a very different
software process for several reasons. For a start, unlike most methodologies, it is a very lightweight
process which doesn't demand large amounts of paper to make it work. Furthermore it has a strong
emphasis on testing and incremental development: both of which are vital to successful projects

One of XP's most difficult areas is its emphasis on evolutionary design, where a software design is not
planned in advance, but evolved as it is built. This is a process that makes active use of refactoring. While
you can use refactoring with any software process, XP attempts to really take the most advantage of it.

XP is a very controversial technique, but I think its influence on software process will be profound. I also
think that it should be high on your list of processes if you are running a project with up to a dozen co-
located developers with uncertain or volatile requirements.

To find out more about XP the best starting point is Kent Beck's book. There's also quite a few sites on the
web where you can find out more about XP. A good place to start is RoleModel's XPDistilled, or Jim
Highsmith's cutter article on XP. Ron Jeffries and Don Wells both have good sites which try to give a
fairly complete picture of XP.

Two recent books give more details on the mechanics of XP. Planning Extreme Programming talks in
more detail about the planning processes within XP. Extreme Programming Installed talks about how XP
was put into practice at a major project.

There's plenty of other web sites that provide information on XP. For ongoing discussion the best place to
look at the moment is the XP egroup set up by ObjectMentor . Much of the original exploration and
discussion of XP occurred on the wiki. Also worth a look is Bill Wake's set of "XPlorations" which
discuss his experiences in learning about XP.

Although XP has grabbed most of the oxygen in this space, it isn't the only lightweight process around.
My new methodology article gives an overview of the whole field of light methodologies and discusses
my ideas on the rationale for these approaches and suggestions on when you should use them.

http://www.martinfowler.com/xp.html (1 of 2)05/12/2003 15:37:22


Martin Fowler

© Copyright Martin Fowler, all rights reserved

http://www.martinfowler.com/xp.html (2 of 2)05/12/2003 15:37:22


METHODS IN PRACTICE

Martin Fowler
fowler@acm.org

Keeping Software
Soft
   when you first programmed? I re- seem to get the same lament: “The users keep changing the

D member the wonderful way in which I could type


a few statements in some obtuse language into the
machine, debug a bit, and the machine would respond. Not
just was it easy to get the computer to do something, it was
requirements.” This always surprises me: I’m surprised anyone
is surprised by changing requirements. I’ve never come across
a serious project where requirements don’t change. You can
get users to sign off on requirements documents in every
also easy to change the program to get it to do something blood group, but they still change their mind.
else. It was just a matter of a few changes and a little debug- They change their mind for several reasons. One is that it is
ging. After all, the whole point of software was to be soft. very hard to visualize what a computer system will look like.
Of course, the changeability of software was an illusion. In Only when you have it in front of you and start using it for
many ways, one of the biggest differences between a software real work do you find out what really is useful and what isn’t.
developer and a regular human is that the software developers Another is that businesses change, and a very real and impor-
know how hard it is to change software. Or rather, it’s not that tant requirement six months ago can become minor as a busi-
it’s hard to change software, it’s just hard to change software ness changes. Exacerbating this is the fact that users increas-
without it breaking. ingly have done a little programming themselves: some VB
This problem is something that software people have here, an Excel macro there. So they know that it’s easy to
known about for a long time. It is why doing ad hoc design— change software (they never get systems with the dependency
designing as you go about building a program—doesn’t work problems that professionals deal with).
for larger-scale systems. For many, this is the challenge of requirements engineer-
To resolve this problem, software developers took inspira- ing. We need to be better at getting requirements right in ad-
tion from other branches of engineering. In these disciplines, vance, to spend more time to get them right, to come up with
there is a clear separation between the design process and the new techniques. I used to believe this too, but now I’ve come
construction process. The designers communicate with the to the conclusion that this is unreachable, at least for a while.
construction people by using drawings that lay out exactly One of the key issues here is the balance of wants and costs.
how something is to be built. If you buy a car and the salesman says, “Would you like a sun-
This idea underpins most of the methods in software de- roof,” the first question you’ll ask is, “How much?” For $20 I
velopment. Instead of ad hoc design, we have what I call up- would have it fitted, for $20,000 I’d do without. We cannot ex-
front design. The idea is that designers make design decisions pect our users to fix their requirements until we can estimate
before those decisions are programmed. The idea is that once our costs with reasonable accuracy. Unfortunately, we are very
the design is developed, it should not significantly change after bad at cost estimation. I don’t think this is because software
programming has started. Of course, changes do occur, but developers are stupid; the problem is that our basic materials
the explicit purpose of the up-front process is to minimize keep changing so quickly. Civil engineers would find it diffi-
these changes. cult to estimate if the fundamental properties of concrete
The difficulty, of course, is getting these designs close kept undergoing a major “upgrade” every year.
enough that you don’t have any significant changes that cause So what’s the alternative? I think it comes down to expect-
the design to deteriorate. This is where the practical problems ing requirements to change and using a development process
start appearing—it’s hard to get a design right in the beginning. that relishes change. This strikes at the core of the up-front de-
sign process. If requirements change without warning, how
The Reality of Changing Requirements But there is a can we develop a stable up-front design?
more fundamental problem. From time to time, I have to visit
badly messed-up projects, to see if there is a way out of trou- Making Change Easier The answer is to build software
ble. Whenever this occurs and I talk to the developers, I always to make it more able to deal with unanticipated change. (We
can build a design that caters for anticipated changes—it is the
Martin Fowler is an independent consultant based in Boston, unanticipated ones that bite you in the bum.) Objects are a
Massachusetts. key part of this. By using objects with encapsulation and poly-

www.DistributedComputing.com DISTRIBUTED
Computing 55
METHODS IN PRACTICE

morphic interfaces, we can improve the packaging of our soft- So dynamic design can lead to simpler designs, without
ware, thus reducing the dependencies and making things eas- sacrificing flexibility. This makes the design process easier and
ier to change. less stressful. Once you get a broad sense of those things that
Dynamic development environments also help with brows- refactor easily, you don’t even think of the flexible solutions.
ers, quick ways to get at cross-references, debuggers and in- You have the confidence to refactor if the time comes. As Kent
spectors that let you explore code, and rapid turns of the com- Beck advises, you build the simplest thing that could possibly
pile/link cycle. For many professional developers, these tools work. As for the flexible, complex design, most of the time
are still new, but any Smalltalker knows how much difference you aren’t going to need it.
it makes when you can edit code in a debugger and have the That’s quite a change in design process, and it’s been a big
change made instantly, without an attention-breaking gap shift for me as a designer. It has several preconditions. You
while compiling and linking go on. need good tests, you need objects, you need to know how to
Refactoring plays a big role here too. Refactoring is a set refactor. But the reward is the ability to put away the fear of
of techniques that let you change the design of software effi- changing requirements and to be responsive to your users
ciently without introducing bugs. With refactoring, if you get without sacrificing your design, and thus your future. Z
a design wrong, you can change it later without incurring a
huge cost.

Dynamic Design All of these techniques point toward a


CHEVY NOVA AWARDS
Here are the nominees for the Chevy Nova
Online
shift in the way we can go about doing design, moving toward Award, given in honor of GM’s fiasco in OFFLINE
what I call dynamic design. With dynamic design, you don’t try trying to market the car in Central and
to get the design right at the beginning. This doesn’t mean South America ( in Spanish,“no va” means “it doesn’t go."
you abandon up-front design; you still do it, but now you don’t • The Dairy Association’s huge success with the campaign “Got
try to find the best solution. Instead all you want is some reason- Milk?” prompted them to expand advertising to Mexico. How-
able solution. You know that as you build the solution, as you ever, it was soon brought to their attention the Spanish transla-
understand more about the problem, you will realize that the tion read “Are you lactating?"
best solution is different from what you originally came up with. • Coors put its slogan, “Turn It Loose,” into Spanish, where it
With refactoring, objects, and a dynamic environment, this is was read as “Suffer from Diarrhea."
not a problem, for it is no longer expensive to make the changes. • Scandinavian vacuum manufacturer Electrolux used the follow-
An important result of this change in emphasis is a greater ing in an American campaign: “Nothing sucks like an Electrolux."
movement toward simplicity of design. Before I used dynamic • Clairol introduced the “Mist Stick,” a curling iron, into Germany,
design, I was always looking for flexible solutions. With any only to find out that “mist” is slang for manure. Not too many
requirement I would be wondering about how that require- people had use for the “Manure Stick."
ment would change during the life of the system. Because de- • When Gerber started selling baby food in Africa, it used the
sign changes were expensive, I would try to build a design that same packaging as in the US, with the smiling baby on the label.
would stand up to the changes that I could foresee. Later they learned that in Africa, companies routinely put on la-
The problem with building a flexible solution is that flexi- bels pictures of what’s inside, since many people can’t read.
bility costs. Flexible solutions are more complex than simple • In China, Pepsi’s “Come alive with the Pepsi Generation” trans-
ones. The resulting software is then more difficult to maintain lated into “Pepsi brings your ancestors back from the grave.”
in general, although it is easier to flex in the direction I had in • The Coca-Cola name in China was first read as “Kekoukela,"
mind. However, you have to understand how to flex the de- meaning “bite the wax tadpole” or “female horse stuffed with
sign. For one or two aspects this is no big deal, but changes oc- wax," depending on the dialect. Coke researched 40,000 charac-
cur throughout the system. Building this flexibility in all these ters to find a phonetic equivalent “kokou kole," translating into
places makes the overall system a lot more complex and ex- “happiness in the mouth."
pensive to maintain. • Frank Perdue’s chicken slogan, “It takes a strong man to make
The big frustration, of course, is that all this flexibility is a tender chicken” was translated into Spanish as “it takes an
not needed. Some pieces of it will be, but it’s impossible to aroused man to make a chicken affectionate."
predict which. So to gain the flexibility you need, you have to • When Parker Pen marketed a ball-point pen in Mexico, its ads
put in a lot more flexibility than you need. were supposed to have read, “It won’t leak in your pocket and
With dynamic design, you approach the risks of change dif- embarrass you.” The company thought that the word “em-
ferently. You still think about potential changes, you still con- barazar” (to impregnate) meant to embarrass, so the ad read:
sider flexible solutions. But instead of implementing these “It won’t leak in your pocket and make you pregnant!"
flexible solutions, you ask yourself, “How difficult is it going • When American Airlines wanted to advertise its new leather
to be to change a simple solution into a flexible solution?” If, first class seats in the Mexican market, it translated its “Fly in
as happens most of the time, the answer is, “Pretty easy,” then Leather"campaign literally, which meant “Fly Naked” (vuela en
you just implement the simple solution. cuero) in Spanish.

56 DISTRIBUTED
Computing December 1998
The Almighty Thud

The Almighty Thud

by Martin Fowler: column for November/December 1997 Japanese


Transalation

I was chatting with a client about an object model review they wanted to me to do. “We can send some
documentation in advance, would that be useful?” they asked. I replied in the affirmative, hoping that I
was not lying. Two days later the UPS man dropped the package off outside my door, it made a loud
noise. It was a good inch and a half of documentation.

I opened it up and found a print-out provided from a CASE tool. It showed a few diagrams, and gave
exhaustive descriptions of every class, with every attribute, and every operation. All of these had
definitions. The Contract class was defined as “a contract between many parties”, its dateSigned
attribute was defined as “the date the contract was signed”. I read through the inch and a half of
documentation, but at the end I was little wiser. There was much on what the objects were, but little
explanation of what they were meant to do. It wasn’t the first time this had happened, and I’ll be
surprised if it is the last.

Why do we bother with models or documentation? They don’t execute, and our customers pay us for
working code, not pretty pictures. We bother with models to communicate. The idea is that a graphical
object model can show how objects fit together more clearly than looking at the source, an interaction
diagram can show a collaboration better than figuring out the call path from several class definitions.
But so often the design documentation fails in this, and leaves me puzzled on my sofa.

Part of the problem is the CASE tools that people use for this kind of work. (CASE tools have two
purposes, documentation and code generation, and I’m only talking about the former role here.) CASE
tools encourage a dictionary mentality. You make an entry for every class, you show every class and
every attribute on the diagrams, you draw an interaction diagram for every use case. They encourage
completism by helping you answer the question “have we documented everything?”

But that question is the wrong question. If you document everything, you are giving everything an equal

http://www.martinfowler.com/distributedComputing/thud.html (1 of 3)05/12/2003 15:37:26


The Almighty Thud

weight. Do that for a complex system, and you are buried in detail. In any system there are some aspects
that are more important than the others, key aspects of the system that once understood, will help
someone to learn more. The art in documentation is to find how to document these aspects as clearly as
possible. In this you emphasize these areas, and leave the details for the code.

Above all this documentation must be brief. Only if it is brief will people read it and understand it. Only
if it is brief will you bother to keep it up to date. You won’t be able to talk about everything, and nor
should you. A friend of mine told me about one project where they were reluctant to change class
names, not because the code took too long to change, but the documentation took too long to change.
When documentation becomes a problem you should deal with it. Throw at least half of it away.

What should you say?


How should you choose what to show? I’m afraid that is down to your professional judgement. There
are no rules to guide you, just your own skill as a designer and communicator. Maybe that is why people
try to show everything, because they cannot decide what to leave out. So here is my approach, as it
stands at the moment.

If your system is of any reasonable size, divide your system into packages (a la UML or Java). Each
package consists of a group of classes that work together for a particular purpose. Document the overall
structure of your system with a diagram that shows packages and their dependencies. (In UML this is a
specific use of a class diagram, I use it so often that I like to name it a package diagram, see my book
UML Distilled.) Work with your design to minimize these dependencies, this is the key to minimizing
the coupling in your system. (There’s not much to read on how to do this, the best one I know is Robert
Martin’s Designing Object-Oriented C++ Applications Using the Booch Method.)

For each package, write a brief document. The basis of the document is some narrative text that
describes the key things the package does, and how it does it. UML diagrams can be used to help
support this. Draw a class diagram that shows the important classes in the package but not necessarily all
of them. For each class show only the key attributes and operations, definitely don’t show all of them.
Concentrate on interface rather than implementation. For each important collaboration in the package,
show an interaction diagram. If any class has interesting lifecycle behavior, then show it with a state
diagram. The document should be small enough that you don’t find it a problem keeping it up to date. I
usually try to keep it to no more than a dozen pages.

As well as documentation per package, it is also useful to show how collaborations extend across
packages. For this identify the key use cases in the system, and document them with interaction
diagrams and narrative. A class diagram that highlights the key classes involved is also useful. Many
people advocate drawing interaction diagrams for every use case in the system. I feel this can lead to too
much documentation, but if you find it useful, and you find it isn’t a problem to keep it up to date, then
go ahead and do it. Even so you should identify no more than a dozen key use-cases to highlight as the
ones that everyone needs to understand.

http://www.martinfowler.com/distributedComputing/thud.html (2 of 3)05/12/2003 15:37:26


The Almighty Thud

Communication is the key


In this entire article I’m stressing communication. I’ve taken a few swipes at CASE tools, but that is
primarily to say that using a tool does not by itself mean you are communicating. Any tool can help or
hinder communication, how you use it determines the outcome.
A project I know bought a multi-user CASE tool that any developer can access from their workstation.
All designs have to be put into the CASE tool. But just because any developer can use it does not mean
that every developer does use it. In fact very few developers looked at the models in the CASE tool, and
even fewer understood them. Realizing this the architect of the project took over an area of wall at the
office, and covered it with a series of diagrams that showed the half-dozen key collaborations in the
system. He showed them using object diagrams with color-coding to help emphasize what was going on.
It does not mean that all the developers understand all the design, but at least now they can see what the
important elements are.

As I started to write this article I was overwhelmed by the things I could talk about. Lots of anecdotes
and tips came to mind. But I know that to get you to read and remember this article I could only talk
about a few of them. I had to select the key things that I had to mention. Communication is all about
that. The key to good communication is to highlight the important things to say. Saying everything is not
communication. That just passes the selection of the important things onto your readers, and discourages
them with a heavy document. That selection of information is one of the most important parts of
communication, and it is the responsibility of every designer.

http://www.martinfowler.com/distributedComputing/thud.html (3 of 3)05/12/2003 15:37:26


TechNetCast Play

HOME
ARCHIVES
Keeping Software Soft
MP3 STACK
TOP-30 by Martin Fowler. Software development is often compared to structural engineering but the
comparison, argues Martin Fowler, is quite misleading. In fact, software design requirements are
Dr. Dobbs Journal volatile: "We need to keep software soft —we need to be able to adapt our software in a responsive
way to match the volatility of changing requirements." A leading software design methodologist makes
mailing list subscribe the case for lightweight development processes. [2000-11-15] (50:00)

Audio/Video
now playing on
technetcast
Entire Program (50:00)
•Rethinking the Modern
OS ● VIDEO PLAY RealPlayer VIDEO 56 [FIREWALL]
•Tim O'Reilly: The
Shape of Thinks to Warning: filesize(): Stat failed for av/events/tnc-0425-56.rm (errno=2 - No such file or directory) in /home/
Come technetcast/live/htdocs/tnc_play_stream.htmlon line 237
•Don Box: Virtualization ● AUDIO PLAY MP3
in Web Services ● AUDIO SAVE MP3
•Effective lobbying for Problems with MP3? READ MP3 HELP.
Open Source ● VIDEO PLAY RealPlayer VIDEO 150 [FIREWALL]
•Inside the XBox
Launch Warning: filesize(): Stat failed for av/events/tnc-0425-150.rm (errno=2 - No such file or directory) in /home/
•History of Linux technetcast/live/htdocs/tnc_play_stream.htmlon line 237

TechNetCast Archives
● SOFTWARE DEVELOPMENT METHODOLOGIES MARTIN FOWLER EXTREME PROGRAMMING
SOFTWARE DEVELOPMENT 2000 EAST

Links
http://technetcast.ddj.com/tnc_play_stream.html?stream_id=425 (1 of 2)05/12/2003 15:37:29
TechNetCast Play

channels ● Show Daily News: Keeping Software Soft


ai ● Martin Fowler, Home
business ● Martin Fowler: The New Methodology
c++
computer history
cyberlaw, cyberrights
Troubleshooting
dot-net
graphics, game dev ● Are you having difficulties viewing this program? Please let us know! (Provide operating system and player
java version info.)
languages
● MP3 Play/Download Tips
linux
mac os
networking ● Player Does Not Launch after Selecting Link Launch the player -RealMedia or MP3 player- manually and
enter the stream URLs directly (File | Open Location):
open source
os design
perl http://technetcast.ddj.com/tnc_play.ram?stream_id=425&stream_type=3 (VIDEO 56)
peer-to-peer
programming http://technetcast.ddj.com/tnc_play.ram?stream_id=425&stream_type=9 (VIDEO 150)
robotics
security
software development
web services
www
xml

Back to
TechNetCast Home

(c) 1999-2003, Dr. Dobb's TechNetCast

http://technetcast.ddj.com/tnc_play_stream.html?stream_id=425 (2 of 2)05/12/2003 15:37:29


M ETHODS IN PRACTICE

Martin Fowler
martin_fowler@compuserve.com

Use and
Abuse Cases

U
 , despite the clunky name, have become sign of the systems looks like the use cases. A common
one of the most popular techniques in object- symptom is to find behaviorally rich controller objects ma-
oriented methods. Ivar Jacobson brought them nipulating dumb data objects, which are little more than an
to prominence by taking a widely used, yet informal tech- encapsulated data structure.
nique and giving it a central place in system development. This kind of design loses most of the benefits of objects.
Since then nearly every writer on object-oriented design The system duplicates behavior across the different con-
has talked about use cases and brought them into their ap- trollers, and knowledge of the data structure is also spread
proach. Naturally, they play an important role in the Uni- around these controllers. The essence of the problem is that
fied Modeling Language (UML). functional decomposition encourages you to think of a be-
Use cases are valuable for several reasons. First, they help havior in the context of a higher-level behavior. Done that
in discovering requirements. Use cases allow you to capture way, it is difficult to use that same behavior in another con-
a user’s need by focusing on a task that the user needs to do. text, even if it is mostly the same. With objects you want to
Use cases help can help formulate system tests to ascertain think of behaviors that are usable in many contexts. Func-
that the use case is indeed built into the system. They also tional decomposition does not encourage that approach.
help control iterative development: in each development it- You can avoid this problem, of course, by remembering
eration, you build a subset of the required use cases. that the internal structure of the system does not need to
Despite this wide usage, there are many problems about look like the external structure (the use cases). However,
use cases that are not well understood. The basic defini- this is a difficult concept for developers without object-
tion—a sequence of actions that a system can perform, in- oriented experience—who are also the most likely to build
teracting with the users—is simple enough. But as soon as a functional decomposition.
you start trying to capture the use cases for a system, you Even if you don’t find that the functional decomposition
run into unanswered questions. I’ve also seen several pro- affects your internal design, a heavily structured set of use
jects get tangled up in use cases, getting into trouble in the cases runs into trouble because people end up spending a
process. So here are a few cases of abuses I’ve seen, and lot of time on them. Driving every use case down to ele-
how I think you should avoid them. mental steps, arguments about which use cases fit into
which higher-level use case, all take time that could be bet-
Abuse by Decomposition ter spent on other things. Capturing every detail of the use
I’ve seen several projects get into difficulties by putting too cases isn’t needed in the early phases of development. You
much effort into structuring the use cases. Following Jacob- do want to look early at the areas of high risk, but a lot of
son’s work, the UML uses a pair of relationships between the details can be left to the later stages of an iterative de-
use cases: uses and extends. These can be useful, but I’ve velopment. That’s the whole point of iterative development.
more often seen them cause trouble—especially the uses re- So I discourage those new to objects from using the uses
lationship. In such cases, the analysts take a fairly coarse- relationship. I also treat similarities between design and use
grained use case and break it down into sub-use cases. Each cases as warning signs. The “extends” relationship seems to
sub-use case can be further broken down, usually until you cause less trouble, but I still don’t make a big thing of it. I’ve
reach some kind of elemental use case, which seems atomic seen projects that used use cases effectively without either
to some degree. of these relationships, so they are by no means essential.
This is functional decomposition, a style of design that is
the antithesis of object-oriented development. It leads to Abuse by Abstraction
problems in a couple of ways: The first is when this use case Objects are all about abstraction. A good design is one that
structure is reflected directly into the code, so that the de- finds powerful yet simple abstractions, making a complex
problem tractable. So as designers we are used to abstrac-
Martin Fowler is an independent consultant based in Boston, tion, encourage abstraction, glory in abstraction.
Massachusetts. But abstraction can lead to trouble with use cases. I re-

www.DistributedComputing.com DISTRIBUTED
Computing 1
M ETHODS IN PRACTICE

member talking to a user at one project who confessed that Would you include change a style, apply a style, and import
although he understood the use cases at the beginning, he styles from another document? The problem with these use
now felt lost with the more abstract use cases. “I think I un- cases is that they don’t directly address a user’s needs. The
derstand them when the developers explain them to me, user’s real needs are something like ensure consistent for-
but I can’t remember the explanations later.” One of the matting within a document, or make one document look
primary purposes of use cases is to communicate with the like another. I’ve characterized the former as systems use
users—the customers—of the system. Abstracting the use cases and the latter as user use cases.
cases beyond the level of comprehension isn’t going to help The problem with going directly to the system use case is
anyone. A lack of abstraction in the use cases does no harm, that it denies you the chance to come up with other system
since the internal structure need not be the same as the ex- use cases that would deal with this problem. You can’t use
ternal structure. I’ve not found that a lack of abstraction in only user use cases, however, because they don’t fit well into
the use cases leads to lack of abstraction in the internals. the iterative scheduling process.
On the contrary, using less abstract use cases helps because I’ll confess that I haven’t come up with a solid answer to
mapping an abstract internal structure to a concrete use this problem. I primarily put my attention to system use
case helps us understand the abstraction. cases, for they are the most useful for iteration planning
Abstracting use cases can also lead to larger use cases, and system testing. However with every system use case I
which, in an iterative development, are more difficult to think about whether there is another user use case which is
plan with. You can also spend a lot of time arguing about sitting behind it. I keep a note of these and try to come up
the abstraction—time better used elsewhere. with alternative system use cases.
So my advice is to err on the side of being too concrete. Use cases are one of the most valuable techniques avail-
Above all, don’t go more abstract that the user can follow. able to us. I use them all the time in my development work,
Use the concrete use cases to explain and verify your pow- and wished I had started using them earlier. But remember
erful abstractions. what you are using them for, and beware of these pitfalls.
And somebody please write a good book on what makes a
Abuse by GUI good use case—there’s at least one active developer who re-
With all the GUI painting tools out these days, more people ally wants to read it. k
are using them to help determine the use cases. The logic is
appealing. A GUI is concrete to a user; it helps snag the easy-
to-forget details; it gives the user a sense of what the system
will look like; GUIs are easy to prototype; they make reason-
able demos to explain the capabilities of the future system.
I used to think that GUI prototypes were a good require-
ments tool for all these reasons. But there is a fundamental
problem. When you show a GUI prototype to a user, it looks
like nearly everything is done, that all that’s left is a bit of
wiring behind the scenes. Of course, we know that what
lurks behind the scenes is the most complicated part of the
exercise, but this is exceedingly difficult for customers to
understand. GUIs lead to a false indication of progress and
difficulty—it may be just a button on the UI, but providing
it could take weeks of effort. There’s a huge gap between the
real effort and the perceived effort, making it difficult to do
the negotiation that is so important in scope control.
And despite the fact that GUI tools seem so easy to use,
there’s always a lot of fine tuning to make it look just right.
This fine tuning sets people’s expectations in a particular
direction, making people reluctant to make changes when
a simpler design idea comes along.
So now I tell people to never show any GUI that hasn’t
got fully working code behind it. It’s still good to mock up
GUIs, but do it with pen and paper. That way you avoid the
false indication of progress.

Abuse by Denying Choice


Take a high-end word processor. Think about the use-cases.

2 DISTRIBUTED
Computing April 1998
METHODS IN PRACTICE

Martin Fowler } fowler@acm.org


Independent consultant in Boston, Massachusetts

Is There Such a Thing as


Object-Oriented Analysis?
, I     on object- Can we, should we, be passive describers when we analyze?

R oriented analysis. At one point, a participant ex-


claimed: “Is this analysis or design—and what’s the
difference anyway?” It’s a thorny question, one that bugs me
from time to time, and always a good candidate for a flame
And if we are not, are we really doing design rather than
analysis?
The key to understanding this question is to remember
that all we are doing in analysis is coming up with a descrip-
war on comp.object. tion of our understanding of the domain. This description
People imagine that it’s easy to ask someone to build a could be prose, or could use UML. Whether we grace this
computer system. You find a programmer, tell them what you description with the term model or not, it is still a descrip-
want, and they go away, get some pizzas, and build it. Yet as tion that we construct, not some universal reality we pluck
we all know, it is devilishly difficult to actually do this for any- out of the problem domain; we are building an artificial de-
thing but the smallest system. For a start, there is a lot to tell. scription of it. As Jim Odell famously said, we do not model
Just writing it all down is a lengthy exercise in itself—hence the world, we model our perception of the world. To do
the term Victorian Novel Specification. The other awkward this we need some language to state our description. To ar-
problem is that people will tell you what they want, but you gue that one language is more natural than another is to ar-
actually have to build them what they need—not necessarily gue that a wooden bridge is more natural than a steel
the same thing. bridge. Either way, it’s a bridge, and it’s constructed, not
In theory, analysis provides a statement that describes the natural.
problem domain, without saying anything about a solution. So, to argue that one modeling language is more natural
Such a statement should not construct anything artificial than another is unimportant. Naturalness is usually in the eye
about the problem domain and it should be technology inde- of the beholder. The real question is whether one language is
pendent. The software people can then just design a solution more useful than another.
to this statement. Pity things don’t work that way. To answer this new question of usefulness, we must under-
In this theory, the term object-oriented analysis is an oxy- stand what we are building the description for. For most prac-
moron. Objects are a design idea—such things as encapsula- titioners the purpose is to build software. A good description
tion, polymorphism, and the like make sense in developing is one that helps us build good software—that is, software that
maintainable software; but if you think of me as a lump of en- helps the users in their task for a reasonable cost. The descrip-
capsulated data with an interface of operations, you need tion that comes from analysis is only as good as its usefulness
more than an optician. Having said this, when you see object in this task.
people do analysis, the models they come up with are clearly Is it more useful to be technology independent? Is it better
different in nature than what a relational data modeler would that my analysis statement should be equally amenable to ob-
come up with. To see this, compare the patterns books of jects, relational databases, functional programming, or any
David Hay and myself (Fowler, M., Analysis Patterns: Reusable other design paradigm? Let’s assume for a moment that such
Object Models, Addison Wesley, 1997; Hay, D., Data Model Pat- a thing is possible. Eventually we have to implement a solu-
terns: Conventions of Thought, Dorset House, 1996); we both tion. At that point, we have to transform it to the technology
claim we are doing analysis modeling, but our style of model- we eventually build with. Such a transformation carries a cost,
ing is very different and clearly influenced by the technology. and if we want to keep the analysis picture up to date we will
Is analysis about just recording how the world is, or is it pay an ongoing cost. Is this cost outweighed by the advantages
about designing something new? Few modelers will actually of a technologically independent model?
model what happens in the business. There are frequent con- My opinion is that it is perfectly reasonable for your
tradictions and inconsistencies between users and depart- analysis model to lean toward the implementation technol-
ments, and words are used in different ways. We try to ab- ogy you intend it to use if, as a result, the model is more
stract, and thus simplify our analysis models, yet such abstrac- helpful in understanding the problem you are working on.
tions are constructed—you can’t really say they are in the world. For me, the essence of the difference between analysis and
continued on page 41

40 DISTRIBUTED
Computing October 1999
METHODS IN PRACTICE

design is that analysis is primarily about understanding the do-


main, while design is about understanding the software that
supports that domain. Clearly the two are closely connected,
and the boundary between them can often become pretty
blurred. But the boundary need not be sharp. We shouldn’t
let purity come before usefulness. In theory, having a model
that is both analysis and design is some hybrid that isn’t good
at either, yet I believe that this kind of hybrid makes the best
model.
Why? My view is that the key to the usefulness of an
analysis model is that it’s a communication medium be-
tween the software experts and the business experts. The
software experts need to understand what the model means
in terms of building software, and the business experts need
to understand that the business process is properly de-
scribed so the software experts are understanding the right
thing.
So, what is an analysis model, and what makes it differ-
ent from a design model? For me the issue is one of empha-
sis. Remember, analysis is about understanding how the do-
main works. I build this understanding by building models,
either in my mind, in UML, or in a programming language.
I can be working out the details of some charging algorithm
by programming it, or in a discussion with users about what
they mean by the word asset. I wouldn’t say that figuring
out database interactions or a distributed computing archi-
tecture was analysis. But my analysis models are still driven
by the same heuristics as any other object-oriented soft-
ware. Analysis is essentially the design of the business ob-
jects and business logic. This isn’t everybody’s definition of
analysis, but I find it useful.
So object-oriented analysis is a reasonable notion. It is
building a description of the domain that increases our under-
standing of that domain, in order to help us build an object-
oriented software system. Judging what is a good analysis is
judging its usefulness for that purpose. This is not a definition
that lends itself to a clean separation between analysis and de-
sign, but then such a separation isn’t really useful anyway. As
in engineering, we are faced with blurred boundaries and
trade-offs. That’s just the way life is. O

www.DistributedComputing.com DISTRIBUTED
Computing 41
METHODS IN PRACTICE

Martin Fowler
fowler@acm.org

Testing Methods:
The Ugly Duckling

E
  to the Design Techniques Annual Ball? testing code and the production code proceeding
The hot crowd is the UML group: Class Diagrams, in tandem.
Sequence Diagrams, Activity Diagrams, all wearing It’s not unusual to write the test code before the pro-
sharp and expensive casual business outfits. ER Diagrams duction code. I often find this useful, because it helps
go in suits, look a little on the gray side, but are still very me to focus on exactly what this incremental step
popular. (They claim they are just as good as the object involves. Essentially, I write the test, and then get the
techniques, the object techniques are just better dressed.) code to pass the test.
CRC cards turn up in sandals, patterns are always Another advantage of writing the test first is that the
trying to turn you into one of them, and formal methods tests help you concentrate on the interface for the new fea-
snub everyone else for the slightest crease or stain. In a ture rather than the implementation. You are asking your-
corner, ignored by all, wearing stained and color-clash- self “How will a client use this new feature?” Getting the
ing overalls, are the testing methods. Nobody wants to test to work then gives me closure on the feature. With the
talk to them. test working, I know I did what I set out to do.
All the design methods get to ride in fancy CASE tools; But there is a further step, essential to the self-testing
testing methods are lucky if anyone walks them home. But technique. Once your new feature test works, you add it to
I’ve noticed that the parties that end in tears are usually the your unit testing code base. There are various ways of
ones that the testing methods weren’t invited to! doing this. These days I keep a separate set of tester classes
Alright, I’m being whimsical, it’s late, my hotel room in my software. As each feature gets added to the produc-
feels boring, and I’ve got a column to write. But this col- tion code, a new test gets added to the test code.
umn is quite serious. You can use design methods until I’ve been working with this on a major financial
you are blue in the face, but how you do your testing will system development project. It has over 2000 unit tests,
probably have a bigger effect. Certainly for many of my and the unit test code is a quarter the bulk of the pro-
clients, getting them to use effective testing techniques duction code. Having such a battery of unit tests is valu-
is more bang for the buck than teaching them UML. able, but only if you use it, and to use it you must be
able to run it easily.
Self-Testing Code An essential factor here is that the tests must give a
A key technique I use is self-testing code. The principles simple indication of whether they pass or fail. A test that
behind this are that testing is not something to start after produces a number that you then have to check manually
you have finished coding, and that test code is as impor- against some piece of paper is a stupid test. You should be
tant a deliverable as production code—and should be able to run all 2000 tests and either see “Ok,” or “Here is a
given the same emphasis. (I should say that this self-test- list of failures.”
ing code is unit test code, written by the developers them- At the project I just mentioned, they use Kent Beck’s
selves. You should have separately written system test Smalltalk testing framework. It has a test panel that goes
code as well.) green if all is well, or red if there are any failures. That way
I’m a great fan of incremental development. Every you can happily just hit the button to run the tests and
time I try to add new features to software, I stop and ask know immediately if everything is fine (Kent and Erich
myself: “What is the smallest piece of new function I Gamma have ported the framework to Java—you can get
can add?” I then focus on adding that feature alone, and the URL from my homepage, http://ourworld.compuserve.
I do not move to a new feature until the feature is com- com/homepages/martin_fowler).
plete—including the self-testing code for that feature. These self-tests are now a golden asset for future
Development then proceeds by small steps, with the development. Since they are easy to run and interpret,
you can run them regularly, even if they take a while.
Martin Fowler is an independent consultant based in Boston, Every time you go off for a meeting or to lunch, run all
Massachusetts.

54 DISTRIBUTED
Computing June 1998
METHODS IN PRACTICE

the tests. Or set up a regular job that runs every test at their productivity, they will be the best endorsers of the
midnight and mails you the result. technique. You may find you need a mentor who prac-
If in the future you do something that breaks some tices the technique to pass on to the development staff.
other part of the system, the tests will quickly tell you. Certainly if I were looking for a mentor, I would be very
You’ll know it must be something you just did that reluctant to hire one who didn’t understand and emphasize
caused the failure, and that knowledge alone is usually testing. Make sure enough testing code gets written. To do
enough to cut out hours of bug chasing. In particular, this you might use a code coverage tool to see how much of
you should try to run the full suite of tests whenever the production code is being exercised.
you integrate. Failing that, keep an eye on the ratio of test code to
It amazes me when a programmer checks in code after production code. Make sure that the tests are being run
days of work and just assumes that it will work with whatev- regularly. If it is practical to enforce running all unit tests
er anyone else has checked in. If you can, run all tests every before checking in code, do that. If not, make sure
time anyone integrates any code. Furthermore, get people to there’s an automatic run of all unit tests daily when you
integrate frequently. With incremental development you can do your daily build. (You do do a daily build, don’t you?)
easily integrate daily. It’s another day now, I’m on an airplane bound for a
Such an approach—what Ron Jeffries calls continuous conference, and I’m not so tired any more. The introduc-
integration and relentless testing—makes bugs show up early, tion to this column looks a little cheesy. So I’ll refrain from
when they are easier to find and fix. This does wonders in making analogies about smartening up testing techniques
reducing integration time. with a flashy new outfit. I’ll just tell you now, if you don’t
When I am developing, I usually will run tests every have self-testing code, start now. It may be the most impor-
time I compile. It’s clearly not practical to run half-an-hour’s tant thing you do this year! ❊
worth of tests on every compile, so when I’m doing some
development I’ll choose a subset, which will run in a few
seconds, that focuses on the code I’m currently working on.
Maybe I’ll do a ten-minute test suite during a coffee break.
These unit tests are a great enabler. I’m a great fan of
refactoring: making improvements to the internal structure
of the code without changing the external behavior.
Regular refactoring is essential to keep the design integrity
of a software system. Refactoring without solid unit tests
leads to long and discouraging bug chases.
Similarly the tests are essential for performance opti-
mization. Again, without the tests it is hard to tell that a
performance enhancement does not introduce a bug.
When I teach self-testing code to developers, a usual
first reaction is that “Well this sounds reasonable, but I’ve
got deadlines to make.” The crucial realization is that self-
testing code actually speeds up writing code. It does this
because it makes debugging much shorter.
Early on in my programming life I discovered that I
spent much more time and effort removing bugs than I did
writing code. If you run tests regularly, bugs tend to show
up earlier. If it’s not long since your last write of a test, you
know which bit of code contains the bug.
After writing self-testing code for a while, developers
realize that they are spending less time debugging and thus
developing faster. The tests enable them to refactor more
easily, thus keeping the system design simpler and allowing
them to develop faster.

Introducing Self-Testing Code


How do you introduce self-testing code into your orga-
nization? Find some people who are willing to give it a
try and have them, well, give it a try. If they can reach
the point where they see how self-testing code improves

www.DistributedComputing.com DISTRIBUTED
Computing 55
METHODS IN PRACTICE

Martin Fowler } fowler@acm.org


Independent consultant in Boston, Massachusetts

What’s a
Model For?
    who think the adoption of can gain in structural relationships (such as data structures),

T the UML is one of the most important developments


in the last couple of years. While I agree that sorting
out silly conflicts over notation is a big step forward, we still
have a more fundamental set of questions: What exactly is the
but with control flow you often lose clarity.
Another important function of models is highlighting. It’s
hard to understand a complex system by diving into the details
in all their gore. You can use a model to highlight just the im-
UML for? Why do we use it, and if we don’t why should we? If portant parts of the system, and you can highlight before you
you are using, or thinking of using, the UML, you ought to create software or after you’ve built all the code. The point is
know the answers to these questions. that you can understand the key structures that make the soft-
It’s important to recognize that creating a UML diagram ware work first, and then you’re in a better position to investi-
involves a cost, and a UML model is not something that fun- gate all the details.
damentally matters to a customer. Customers want software Notice that I say, “highlight the important details,” not “ig-
that works, not pictures, however pretty or standard. Thus, nore the details.” A high-level view that ignores all details is
the value of modeling is entirely bound up with its effect on usually worthless because it doesn’t tell you anything. Rather
the software you are producing. If the model improves the than a high-level view, I prefer to think of this style as a skele-
quality or reduces the cost, then the model has value. But the tal model. It shows you the bones of the system, which can be
model has no value on its own. It reminds me of a character quite detailed.
in a (forgotten) novel: “He was like the 0 in 90, with his wife To my mind, a skeletal model is better than a fully-fleshed
he was something, without her he was nothing.” model, where there’s so much more information to wade
The value that a model provides is fundamentally about through. When I’m trying to understand a model, I have to
giving the user a greater understanding of something than the figure out where to start. Typically people do this by trying to
software itself. This may be greater understanding of the soft- find the important stuff, but since they don’t know what’s im-
ware or of the domain that the software supports. It can do portant, it’s much easier to get the person who knows the
this either by a two-dimensional graphical presentation, or by model to do the selection. Similarly, if I’m creating a model
highlighting important information. before building the system, the key decisions are in those im-
A complicating factor is that all humans don’t think alike. portant details. Not all issues are equally important, and I have
Some people understand things better in a textual form; oth- limited brain power. I need to expend that power on the im-
ers prefer pictures. People differ where they are on this scale, portant details, so I use a skeletal model.
and some prefer pictures for some subjects and text for others. I’ve also found a skeletal model is easier to maintain than a
So beware of over-restrictive standards. Remember that indi- fully-fleshed one. Important details change less often. And the
vidual needs differ, and that you need to find what the most skeletal model is more useful, so people are more inclined to
effective blend is for the people you are working with. keep it up to date. If people want details, they can explore the
I’ll start by looking at the simple transformation from text code once the skeleton has provided the overview. The nice
to graphics, leaving all the details in. In this approach you take thing about the code is that it’s always in sync with itself.
everything you can say in text and put it in the model. This The crux is that a model is either fully-fleshed or skeletal, it
takes a lot of work; doing this level of detail with model and can’t be both. You either include all details, or you decide to
source code takes too much time to be worthwhile, unless leave something out. As soon as you leave something out, you
you have tools that automate the task. This is where many are going down the skeleton path, even though your skeleton
CASE tools come in: either round trip where tools convert may look less anorexic than mine. Your decision will be based
from model to code and back again (e.g., Rational Rose); or on what you find most valuable in visualizing the system. Peo-
tripless, where the code is the storage mechanism for the ple vary, so your choice will be different than other people’s,
model (e.g., Together-J). but you do need to make an explicit choice.
The cost of producing the model is lowered, although This is a key problem with many CASE tools. The fashion
there is still a cost. However, when you have a model that de- these days is for the CASE tools to keep an automated link to
tailed, you have to ask how much you’re gaining. I think you the code. A tool, however, cannot tell important details from
continued on page 35

www.DistributedComputing.com DISTRIBUTED
Computing 33
ODBMS

Figure 1. Object Structure for a Clothing Catalog Company


is another performance enhancement for providing complex
data to web servers.
Several ODBMS vendors offer solutions similar to this. If
you are interested, I suggest you check out the Web sites for
Ardent Software <www.ardentsoftware.com>, Object De-
sign <www.objectdesign.com>, and POET Software
<www. poet.com>. These companies had XML data server
offerings at the time I was writing this column. By the time it
appears, there may be more companies with offerings. Come
to my Web site to find if there are more.
We live in a world of many technical options. The key to
finding good solutions often involves matching business needs
for performance to the options available. In this column, an
example of a good solution for a middle-tier database in an
XML data server was outlined. In this case, an ODBMS is able
to provide the high performance on complex data required. As
we move through the world of increasing database diversity,
an ODBMS is a serious option for an XML data server. Q

Editor’s Note: Doug Barry has just published XML Data Servers: An
Infrastructure for Effectively Using XML in Electronic Commerce, which
looks at architectural options for XML data servers and provides
analysis/features of each architecture (www.xml-data-servers.com).

METHODS IN PRACTICE

continued from page 33


side issues, so the result is always a fully-fleshed model. This
There are many database options for an XML data server. is made worse by the fact that tools typically base their
For this clothing company example, I am going to discuss us- analysis on the data structure of the classes rather than the
ing an ODBMS, which can be a good choice because XML interfaces. The whole point of working with objects is that
data looks like a graph. (See Figure 1 for a fragment of the ob- you see the interfaces, not the internal data structure, so the
ject structure for a clothing catalog company.) Searching for typical reverse-engineered diagram shows you the very
clothing information involves traversing this graph structure things that are supposed to be hidden. CASE tool vendors
from product to item to size and to color swatch. Keep in need to put more time into thinking about how to show the
mind that this object structure fragment has been simplified— user important things and how to hide things that should
it has objects such as color swatch that will be shared by other stay under wraps. Of course, since everyone’s definition of
items in the catalog not shown in this figure. important is different, this means there’s a lot of tricky cus-
If you have been reading my columns or visiting my Web tomization to do.
site, you have probably read (many times) that ODBMSs are So, the unavoidable dilemma: In order to see the wood
great when you have a business need for high performance on from the trees in design, you need a skeletal model. However,
complex data. One sign of complex data is a graph structure as soon as you do this, you lose the ability to have an auto-
coupled with access by traversal, such as this example. When mated connection to the details.
you are selling products on the Internet and your Web site I don’t think we’ll see a solution from CASE vendors any
must respond quickly to people browsing or agent programs, time soon. If you want a model that really does communicate
your site must respond quickly, or the people/agents will just effectively, you need to make it a skeletal model, and that
move on. This is a compelling business need. means you have to build it yourself. In the end the human
Figure 2 shows a possible architecture that uses an ODBMS brain counts.
as an XML data server. It shows the mappings from the XML As a last note, I’d like to thank Derek Coleman for helping
data sources discussed earlier as well as the tools for editing me crystallize my thinking on this column with the assistance
XML data. It also shows a connection to a merchant system. of some good wine and a paper napkin—two of the world’s
Note the caching in the middle tier that ODBMSs offer. This most effective (and enjoyable) design tools. %

www.DistributedComputing.com DISTRIBUTED
Computing 35
METHODS IN PRACTICE

Martin Fowler
fowler@acm.org

Refactoring: Doing Design


After the Program Runs
      for any length of local variables, you may have to pass in parameters, return a

I time, you should have heard about the notion of it-


erative development. The idea of iteration is that you
cannot get a design right the first time, you need to refine it as
you build the software. By iterating over the design several
value, or even not be able to do the extraction. The tool does
this analysis, prompts for the new method name, asks you to
name any parameters, and creates the new method with a call
from the old one. The program works exactly the same as it did
times, you get a better design. Even throwing away code before but is now a little easier for a human to read. This is im-
helps; indeed it is the sign of a good project that it does regu- portant: Any damn fool can write code that a computer can un-
larly throw away code. To not do so indicates a lack of learn- derstand, the trick is to write code that humans can understand.
ing—and keeping bad ideas around. The tool builder has to prove that the refactoring is seman-
Iteration is a great principle to discuss, but it has some tics preserving, then figure out how to provably carry out the
problems in practice. If you make a change to existing code, transformation in the code. It’s hairy stuff and requires a lot of
does that not carry the risk of introducing bugs? While people knowledge of compiler technology, but it can be done. The
have come up with various techniques and methods for design benefit is immediate. Once the transformation is encoded, you
in advance, there is not much discussion of how to apply them can use it with complete confidence. A semantics-preserving
in an iterative process, or how to do the iteration in a con- transformation is never going to add a bug to your program.
trolled and efficient manner. Tools like this are not science fiction. Bill Opdyke, while
Refactoring is the first technique I’ve come across that is a student at the University of Illinois, proved several of these
explicitly about doing iterative development in a controlled refactorings. Since then, two other graduate students, John
manner. It starts with software that currently works but is not Brant and Don Roberts, have produced a refactoring browser
well suited to an enhancement you wish to make. Refactoring for Smalltalk that implements these refactorings, and a few
is the controlled process of altering the existing software so more. If you are a Smalltalker, you should download it from
it’s design is the way you want it now, rather than the way you www.cs.uiuc.edu/users/droberts/Refactory.html.
wanted it then. It does this by applying a series of particular The refactoring browser is an awesome tool. With it I
code transformations, each of which are called refactorings. can safely reorganize some pretty ugly code (and yes even
Each refactoring helps change the code in a way that both is Smalltalk can get ugly). But what if you are working outside
rapid and does not introduce bugs. (Yes, I know that means of Smalltalk? Is refactoring still applicable? The answer is yes,
the word refactoring means two different things—I guess over- although not with tool support.
loading is just ingrained in this industry!)
How does refactoring do this magic? Essentially, there are two Refactoring Without Tools Although manual refactoring is
routes. The first is manual; the second relies on tools. Although not as easy, it is still possible—and useful. It boils down to two
using tools is less common at the moment, I’ll start with that. principles: take small steps and test frequently.
Humans can use the same semantics-preserving transforma-
Refactoring With Tools The essence of the tools-based ap- tion tools use, but in method extraction you have to look at the
proach is the notion of the semantics-preserving transformation. local variables yourself. It takes a little longer, but it isn’t too dif-
This is a transformation that you can prove will not change the ficult, because you’re looking at only a small section of code.
execution of the program. An example of this is a refactoring You then move the code over, put in the call, and recompile.
called extract method. If you have a long section of procedural If you did it correctly, you won’t get any bugs. Of course,
code, you can make it easier to read by taking a suitable chunk that’s a big if, so this is where tests come in. With manual
of the procedure and turning it into a separate method. To do refactoring you need to have a battery of tests that exercise
this with a tool, you select the code you wish to extract, and the the code sufficiently to give you confidence that you won’t in-
tool analyzes this code, looking for temporary variables and pa- troduce new bugs. If you build self-testing code, then you will
rameters. Depending on what the selected code does with these already have those tests. If not, you have to build them your-
self, but of course tests are useful anyway, since they make it
Martin Fowler is an independent consultant based in Boston, MA. easier to add new function as well as refactor.

www.DistributedComputing.com DISTRIBUTED
Computing 55
56
MindQ Ad

Refactoring to Understand Code When you follow a Its great strength is that it works on existing software. I’m
rhythm of small change, test, small change, test, you can make rarely faced with a green field. Often I have to work with
some remarkably large changes to a design. I’ve gone into some some form of existing code base. Refactoring provides a way
pretty nasty lumps of code, and after a few hours found class to manipulate and improve the code base without getting
structures that radically improve the software design. I don’t trapped in bugs.
usually have the design in mind when I start. I just go into the When working with new code, it gives developers the abil-
code and refactor initially just to understand how the code ity to change designs and make the iterative development pro-
works. Gradually, as I simplify the code, I begin to see what a cess much more controlled. I’ve noticed that it makes a signifi-
better design might be and alter the code in that direction. cant improvement to development speed. When trying to add
Refactoring to understand code is an important part of the new function to software, several projects have seen how it is
activity. This is obviously true if you are working with some- quicker to first refactor the existing software to make the
one else’s code, but it is often true with your own code as well. change easier. Thus I don’t recommend setting aside time to
I’ve often gone back to my own programming and not fully refactoring. It should be something you do because you need
understood what I was doing from the code, or gained a better to add a feature or fix a bug. That also makes it easier to justify
understanding by comparing it to later work. Of course, you to skeptical managers.
can do a similar thing by commenting, but I’ve found it better The biggest problem with refactoring at the moment is
to try to refactor the code so its intention is clear from the finding out more about how to do it. I’m in the process of
code, and it does not need so many comments. Some refactor- writing about what I, and various others, have learned about
ers go so far to claim that most comments are thus rendered the process, but that is still a way from publication. You can
unnecessary. I don’t go that far, but I do prefer to reach clarity find some more information, including references and an in-
through good factoring if I can. troductory example of refactoring, at ourworld.
compuserve.com/homepages/Martin_Fowler/.
The Value of Refactoring Refactoring has become a central I hope I’ve stimulated you to find out more about refactor-
part of my development process, and of the process I teach ing. I believe it is going to be one of crucial new developments
through my seminars and consulting work. It’s a design tech- of the next few years, and tools that include refactorings will
nique that is a great complement to the up-front design tech- be very important to software developers. I’d be interested to
niques advocated by the UML and various methods. know what you think; drop me a note at fowler@acm.org. s

56 DISTRIBUTED
Computing September 1998
DC Columns: Standard UML

How standard is Standard UML?

(From Martin Fowler's column originally published in Distributed Computing, Spring 1999)

A few years ago, one of the most tiresome aspects of my consulting life was the methodology wars:
furious arguments about which notation to use. Always these rows caused a lot of heat, and almost all
the time they were pointless - it didn't matter which we picked. Thanks to the UML, most of that is gone
and forgotten. We now have a standard notation. But as people are discovering, the standard doesn't
settle all the questions.

The questions that rise up now tend to be more detailed issues: how to represent some particular thing in
a UML model, or what a certain UML construct means for our implementation environment. The thing
that surprises many people is that for many of these issues, there is no cut and dried answer.

Why is this? A large part of the reason is tradition. Modeling methods, whether OO or not, were never
very formal affaires. Definitions were left to intuition, and there were many gaps. People with a formal
methods background criticized these methods for this. They argued that the lack of rigor meant that too
much ambiguity crept into the models. But the reality is that many people found that despite this lack of
formality, the informal methods were generally more useful than the formal methods. In practice it
seems that informality is an advantage.

There are formal elements to the UML. The center of these is the meta-model: a UML model that
describes the structure of the UML. But even a meta-model leaves many gaps. It may define an attribute
as a kind of structural feature whose type is a classifier, but what does that really mean when I program?
In Java does it mean a field, a pair of get and set operations, or a parameter to an operation? If you ask
ten UML experts what the answer to that question is, the only agreement you're likely to get is that the
answer includes the words "it depends". The meta-model's primary purpose is to define a well-formed
model so that CASE tools can someday communicate. It's a long way from a truly rigorous approach.

Dealing with multiple interpretations

So what does this mean for you? For a start it means that you'll see a number of interpretations of the

http://www.martinfowler.com/distributedComputing/standard.html (1 of 3)05/12/2003 15:37:43


DC Columns: Standard UML

UML. These interpretations will appear in books, training courses, and project documentation. You need
to be aware of this. There is much less variation than the variations between methods in the past, but
variation will be there. Within a team you'll have to come up with a more standard consensus
interpretation for these issues as they come up. As you do this, beware of anyone who states with great
certainty about how one interpretation is right or wrong. Some things are fairly cut and dried, but many
are not.

How do you choose an interpretation? The overriding principle is to understand what you are using the
UML for. If you are using a CASE tool to generate code, then the interpretation to use will inevitably be
that of the CASE tool's code generator. If not then the overriding purpose will be that of communication.
So you want to choose an interpretation that will communicate best with other people. This is an
important point about the standard, it encourages a common interpretations of our diagrams.

Here I think the issues of interpretation will parallel that of a natural language (like English) rather than
a defined language (like ANSI C). There won't be one single body that will pronounce on UML
interpretations. If such a body does exist, it is the OMG: through its analysis and design task force. It
holds the key to the UML standard. But they will never pronounce on all the issues. And even where
they do pronounce, common practice may well differ from the official line. It's similar to that of the role
of the French language academy that outlawed such phrases as "faire du shopping", but couldn't stop
them passing into common parlance.

So just as with English, an important part of steering common usage will come from the UML mavens,
those people who set themselves up to comment on correct and tasteful UML. In this picture the three
amigos will be particularly important mavens. Their writings will carry a lot of weight, but won't
necessarily be absolute.

As well as variations in interpretation, we will also find downright different notations. Many people will
perceive an important gap in the UML and propose some new extensions to fix the problem. Some of
these will fit in smoothly through the UML extension features (stereotypes and the like), others will be
outright deviations from the OMG documents. Again these will rise and fall depending on whether other
people pick them up.

Choosing Interpretations
So when you are using the UML to communicate, and you are choosing an interpretation or considering
an extension - how should you choose? Look at the influential sources and see if they say anything. If
they do, that should influence your decision, but it shouldn't settle the decision. In the end you have to
choose what is most useful for you. It may be that one interpretation makes much more sense for your
project - it leads to less clutter, is more visually apparent. You will have to make clear to your readers
that you are taking a less traveled course, but sometimes it can be worthwhile. So try to stick to the
common usage, but don't let these pronouncements rule you. The UML is there to help you, not the other
way round.

http://www.martinfowler.com/distributedComputing/standard.html (2 of 3)05/12/2003 15:37:43


DC Columns: Standard UML

This view of the UML as a natural language also suggests how it may evolve. Natural languages evolve
by people pushing the language in various directions. Those that are useful pass into common usage, and
then gradually become more standard, those that don't fade into memory. I think we'll see a fair bit of
pushing at the UML's edges over the next few years. This will be a good thing, for it will keep the UML
vibrant and allow it to develop. This edge-pushing happened with pre-UML methods, and many ideas
found their way into the UML. The fact that the variations have a common base will make this process
easier, and perhaps even accelerate the UML. So don't expect it to be static, and do expect the official
standard to be a couple of steps behind the best usage.
The impact on CASE tools

CASE tools have a particular role to play in this standards world, and their decisions will affect the way
you use the UML. Essentially CASE tools must make a choice about how they will play the UML game.
The great advantage of the UML for CASE industry is that it frees them from the necessity of supporting
multiple methods. They can now focus their energies on doing something useful with the UML.

In order to support the UML they have to support the UML meta-model, but all the interpretation issues
still apply. As an example we'll see different decisions made with code generators. Not just will they
generate different code, they'll make different decisions about the intention of the code they generate. So
you'll find that the UML in one case tools doesn't mean the same as the UML in another.

CASE tools talk about their ability to check your diagrams for you, to prevent you from making
mistakes. They see it as a feature, but I'm not so sure. I know what I want to do, and I find it very
irritating when a CASE tools doesn't let me do something I need. People see it as a boon for less
experienced developers, but I think that a good review process is far more valuable than mechanical
checking. Tools miss the subtleties of communication. So don't let CASE tools be the arbiter of what
you draw. Your brain can beat a CASE tools any day.

http://www.martinfowler.com/distributedComputing/standard.html (3 of 3)05/12/2003 15:37:43


Refactoring Home Page

Catalog Mailing List Book Supplements Tools Links martinFowler.com

Refactoring Home Page

Maintained by Martin Fowler, Chief Scientist: ThoughtWorks

Refactoring is a technique to restructure code in a disciplined way. For a long


time it was a piece of programmer lore, done with varying degrees of
discipline by experienced developers, but not passed on in a coherent way. In July 1999 Addison-
Wesley published my book describing Refactoring. The book describes the refactoring process, together
with a catalog of refactorings. Since that book refactoring has played an increasingly visible role in
software development. There is more written about it and since the beginning of 2001 we've seen a lot of
development of a new breed of refactoring tools, which I believe will make a huge impact to the work of
software development.

I originally intended this site to be a support site for my book and a source for updates to the refactoring
scene. It's since become a kind of refactoring portal, but I say that apologetically since I've never found
the amount of time to devote to it that it's really needed. However I do try to collect here as much
information on refactoring as I can keep up with.

News
In recent years, Alejandro Garrido has been working on a refactory for C as part of a doctoral
thesis at UIUC (where else?) One the biggest challenges of this project is dealing with the pre-processor.
Her site includes papers and on-going thesis documentation on her progress so far.

Over much of the last year or so I've been very frustrated by a lack of refactoring support for .NET. In
January 2003 I heard about a couple of tools that support refactoring in .NET. I hope that people will
post their experiences with these to the refactoring list.

Online Catalog
At the moment, this online catalog contains mostly summaries of the refactorings in the refactoring
book. The summaries are limited to the name, outline, and sketch from the book; you'll have to go to the

http://www.refactoring.com/ (1 of 3)05/12/2003 15:37:45


Refactoring Home Page

book for more information.

Supplements for the Refactoring Book


Oh yes, I make mistakes. Fortunately some careful readers spot them, so here's the errata.

One of the frustrating parts of writing this book is that I threw away more pages than are in the book.
Here's one of chapters that didn't cut it: a 98 page example of refactorings. Just right for a really
sleepless night!

Several people have asked about the source code for the refactorings. I'm afraid I don't have the source
code in any edible form.

Links to Other Refactoring Sites


There is a refactoring mailing list at http://groups.yahoo.com/group/refactoring

Many of the folks at UIUC who've been close to the development of refactoring are now working
together under the name of The Refactory Inc. Don Roberts's home page also contains a lot of useful
links on refactoring.

Josh Kerievsky has been exploring the relationship between refactoring and patterns and has detailed
several interesting refactorings that show how you can evolve into the well known design patterns.

Bill Opdyke wrote the first serious publication on Refactoring, which is Bill Opdyke's Phd thesis.

Don Roberts has also completed his thesis.

The wiki web is fascinating discussion group hosted by Ward Cunningham. You can find a lot of
discussion about refactoring on the wiki.

Luciano Ramalho has produced a Python transcription of the example from chapter 1. You get to see all
of the refactorings with the distinct flavor of Python - a language I like a lot.

Bill Wake has been working with extreme programming and has put together quite a few nice essays on
his thoughts and experiences. Several of these touch on refactoring, including an example refactoring
session (later extended), refactoring in and out of the composite pattern, and some refactorings and
optimizations inspired by Jon Bentley's work.

http://www.refactoring.com/ (2 of 3)05/12/2003 15:37:45


Refactoring Home Page

The CoreJ2EE patterns book contains many refactorings targeted at J2EE.

Ward Cunninghams famous wiki has several wiki pages on refactoring.

Mel Ó Cinnéide is a lecturer at University College Dublin who is interested in composite refactorings
using Java.

Don Batory and Lance Tokuda have been doing some research on refactoring. They don't have a single
web page to summarize their work in this area, but they recommend a pdf paper as a recent overview.

If you look at any work in program restructuring, you're bound to come across the work of Bill
Griswold. He's been researching program restructuring techniques for over a decade.

Linking to this site


Feel free to link into this site. I'm intending to maintain the route into the catalog pages so you can link
directly to catalog pages if you want to when talking about refactorings.

Don Wells put together an excellent site on extreme programming. In doing this he
created a very nice graphic for refactoring. He's kindly allowed me to use it and suggest
you also use it for linking to refactoring.com. Thank him by taking a look at
extremeprogramming.org.

©All materials on this site are copyrighted. For articles attributed to named authors, they are the copyright of the
corresponding authors. Any unattributed articles are copyright Martin Fowler.Please link freely to this site, but if you
want to copy any of the materials you should contact the authors first

http://www.refactoring.com/ (3 of 3)05/12/2003 15:37:45


Crossing Refactoring's Rubicon

About Contact
Home Blog Articles Books ThoughtWorks
Me Me

Crossing Refactoring's Rubicon


Martin Fowler
Chief Scientist, ThoughtWorks

Last Significant Update: February 2001

In January 2001 two Java tools crossed Refactoring's Rubicon. Refactoring in Java now has serious tool
support

As I suspect anyone who's reading this knows, I'm a big fan of refactoring. It's something I've wrote about
and talked about for several years now. But one thing I also know is that this is the early days of
refactoring. In my book, I describe how to manually refactor programs. Yet manual refactoring really is
about cutting down a forest with an axe - we need refactoring tools to take a real chain saw to the problem.

Of course refactoring tools are not unknown. Even before I started work on the refactoring book, John
Brant and Don Roberts came up with the Smalltalk Refactoring Browser. This awesome tool makes
refactoring much quicker and more pleasurable. The trouble is that it is a Smalltalk tool, and not many
people are using Smalltalk. Indeed I've hardly ever used the Refactoring Browser because most of the
work I've done in the last few years has been in Java.

But the Refactoring Browser makes one thing very clear. Tool support for refactoring is both possible and
valuable. I always believed it was only a matter of time. As a popular memory-managed language, I
expected that Java would soon have such tools.

Approaching The Rubicon


In 1999 a number of people contacted me about tools they were working on that supported refactoring. I
keep a list of these tools at www.refactoring.com (there another list on the wiki). Although refactoring.
com is hardly a hub of the web people clearly wanted to be listed amongst the refactoring tools.

However I'm not at all interested in reviewing refactoring tools on the site. There are many things that
interest me, but reviewing software products is not one of them. I'm happy to keep a list, but reviews I'll
leave to others.

Having said that some minimum standards are in order. A couple of vendors wanted me to mention their

http://www.martinfowler.com/articles/refactoringRubicon.html (1 of 3)05/12/2003 15:37:46


Crossing Refactoring's Rubicon

tools. I looked at their "Move Method" capability, and found that although they could move a method
body from one class to another, they didn't alter the callers. As a result a program no longer compiles after
applying the transformation: hardly semantics preserving!

There were tools that were more honest about their capabilities. A number offered the ability to do various
kinds of renaming, such as Rename Method. Now providing the callers are adjusted, renaming counts as a
refactoring - and a very useful one to boot. Also several tools support Move Class and, since repackaging
is a pain in the neck in Java, this is a very useful refactoring.

All of these were encouraging signs. But even so I was not seriously excited. All these were steps, but
there was a key barrier to cross.

The Rubicon
The kinds of renames that I've been talking about require some analysis of the software, but it's fairly
shallow. You can do renames with without going too deep into the structure of the program. Indeed many
people do renames manually by editor search/replace or through simple regular expression based scripts.
To go the full extent into refactoring you actually have to analyze and manipulate the parse tree of the
program, as John and Don describe in the book.

A refactoring that needs this capability is Extract Method. While one reviewer on amazon described this as
merely cut and paste, Extract Method actually requires some serious work. You have to analyze the
method, find any temporary variables, then figure out what to do with them. The analysis is not something
you can do by regular expression manipulation. It requires some careful work.

That's why I see it as a key refactoring. If you can do Extract Method, it probably means you can go on
more refactorings. It's the sign that says "I'm serious about this".

Crossing the Rubicon


The first thing that made me think there was a serious attempt at crossing the Rubicon was in mid-1999
when I was contacted by Instantiations. For those that don't know, Instantiations is one of the most highly
regarded names in OO circles. Born out of the Portland Smalltalk community the company was one of the
major parts of Digitalk and did a lot of serious work in Smalltalk. Since then they've moved onto to Java
and developed several products, including Jove - a native compiler.

So when Instantiations said they were starting work on a refactoring tool (then codenamed Alchemy - now
called jFactor) I was excited because I knew they had the understanding to do a good job. I was even more
encouraged when they said that the first refactoring they were going to tackle was Extract Method.

However they weren't the first across the river. That prize goes to X-ref: a plug in for emacs developed by

http://www.martinfowler.com/articles/refactoringRubicon.html (2 of 3)05/12/2003 15:37:46


Crossing Refactoring's Rubicon

Marian Vittek. To be honest this didn't have a big effect on me as I don't do my Java in emacs. Also x-ref's
extraction has some limitations and Marian's outfit is a small operation. But it got there and is well worth
looking at if you use emacs regularly.

If X-ref was the rowboat crossing the Rubicon, Instantiations crossed the river in style. Their tool jFactor
supports a nice list of refactorings, including Extract Method, in a very professional looking tool. jFactor
is available as a plug in for IBM's Visual Age for Java. Now extract method is just a case of select the
code, choose the menu item, and type in the name. Refactoring is here in style.

jFactor was enough for me to consider January 2001 a banner month for refactoring, but I got a pleasant
surprise. For a while IntelliJ have been building an IDE for Java that was liked for its Visual Age like
searching capabilities. They added various renaming capabilities to the tool which made it a minor favorite
on the sixth floor here where we were unable to use Visual Age. Then in January I got a surprise email -
their IDEA tool now supports Extract Method.

Going Further
The January flurry is exiting for me, as I'm convinced that refactoring tools are going to make a big impact
on software engineering. Indeed I've called John and Don's Refactoring Browser the biggest step forwards
in development tools since the IDE. I also hope that now the Rubicon of Extract Method is crossed, more
refactorings will follow. Certainly I urge you check out these tools and try out their refactoring
capabilities.

As a side note, I'm not going to provide reviews of these tools. Doing a proper review is too time
consuming. I do keep in touch with these vendors and will be doing what I can to help their developments.
However I would be interested in seeing feedback on these tools and will continue to maintain a list on
refactoring.com information about refactoring tools. I'll also post tool news on that site as the vendors
share it with me.

Revision History

Here's a list of the major updates to this paper

● February 2001: Original article posted to martinfowler.com

© Copyright Martin Fowler, all rights reserved

http://www.martinfowler.com/articles/refactoringRubicon.html (3 of 3)05/12/2003 15:37:46


UML Distilled (3rd Edition): errata

About Contact
Home Blog Articles Books ThoughtWorks
Me Me

Errata for UML Distilled (3rd Edition)


In September 2003, the 3rd edition of UML Distilled appeared. To keep up to date with the UML, you
should get the new edition as it is compatible with the latest UML 2 standard. For people who have the
2nd edition, I will keep the errata for the 2nd edition available.

Page inside front right cover: On the box marked composite structures, the delegation connectors should
be solid lines not dashed.

Page 12: In figure 1.2 the line connecting Composite Structure Diagram to the generalization structure is
missing.

Page 67: In figure 5.1, the arrows between the classes should be dashed lines since they are dependencies.

Page 73: In figure 5.9, all the message arrowheads should use a filled black synchronous arrowhead rather
than the stick arrowhead. Furthermore the participants at the top should not have their names underlined.
(I suppose since this is a non-normative diagram I could rationalize this away, but I should stick as close
to the standard as I can and correct even the backward incompatible changes.

Page 108: On the third line "providing the door is open" should read "providing the door is closed"

Page 125: Second paragraph, last sentence: "on the output pin quary that supplies" should read "on the
output pin query that supplies"

Page 135: Fifth paragraph, the phrase "delegating connector" should be replaced by "delegation
connector" in two places.

Page 136: In figure 13.2, the delegation connectors should be solid lines, not dashed. Also the label
"delegation connector" should be changed to "delegating connector".

Page 140: In figure 14.2 the delegation connectors should be solid lines, not dashed.

Page 143: Fifth paragraph, first sentence: "When you use a collaboration, you can show that by placing..."
should read "When you use a collaboration, you can show you're using one by placing..." Also the words
"collaboration occurrence" should be in bold.

http://www.martinfowler.com/umlsupp/umlErrata.html (1 of 2)05/12/2003 15:37:46


UML Distilled (3rd Edition): errata

Many thanks to Jim Wanner, Magnus Vesterlund, Marcus Price and others I've forgotten for spotting and
telling me about these errors

© Copyright Martin Fowler, all rights reserved

| Home |

http://www.martinfowler.com/umlsupp/umlErrata.html (2 of 2)05/12/2003 15:37:46


Software Development Online: October

December 2003
Search
more search
713 USERS ONLINE

HOMEPAGE
SITE CONTENTS BY YEAR October 2000
RESEARCH REPORTS Issue Theme: Tales of Terror
SEND US FEEDBACK
SUBSCRIBE TO SD
ADVERTISE WITH SD
MY ACCOUNT
Practices
LOG OUT
REGISTRATION FAQ COVER FEATURE Issue Theme:
Tales of Terror Component Success
--more--
OPEN SOURCE Gather 'round the campfire and let your flashlights cast spooky shadows. You're about to
AGILE PROCESSES encounter hair-raising horror in the form of performance problems, poor planning and skipped
THE SALARY SURVEY specifications... Subscribe For Free
THE JOLT AWARDS Now!
SD BEST PRACTICES UML ROUNDTABLE
Defining the UML Kernel
FUTURE OF DATABASES by Roger Smith
MDA EXPLAINED Faced with increasing system complexity and shorter deadlines, a new generation of modelers is
ANTI-PIRACY MEASURES
working at removing, rather than adding, complications to an already massive standard for
designing software.

Focus On: Project Management


REAL-WORLD REQUIREMENTS
The Habits of Effective Analysts
by Karl Wiegers
Software specs don't just lie around waiting for someone to collect them.

TUTORIAL
Estimating Software Costs
by William H. Roetzheim
First in a four-part series: How big will the system be? And how do you measure it?
http://www.sdmagazine.com/articles/2000/0010/ (1 of 5)05/12/2003 15:37:52
Software Development Online: October

CAREER & TRAINING


UML DESIGN CENTER Focus On: E-Development and Security
PROJECT MANAGEMENT
SECURITY
SECURITY BEAT
BEYOND OBJECTS
CONFERENCE COVERAGE Safe Signatures?
PRODUCT REVIEWS by Roger Smith
TEST CENTER Uncle Sam giveth, Uncle Sam taketh away.

TOOLBOX
SCOTT AMBLER
GRADY BOOCH No More Cracks in the Wall
WARREN KEUFFEL by Roger Smith
BERTRAND MEYER
CLEMENS SZYPERSKI
ROBERT MARTIN People
AGILE MODELING MANAGEMENT FORUM
DEVTALK
SUBSCRIBE
Money Bags and Baseball Bats
by Rob Thomsett
Five rules for managing your project's sponsor.
SD WEST 2004
SD BEST PRACTICES
Products
AUTHOR GUIDELINES
EDITORIAL CALENDAR HELLO, WORLD!
AUTHOR BIOGRAPHIES
Open Source Forte for Java
by Chris Minnick
HOME Sun climbs on the free software bandwagon with its soon-to-be released development
CAREER CENTER environment.
HOT TOPICS
INTERFACE PRODUCT REVIEW
MODELING AND DESIGN
OFFSHORE OUTSOURCING Debugging Applications in the Field
PROJECT MANAGEMENT by Andy Barnhart
READER REVIEWS Many use the "do-nothing" approach to implementing code for tracing after release.
TESTING & Q.A.
WEB SERVICES
Departments
EDITORIAL CALENDAR
POSTED PRESS RELEASES THINKING OBJECTIVELY
MEDIA KITS
Enterprise Java Bean Persistence 201
ADVERTISING CONTACTS
DEVELOPING WITH COMPONENTS Scott Ambler
Container-managed persistence decouples your object schema from your data schema.

http://www.sdmagazine.com/articles/2000/0010/ (2 of 5)05/12/2003 15:37:52


Software Development Online: October

BEYOND OBJECTS Subscribe to


Components and Architecture Software
Clemens Szyperski Development's
Contracts make reusable building blcoks easier to implement, test and compose. email newsletters
Agile Modeling
TOOLS OF THE TRADE (Monthly)
Getting Ahead in Software Online Update
(Monthly)
Warren Keuffel
DevTalk
Janet Ruhl's career advice may help you survive the dot-com meltdown.
(Monthly, HTML
only)
EDITOR'S NOTES Web Services
Buyer Beware (Monthly)
Alexandra Weber Morales SD Show Daily
Information is the currency of the Internet. (Occasional)
SD People and
FEEDBACK Projects
(Monthly)
Letters to the Editor
SD Secure Start
Our readers discuss virtual machines, positive projects, coupling measures, customer agreements (Monthly)
and 64-bit omissions.
your email
NEW AND NOTEWORTHY Submit
Java Rules!
Roger Smith (more information)
ILOG's JRules, ForInstance.com, INT's J/CarnacPro toolkit, Intuitive System's Optimzeit,
FileStream's TurboZIP 4.2 and jGuru's free short courses.

http://www.sdmagazine.com/articles/2000/0010/ (3 of 5)05/12/2003 15:37:52


Software Development Online: October

http://www.sdmagazine.com/articles/2000/0010/ (4 of 5)05/12/2003 15:37:52


Software Development Online: October

MarketPlace
Stop struggling to get new clients and projects!
Free, innovative marketing and sales advice exclusively for IT professionals and
consultants. Articles, audio tips, and a free weekly newsletter packed with unique, proven
strategies to grow your IT business.
Accelerate your Java™ development! Announcing Borland® JBuilder® X
With the leading cross-platform Java IDE on your side, speed your Web, XML, mobile,
database app dev with 2-way visual designers. Empower your productivity with Struts,
Web Services designers, UML™ code visualization, refactoring and more! Download a free
JBuilder X trial now! (URL)
U.S. Engineers and IT Professionals
National Technological University's degrees in Engineering and Information Technology
best serve students in the United States. Advance your career with a technical degree
from an accredited university. Learn more about NTU today!
Building Enterprise-Class Applications Just Got Easier
Build enterprise-class applications smarter, faster, and better with BEA WebLogic
Workshop 8.1. Find out how simple it is without downloading any software. Start your
free, no-obligation hosted trial.
Parature Online Support Software
Industry’s most powerful online support portal to manage and deflect up to 80% of your
incoming service inquiries. The #1 web-based help desk software that features self-
service, ticket management, contact management, online surveys, forums and more.
Wanna see your ad here?

Travel: Hotels • Las Vegas Hotels • Popular Hotels | Finance: Compensation Claims | Electronics Digital
Cameras • Digital Camera • Sony Digital Camera • Camcorders | Miscellaneous: SEO Company : SEO Guy
• Systems Management Software

Copyright © 2003 CMP Media LLC, SD Magazine's Privacy Policy, Comments: webmaster@sdmagazine.com
SDMG Web sites: BYTE.com, C/C++ Users Journal, Dr. Dobb's Journal, MSDN Magazine, Sys Admin, SD Expo, SD
Magazine, Unixreview, Windows Developer Network, New Architect

web1

http://www.sdmagazine.com/articles/2000/0010/ (5 of 5)05/12/2003 15:37:52


Appendix B

Changes between
UML Versions

When this book first appeared on the shelves, the UML was in version
1.0. Much of it appeared to have stabalized and it was in the process of
OMG recognition. Since then there have been a number of revisions. In
this appendix I describe the significant changes that occur, and how
they affect the material in this book. If you have an earlier printing of
the book, this summarizes the changes so you can keep up to date. I
have made changes to the book to keep up with the UML, so if you
have a later printing it describes the situation as it was at that time.

Revisions in the UML


The earliest public release what came to be the UML was version 0.8 of
the unified method. It was released for OOPSLA (October) 1995. It was
called the “Unified Method” and was the work of Booch and Rum-
baugh, as Jacobson did not join Rational until then. In 1996 they
released a 0.9 and a 0.91 version that included Jacobson’s work. At this
time they changed the name to the UML.
Version 1.0 of the UML was submitted to the OMG Analysis and
Design Task force in Janurary 1997. It was then combined with other
submissions and a single proposal for the OMG standard was made in

207
208 APPENDIX B CHANGES BETWEEN UML VERSIONS

Septemember 1997, this was called version 1.1. This was adopted by
the OMG towards the end of 1997. In a fit of darkest obfustication the
OMG called this standard version 1.0. So it was both OMG version 1.0
and Rational version 1.1, not to be confused with Rational 1.0. In prac-
tice everyone calls that standard version 1.1.
UML 1.1 had a number of minor visible changes from version 1.0.
When the OMG adopted UML 1.1 they set up a Revision Task Force
(RTF) chaired by Cris Kobryn to tidy up various loose ends with the
UML. They interally released version 1.2 in July 1998. This release was
internal in that 1.1 remained the official UML standard. You could
think of version 1.2 as a beta release. In practice this distinction hardly
mattered as the only changes in the standard were editorial: fixing
typos, grammatical errors and the like.
A more significant change occurred with version 1.3, most notably
affecting Use Cases and Activity Diagrams. The amigos’ user guide
and reference manual were published late in 1998 with the 1.3
changes, before the official 1.3 documents were made public, which
caused some confusion.
In April 1999 the RTF will submit version 1.3 to the OMG as new offi-
cial standard of the UML. The OMG Analysis and Design Task Force
will then take over the UML again and consider any future moves. Of
course this is what I currently know, check my web site for future
update information.

Changes in UML Distilled


As these revisions go on, I’ve been trying to keep up by revising UML
Distilled with subsequent printings. I’ve also taken the opportunity to
fix errors and make clarifications.
The 1st through 5th printings are based on UML 1.0. Any changes
between these printings were minor. The 6th printing took UML 1.1
into account, (however due to a glitch the inside covers still show 1.0
notation). The 7th through 10th printings were based on UML 1.2.
Those printings based on UML after 1.0 have the UML version number
on the front cover. (Unfortunately a printing error meant that some
copies of the 10th printing were labelled as 1.3 — I’m sorry about that.)
CHANGES FROM UML 1.0 TO 1.1 209

In the rest of this appendix I’ll summarize the two major changes in
the UML, from 1.0 to 1.1 and from 1.2 to 1.3. I won’t discuss all the
changes that occur, but rather only those that
• change something I said in UML Distilled, or
• represent important features that I would have discussed in UML
Distilled
I am continuing to follow the spirit of UML Distilled: to discuss the key
elements of UML as they affect the application of the UML within real
world projects. As ever, the selections and advice are my own. If there
is any conflict between what I say and the official UML documents, the
UML documents are the ones to follow. (But do let me know, so I can
make corrections.)
I have also taken the opportunity to indicate any important errors or
omissions in the earlier printings. Thanks to the readers who have
pointed these out to me.

Changes from UML 1.0 to 1.1

Type and Implementation Class


On page 55 of UML Distilled, I talked about perspectives, and how they
altered the way people draw and interpret models, in particular class
diagrams. UML now takes this into account by saying that all classes
on a class diagram can be specialized as either types or implementa-
tion classes.
An implementation class corresponds to a class in the software envi-
ronment in which you are developing. A type is rather more nebulous;
it represents a less implementation-bound abstraction. This could be a
CORBA type, a specification perspective of a class, or a conceptual
perspective. If necessary, you can add stereotypes to differentiate fur-
ther.
You can state that for a particular diagram, all classes follow a particu-
lar stereotype. This is what you would do when drawing a diagram
from a particular perspective. The implementation perspective would
210 APPENDIX B CHANGES BETWEEN UML VERSIONS

use implementation classes, while the specification and conceptual


perspective would use types.
You use the realization relationship to indicate that an implementation
class implements one or more types.
There is a distinction between type and interface. An interface is
intended to directly correspond to a Java or COM style interface. Inter-
faces thus have only operations and no attributes.
You may use only single, static classification with implementation
classes, but you can use multiple and dynamic classification with
types. (I assume this is because the major OO languages follow single,
static classification. If one fine day you use a language that supports
multiple or dynamic classification, that restriction really should not
apply.)

Complete and Incomplete Discriminator Constraints


On page 78 of previous printings of UML Distilled, I said that the {com-
plete} constraint on a generalization indicated that all instances of the
supertype must also be an instance of a subtype within that partition.
UML 1.1 defines instead that {complete} indicates that all subtypes
within that partition have been specified, which is not quite the same
thing. I have found a lot of inconsistency on the interpretation of this
constraint, so you should be wary of it. If you do want to indicate that
all instances of the supertype should be an instance of one of the sub-
types, then I suggest using another constraint to avoid confusion. Cur-
rently, I am using {mandatory}.

Composition
In UML 1.0, using composition implied that the link was immutable
(or frozen; see below), at least for single-valued components. That con-
straint is no longer part of the definition.

Immutability and Frozen


UML defines the constraint {frozen} to define immutability on associa-
tion roles. As it’s currently defined, it doesn’t seem to apply it to
attributes or classes. In my practice, I now use the term frozen instead
CHANGES FROM UML 1.2 (AND 1.1) TO 1.3 211

of immutability, and I’m happy to apply the constraint to association


roles, classes, and attributes.

Returns on Sequence Diagrams


In UML 1.0, a return on a sequence diagram was distinguished by
using a stick arrowhead instead of a solid arrowhead (see page 104).
This was something of a pain, since the distinction was too subtle and
easy to miss. UML 1.1 uses a dashed arrow for a return, which pleases
me, as it makes returns much more obvious. (Since I used dashed
returns in Analysis Patterns, it also makes me look influential.) You can
name what is returned for later use by using the form “enoughStock :=
check()”.

Use of the Term “Role”


In UML 1.0, the term role primarily indicated a direction on an associ-
ation (see page 57). UML 1.1 refers to this usage as an association end.
There is also a collaboration role, which is a role that an instance of a
class plays in a collaboration. Many people still use the term role to
mean a direction of an association, although association end is the for-
mal term.

Changes from UML 1.2 (and 1.1) to 1.3

Use Cases
The changes to use cases involve new relationships between use cases.
1.1 has two use case relationships: «uses» and «extends», both of
which are stereotypes of generalization. 1.3 offers three relationships.
• «include» - a stereotype of dependency. This indicates that the
path of one use case is included in another. Typically this occurs
when a few use cases share common steps. The included use case
can factor out the common behavior. An example from an ATM
machine might be that “Withdraw Money” and “Make Transfer”
both use “Validate Customer”. This replaces the common use of
«uses».
212 APPENDIX B CHANGES BETWEEN UML VERSIONS

• generalization (no stereotype). This indicates that one use case is a


variation on another. Thus we might have one use case for With-
draw Money (the base use case) and a separate use case to handle
the case where the withdrawal is refused due to lack of funds. The
refusal could be handled as a use case that specializes the with-
drawal use case. (You could also handle it as just another scenario
within the Withdraw Money use case.) A specializing use case like
this may change any aspect of the base use case.
• «extend» - a stereotype of dependency. This provides a more con-
trolled form of extension than the generalization relationship. Here
the base use case declares a number of extension points. The
extending use case can only alter behavior at those extension
points. So if you are buying a product on line, you might have a
use case for buying a product with extension points for capturing
the shipping information and capturing payment information.
That use case could then be extended for a regular customer where
this information would be obtained a different way.
One of the confusions of all this is the relationship between the old
relationships and the new. Most people used «uses» the way the 1.3
«includes» is used, so for most people we can say that «includes»
replaces «uses». People used 1.1 «extends» in both the controlled man-
ner of the 1.3 «extends» and as a general overriding in the style of the
1.3 generalization. So you can think that 1.1 «extends» is split into the
1.3 «extend» and generalization. Now although this explanation cov-
ers most usage of the UML that I saw, it isn't the strictly correct way of
using those old relationships. However most people didn't follow the
strict usage and I don't really want to get into all that here.

Activity Diagrams
At 1.2 there were quite a few open questions on the semantics of Activ-
ity Diagrams. So the 1.3 effort did quite a lot of tightening up on these
semantics.
For conditional behavior the diamod shaped decision activity can now
be used for a merge of behvior as well as as a branch. Although neither
branches or merges are necessary to describe conditional behavior, it is
increasingly common style to show them so that you can bracket con-
ditional behavior.
CHANGES FROM UML 1.2 (AND 1.1) TO 1.3 213

The synchronization bar is now referred to as a fork (when splitting


control) or as a join (when synchronizing control together). You can no
longer add arbitrary conditions to joins. You must also follow match-
ing rules to ensure forks and joins match up. Essentially this means
that each form must have a corresponding join that joins the threads
started by that fork. However you can nest fork and joins, and you can
eliminate forks and joins on the diagram when threads go directly
form one fork to another fork (or one join to another join).
Joins are only fired when all incoming threads complete. However you
can have a condition on a thread coming out of a fork. If that condition
is false, then that thread is considered complete for joining purposes.
Multiple Triggers are no longer present. Instead you can have
dynamic concurrency in an activity (shown with a * inside an activity
box). Such an activity may be invoked several times in parallel. All its
invocations must complete before any outgoing transition can be
taken. This is loosely equivalent, although less flexible, to a multiple
trigger and matching synchronization condition.
These rules reduce some of flexibility of activity diagrams, but they do
ensure that acitivity diagrams are truly special cases of state machines.
The relationship between activity diagrams and state machines was a
matter of some debate in the RTF. Future versions of the UML (after
1.3) are expected to make activity diagrams a completely different
form of diagram.
214 APPENDIX B CHANGES BETWEEN UML VERSIONS
design
Editor: Martin Fowler ■ T h o u g h t Wo r k s ■ fowler@acm.org

Who Needs an Architect?


Martin Fowler

andering down our corridor a while chitect.) However, as so often occurs, inside

W ago, I saw my colleague Dave Rice


in a particularly grumpy mood. My
brief question caused a violent
statement, “We shouldn’t interview
anyone who has ‘architect’ on his
resume.” At first blush, this was an odd turn of
phrase, because we usually introduce Dave as
one of our leading architects.
The reason for his title schizo-
the blighted cynicism is a pinch of truth. Un-
derstanding came to me after reading a posting
from Ralph Johnson on the Extreme Program-
ming mailing list. It’s so good I’ll quote it all.
A previous posting said

The RUP, working off the IEEE definition, defines


architecture as “the highest level concept of a sys-
tem in its environment. The architecture of a soft-
phrenia is the fact that, even by our ware system (at a given point in time) is its orga-
industry’s standards, “architect” nization or structure of significant components
and “architecture” are terribly interacting through interfaces, those components
overloaded words. For many, the being composed of successively smaller compo-
term “software architect” fits per- nents and interfaces.”
fectly with the smug controlling im-
age at the end of Matrix Reloaded. Johnson responded:
Yet even in firms that have the
greatest contempt for that image, I was a reviewer on the IEEE standard that used
there’s a vital role for the technical that, and I argued uselessly that this was clearly
leadership that an architect such as Dave plays. a completely bogus definition. There is no high-
est level concept of a system. Customers have a
What is architecture? different concept than developers. Customers do
When I was fretting over the title for Pat- not care at all about the structure of significant
terns of Enterprise Application Architecture components. So, perhaps an architecture is the
(Addison-Wesley, 2002), everyone who re- highest level concept that developers have of a
viewed it agreed that “architecture” belonged system in its environment. Let’s forget the devel-
in the title. Yet we all felt uncomfortable defin- opers who just understand their little piece. Ar-
ing the word. Because it was my book, I felt chitecture is the highest level concept of the ex-
compelled to take a stab at defining it. pert developers. What makes a component
My first move was to avoid fuzziness by significant? It is significant because the expert
just letting my cynicism hang right out. In a developers say so.
sense, I define architecture as a word we use
when we want to talk about design but want So, a better definition would be “In most successful
to puff it up to make it sound important. (Yes, software projects, the expert developers working
you can imagine a similar phenomenon for ar- on that project have a shared understanding of the

2 IEEE SOFTWARE Published by the IEEE Computer Society 0740-7459/03/$17.00 © 2003 IEEE
DESIGN

system design. This shared understanding The architect’s role their level so that they can take on
is called ‘architecture.’ This understanding So if architecture is the important more complex issues. Improving the
includes how the system is divided into stuff, then the architect is the person (or development team’s ability gives an ar-
components and how the components in- people) who worries about the impor- chitect much greater leverage than be-
teract through interfaces. These compo- tant stuff. And here we get to the ing the sole decision maker and thus
nents are usually composed of smaller essence of the difference between the running the risk of being an architec-
components, but the architecture only in- Matrix Reloaded species of architect tural bottleneck. This leads to the satis-
cludes the components and interfaces that and the style that Dave Rice exemplifies. fying rule of thumb that an architect’s
are understood by all the developers.” Architectus Reloadus is the person value is inversely proportional to the
who makes all the important decisions. number of decisions he or she makes.
This would be a better definition because The architect does this because a single At a recent ThoughtWorks retreat,
it makes clear that architecture is a so- mind is needed to ensure a system’s con- some colleagues and I were talking
cial construct (well, software is too, but ceptual integrity, and perhaps because about the issue of architects. I found it
architecture is even more so) because it the architect doesn’t think that the team interesting that we quickly agreed on the
doesn’t just depend on the software, but members are sufficiently skilled to make nature of the job, following Architectus
on what part of the software is consid- those decisions. Often, such decisions Oryzus, but we could not easily find a
ered important by group consensus. must be made early on so that everyone name. Architectus Reloadus is too com-
else has a plan to follow. mon for us to be comfortable with “ar-
There is another style of definition of ar- Architectus Oryzus is a different chitect,” and it’s based on a flawed
chitecture which is something like “archi- kind of animal (if you can’t guess, try metaphor (see http://martinfowler.com/
tecture is the set of design decisions that www.nd.edu/~archives/latgramm.htm). bliki/BuildingArchitect.html). Mike Two
must be made early in a project.” I com- This kind of architect must be very came up with the best name I’ve heard
plain about that one, too, saying that ar- aware of what’s going on in the project, so far: guide, as in mountaineering. A
chitecture is the decisions that you wish looking out for important issues and guide is a more experienced and skillful
you could get right early in a project, but tackling them before they become a se- team member who teaches other team
that you are not necessarily more likely to rious problem. When I see an architect members to better fend for themselves
get them right than any other. like this, the most noticeable part of the yet is always there for the really tricky
work is the intense collaboration. In the stuff.
Anyway, by this second definition, pro- morning, the architect programs with a
gramming language would be part of developer, trying to harvest some com- Getting rid of software
the architecture for most projects. By the mon locking code. In the afternoon, the architecture
first, it wouldn’t be. architect participates in a requirements I love writing a startling heading, and
session, helping explain to the require- the best, like this one, have an impor-
Whether something is part of the architec- ments people the technical conse- tant meaning that’s not immediately ob-
ture is entirely based on whether the de- quences of some of their ideas in non- vious. Remember Johnson’s secondary
velopers think it is important. People who technical terms—such as development definition: “Architecture is the decisions
build “enterprise applications” tend to costs. that you wish you could get right early
think that persistence is crucial. When they In many ways, the most important in a project.” Why do people feel the
start to draw their architecture, they start activity of Architectus Oryzus is to need to get some things right early in the
with three layers. They will mention “and mentor the development team, to raise project? The answer, of course, is be-
we use Oracle for our database and have cause they perceive those things as hard
our own persistence layer to map objects to change. So you might end up defining
onto it.” But a medical imaging applica- architecture as “things that people per-
tion might include Oracle without it being ceive as hard to change.”
considered part of the architecture. That is It’s commonly believed that if you
because most of the complication is in an-
What makes a are building an enterprise application,
alyzing the images, not in storing them. component significant? you must get the database schema right
Fetching and storing images is done by It is significant early on because it’s hard to change the
one little part of the application and most database schema—particularly once
of the developers ignore it. because the you have gone live. On one of our pro-
expert developers jects, the database administrator,
So, this makes it hard to tell people how Pramod Sadalage, devised a system
to describe their architecture. “Tell us
say so. that let us change the database schema
what is important.” Architecture is about (and migrate the data) easily (see http://
the important stuff. Whatever that is. martinfowler.com/articles/evodb.html).

July/August 2003 IEEE SOFTWARE 3


DESIGN

By doing this, he made it so that the Here’s Johnson again, this time in My reservation of Aspect-Oriented Pro-
database schema was no longer archi- response to an email message I sent gramming is that we already have fairly
tectural. I see this as an entirely good him: good techniques for separating aspects
thing because it let us better handle of programs, and we don’t use them. I
change. One of the differences between building don’t think the real problem will be
At a fascinating talk at the XP 2002 architecture and software architecture is solved by making better techniques for
conference (http://martinfowler.com/ that a lot of decisions about a building separating aspects. We don’t know what
articles/xp2002.html), Enrico Zani- are hard to change. It is hard to go back should be the aspects that need separat-
notto, an economist, analyzed the un- and change your basement, though it is ing, and we don’t know when it is worth
derlying thinking behind agile ideas in possible. separating them and when it is not.
manufacturing and software develop-
ment. One aspect I found particularly There is no theoretical reason that any- Software is not limited by physics, like
interesting was his comment that irre- thing is hard to change about software. buildings are. It is limited by imagina-
versibility was one of the prime drivers If you pick any one aspect of software tion, by design, by organization. In
of complexity. He saw agile methods, in then you can make it easy to change, short, it is limited by properties of peo-
manufacturing and software develop- but we don’t know how to make every- ple, not by properties of the world. “We
ment, as a shift that seeks to contain thing easy to change. Making something have met the enemy, and he is us.”
complexity by reducing irreversibility— easy to change makes the overall system
as opposed to tackling other complex- a little more complex, and making
ity drivers. I think that one of an archi- everything easy to change makes the en-
tect’s most important tasks is to remove tire system very complex. Complexity is
Martin Fowler is the chief scientist for ThoughtWorks, and In-
architecture by finding ways to elimi- what makes software hard to change. ternet systems delivery and consulting company. Contact him at
nate irreversibility in software designs. That, and duplication. fowler@acm.org.

4 IEEE SOFTWARE h t t p : / / c o m p u t e r. o r g / s o f t w a r e
design
Editor: Martin Fowler ■ T h o u g h t Wo r k s ■ fowler@acm.org

The Difference between


Marketecture and
Tarchitecture
Luke Hohmann

ver the years, I’ve been fortunate software architect or chief technologist as the

O enough to help build a fairly diverse set


of software solutions. Along the way,
I’ve played various roles, including in-
dividual contributor, direct manager,
and senior member of the corporate
executive staff. I’ve worked in engineering,
product marketing and product management,
quality assurance, first- and sec-
ond-line support organizations,
tarchitect and the product-marketing manager,
business manager, or program manager re-
sponsible for the system as the marketect.
The tarchitecture is the dominant frame of
reference when developers think of a system’s
architecture. For software systems, it encom-
passes subsystems, interfaces, the distribution
of processing responsibilities among processing
elements, threading models, and so forth. In re-
Good and on technical publications. One cent years, several authors, including Martin
development thing I’ve learned is that a gap of- Fowler and Mary Shaw, have documented dis-
ten exists between product man- tinct tarchitecture styles or patterns, including
processes agement/marketing and engineer- client-server, pipeline, embedded systems, and
address more ing/development organizations. blackboards. Our profession has begun to doc-
Although we might briefly ument how and when these various kinds of ar-
than how to chuckle when Dilbert calls atten- chitectures are appropriate. It remains to be
write code. tion to this gap, most of us who’ve seen if we’ll have the discipline to routinely
lived through it (or helped cause it) leverage this knowledge.
cringe at its effects: product and Marketecture is the business perspective of
service offerings that ultimately fail to meet the system’s architecture. Among other things,
market needs. An essential step to bridging it embodies
this gap is to clarify the various responsibilities
associated with product management and ■ The complete business model, including li-
marketing versus those associated with prod- censing and selling models
uct engineering and development. We must ■ Value propositions
also clarify the manner in which the marketing ■ Technical details relevant to the customer
and technical aspects of the system work to- ■ Data sheets
gether to accomplish business objectives. ■ Competitive differentiation
■ Brand elements
Who is responsible for what? ■ The mental model that the marketing de-
We can divide software systems architec- partment attempts to create for the customer
turally along two broad dimensions. The first ■ The system’s specific business objectives
is the tarchitecture or “technical architecture”
and the second is the marketecture or “mar- Additionally, it includes—as a necessary com-
keting architecture.” I refer to the traditional ponent for shared collaboration between the

0740-7459/03/$17.00 © 2003 IEEE Published by the IEEE Computer Society IEEE SOFTWARE 51
DEPT
DESIGN
TITLE

tarchitects, marketects, and develop- installing, operating, maintaining, and comprehensive product development
ers—descriptions of functionality that upgrading multiple components. Inter- process can provide. When conducted
are commonly included in marketing nally, this approach became known as properly, these processes kick in before
requirements documents, use cases, XP the “$50,000 Boolean flag.” development begins, and they are al-
stories, and so forth. The second example illustrates that ways present after development is com-
Although tarchitecture and marketec- the inverse to this approach can also plete. To see what I mean, watch what
ture influence each other, marketecture work quite nicely. In this same system, your development organization does af-
dominates. Marketectural concerns— we sold a client-side Component Object ter it celebrates shipping the gold mas-
ranging from usability, installability, Model application programming inter- ter—it starts on the next version. The
upgradability, supportability, deployabil- face that was physically created as a sep- rest of the organization, from customer
ity reliability, and other so-called non- arate dynamic linked library. This let us and professional services, continues to
functional requirements—change radi- easily create and distribute bug fixes, up- work on the release, deploying it to cus-
cally from market to market. They all dates, and so forth. Instead of upgrading tomers, managing upgrades, conducting
influence the tarchitecture. a monolithic client (which is challenging press and analyst tours, and so forth.
in Microsoft-based architectures), we One reason the comprehensive prod-
Examples could simply distribute a new DLL. uct development process is a bigger Big
When I speak of the difference be- Marketing didn’t sell the API as a sepa- Picture is that this is where we calculate
tween marketecture and tarchitecture, rate component but instead promoted it profit and loss. Put another way, most
most people clamor for specific examples. as an integrated part of the client. organizations view engineering as a cost
Here are two for your consideration. center. The marketect is usually consid-
One “heavy-client” client-server ar- The big picture ered a “mini CEO,” responsible for the
chitecture that I helped create had a Software architecture has created var- product’s overall financial health. The
marketing requirement for a “modu- ious definitions. Most of the ones that effects of this responsibility can be far-
lar” extension of system functionality. I’ve found useful have some element of reaching, especially if they are not done
Its primary objective was to separately trying to capture the system’s big picture. effectively.
price each module and license it to cus- The same can be said of development One of my clients recently asked me
tomers. The business model was that, processes, the majority of which try to to conduct a business audit of one of
for each desired option, customers capture development’s big picture. From their products. The technical team was
would purchase a module for the XP to SCRUM to “just get it done,” in the process of transforming a heavy-
server that provided the necessary core good development processes address client client-server application to a
functionality. Each client would then more issues than just how to write code. browser-based application. Everyone
install a separately licensed plug-in to They deal with issues ranging from was thrilled with the progress they had
access this functionality. In this man- structuring the team to quality assurance made: customers liked the browser ap-
ner, the modules resided at both the practices to scheduling. proach (which was easier to manage
server and client level. One example These are big-picture issues, but and deploy), the technical team en-
was the extended reporting module—a they’re not big enough. If you’re run- joyed learning new skills, and market-
set of reports, views, and related data- ning a business whose products or ser- ing was busy making plans on how to
base extract code that a customer vice offerings are based on software, offer the new browser-based applica-
could license for an additional fee. In you need the bigger Big Picture that a tion as an application service provider.
terms of our pricing schedule, we sold I wasn’t so thrilled. My analysis in-
modules as separate line items. dicated that my client was one release
Instead of creating a true module on away from losing more than US$5 mil-
the server, we simply built all the code lion in licensing revenue. In the old sys-
into the server and enabled and disabled tem, both the client and server were of-
various modules with simple Boolean fered as a perpetual license with a 15
flags. Those in product management
My analysis indicated percent annual maintenance fee. As the
were happy because the group could in- that my client was one development team created releases that
stall and uninstall the module in a man- release away from migrated functionality from the client
ner consistent with their goals and ob- to the new server, my client simply
jectives for the overall business model. losing more than shipped them to customers based on
The developers were happy because US$5 million in the terms of their existing maintenance
building one product with Boolean flags agreement. Unfortunately, they had
is considerably simpler than building
licensing revenue. forgotten to consider that once all the
two products and dealing with the is- functionality in the client had moved to
sues that would inevitably arise when the server, they would lose their license

52 IEEE SOFTWARE h t t p : / / c o m p u t e r. o r g / s o f t w a r e
DESIGN
SOFTWARE
ENGINEERING Software configuration
revenue associated with the client. Be-
management domain
cause they had not created any means
to recoup the revenue, resolving the GLOSSARY (cont’d from inside
back cover)
problem wasn’t easy.
First, we delayed removing the
client until we had a way to recoup the
revenue. As you can imagine, this was program support librarian (PSL): See program librarian.
not well received by the technical team, release: The formal notification and distribution of an approved
but once they understood the financial version of a hardware/software system. [IEEE Std. 828-
implications, they supported the deci- 1998]
sion. Next, I worked with the legal software change control: The process by which a software
team to see if we had any freedom to change is proposed, evaluated, approved or rejected, sched-
charge upgrade fees for a new release uled, and tracked. [IEEE Std. 610.12-1990] See also config-
or increase the maintenance fees on the uration management, software configuration control.
server (because it had more functional- C a l i f o r n i a S t a t e U n i v e r s i t y, S a c r a m e n t o ■ t h a y e r @ c s u s . e d u software component (SC): A functionally or logically distinct
ity). We couldn’t charge an upgrade part of a software configuration item, distinguished for the
fee, but we could increase maintenance purpose of convenience in designing and specifying a com-
fees, provided the customer hadn’t plex SCI as an assembly of subordinate elements.
locked in the maintenance agreement software configuration: 1. The arrangement of a computer sys-
(several had). Finally, I suggested re- tem or component as defined by the number, nature, and in-
vamping the server’s business model to terconnections of its constituent parts. 2. The functional and
separately license each browser appli- physical characteristics of a software system as set forth in
cation, increasing both list and average technical documentation or achieved in a product. [IEEE Std.
selling price. Although some of these 610.12-1990]
changes were painful, they were less software configuration auditing: The process of verifying that
painful than losing $5 million. all required hardware/software configuration items have
been produced, that the current version agrees with speci-
hat does this mean for you? In- fied requirements, that the technical documentation com-

W dustry pundits, regardless of in-


dustry, tell us that to be successful
in today’s business climate, we must
pletely and accurately describes the configuration items,
and that all change requests have been resolved. [IEEE
Std. 610.12-1990] See also software configuration
transcend a self-absorbed focus on our management.
jobs and understand how our work fits software configuration control: The evaluation, coordination,
into the business’ larger objectives. For approval or disapproval, and implementation of changes to
developers, this can mean remembering configuration items after formal establishment of their con-
to check with your marketect depart- figuration identification. [IEEE Std. 610.12-1990] See also
ment regarding the impact of a major software configuration management.
Richard H. Thayer ■

tarchitectural change. To help you get software configuration identification: 1. An element of config-
started, send me the answer to the fol- uration management consisting of selecting the configuration
lowing questions: How does your com- items for a software system and recording their functional
pany make money (that is, what is your and physical characteristics in technical documentation.
business model)? What new technology 2. The current approved technical documentation for a soft-
will most affect your ability to lower ware configuration item as set forth in specifications, draw-
your customer’s total cost of owner- ings, associated lists, and documents referenced therein.
ship? Which nonfunctional require- [IEEE Std. 610.12-1990] See also software configuration
ment is most important to your cus- management.
tomers? I look forward to receiving software configuration item (SCI): A software entity that has
your answers. been established as a configuration item. The SCI exists
where functional allocations have been made that clearly
distinguish equipment functions from software functions and
Luke Hohmann is a management consultant for prod- where the software has been established as a configurable
uct management, software development, and organizational ef- item. Contrast with hardware configuration item.
fectiveness. Portions of this article were based on material from
his book Beyond Software Architecture: Creating and Sustaining
Winning Solutions (Addison-Wesley, 2003). Contact him at —Continued on p. 56
luke@lukehohmann.com.

July/August 2003 IEEE SOFTWARE 53


design
Editor: Martin Fowler ■ T h o u g h t Wo r k s ■ fowler@acm.org

Components and
the World of Chaos
Rebecca Parsons

any writers espouse the idea that that components don’t interact in ways other

M commercial software development


will soon consist of tribes of mon-
keys assembling commercially
available components, resulting in
faster development, significantly
reduced costs, and more reliable software. Al-
though we all dream that complex applications
development will eventually become faster,
cheaper, and better, realizing this dream with
than through the interfaces or assembly frame-
work. Also, tests should be able to demon-
strate that the component respects its inter-
face, and no part of a system should be terribly
complex. Additionally, suitably designed com-
ponents should be more amenable to reuse
than monolithic systems.
The complex development effort required
for building component systems involves both
components as currently conceived the creation of these components and their ag-
has some fundamental flaws. gregation into systems. In this view, the hard
work of software development moves from
Components building complete systems to designing and
As is often the case with trends creating these individual components, but even
in the IT industry, the term compo- this is easier given the boundaries on compo-
nent has too many meanings. For nents. The difficulty in software development’s
the purposes of this discussion, a assembly phase involves identifying the appro-
component priate components to use rather than creating
complex software. Some even envision global
■ Has a simple, well-defined in- repositories of components that existing sys-
terface tems monitor to find new or improved compo-
■ Is an object, meaning that the data and nents that perform desired functions. You
methods are combined as a unit could then incorporate these new components
■ Exhibits a degree of specialization of func- dynamically into an existing system.
tionality (often obtained through configu-
ration), with the appropriate range of life- Problems
cycle methods to support the desired However, problems exist, even without
functionality considering the impact of systems dynamically
■ Is designed with the expectation of reuse, changing their component configuration and
although the reuse context is unpredictable use. Assembling components requires

Additionally, a system built with components ■ Initially identifying the appropriate compo-
achieves complex functionality through the in- nents to implement the desired functionality
teraction of various components. ■ Determining and resolving gaps between
Sounds ideal. According to this, each simple the desired functionality and the compo-
component should be easy to specify, describe, nents’ functionality
create, and test. Encapsulation should ensure ■ Specifying the component interactions

0740-7459/03/$17.00 © 2003 IEEE Published by the IEEE Computer Society IEEE SOFTWARE 83
DESIGN

This requires a language that can suffi- We don’t need direct parallels to gories of development: designing and
ciently describe the components’ seman- emergent computation to see that con- developing component implementation
tics so that the component assembler can structing component systems is diffi- and constructing applications. We fo-
identify the desired components and see cult. Despite significant investment in cus on the latter—constructing applica-
how to connect them to achieve the de- tools and formalisms, delivered sys- tion components and applications us-
sired systems functionality. The assembler tems still contain significant defects, ing a component framework and a
must also understand how the compo- even when measured against expected suite of existing components. Design-
nent assembly framework interacts with behavior. Defining expected behavior ing a good component involves consid-
the components. Neither these activities at the component level is not sufficient ering several factors, including appro-
nor the tools that support them, nor the to ensure correct behavior at the global priate encapsulation, clean interfaces,
skills required to use them, are trivial. level, even when systems are con- appropriate granularity of functional-
Another problem with components structed using components. Specifying ity, appropriate balance of specificity
concerns their nature. One of the compo- the component solution’s expected be- and reusability, and completeness of
nent model’s primary strengths is that it havior requires specifying the results of functional coverage. The developers re-
separates large systems into simpler com- the components’ interactions with each sponsible for creating the component
ponents interacting through simple inter- other. The component framework com- must understand the component frame-
faces. Other types of systems share this municates with the components and work as well as the required component
strength. Work in the nonlinear systems external environment. behavior. The test design of the individ-
field has shown that the characteristics of Emergent computation in similar set- ual components is the most straightfor-
simple interfaces and the interaction of tings should be enough to convince us ward of these activities. If the compo-
simple entities through those interfaces that describing the expected behavior of nent is designed properly, the interfaces
can give rise to emergent behavior. such a complex of interacting compo- should be simple and completely speci-
nents is challenging at best. The most fied and the behavior should be prop-
Emergent computation rigorous component-level testing will erly encapsulated. (I’ve already de-
Emergent behavior, or emergent com- not tell us enough at the system level to scribed the difficulty of constructing
putation, describes the appearance of provide any assurances that we’ve and testing applications created using
global computation or problem solving achieved the desired result. So, we must components.)
from a system of distributed, discrete resolve the issue of understanding the Although components have poten-
computational systems. It is a computa- global behavior. We must also face how tially altered the desired balance of
tional ability that is not specifically pro- the computational power inherent in skills for developers, they have neither
grammed but rather emerges at a high components’ interacting systems affects radically simplified the task nor radi-
level when simpler components interact. our ability to construct systems. cally altered the basic skills and train-
Researchers in this field are often star- ing needed. The skills for component
tled at the level of complexity that arises Constructing applications designers and developers parallel
from very simple computational struc- Application development in the those needed for large-scale object-
tures. In systems with emergent charac- component world involves three cate- oriented design and development.
teristics, the system’s global behavior dif- Good objects and components share
fers from what designers anticipated. many design characteristics, such as
These failed expectations are often in the clean interfaces, functional cohesion,
behavior’s specifics (the particular solu- adaptability, and completeness. Simi-
tions generated, for example); however, larly, developing these systems re-
these surprises can also deviate from ex- quires skills in performance, readabil-
pectations in more substantial ways.
The most rigorous ity, and extensibility.
It is easy to dismiss this notion as component-level Designing and developing good
something akin to the latest science fic- components requires even more insight
tion thriller. Clearly, the components
testing will not tell us and vision into the application do-
used in software systems may not in- enough at the system main’s needs. It might seem that global
teract in arbitrary ways. They can’t alter level to provide any systems understanding becomes less
their internal behavior and act au- necessary in the component world.
tonomously, and systems using com- assurances that However, the issues with emergent be-
ponents are not designed to learn new we’ve achieved havior demonstrate the need for both a
behaviors. The components still exist global understanding of the component
in the particular framework originally
the desired result. interactions and a local understanding
specified, so these systems should still of individual components’ behavior.
behave tractably. This level of understanding is more

84 IEEE SOFTWARE h t t p : / / c o m p u t e r. o r g / s o f t w a r e
DESIGN

common in developers who understand he ideal world of systems development ing greater developer skills. However, this
the behavior of heterogeneous distrib-
uted and parallel systems. We are not
looking at a significant reduction in the
T by simple-minded composition of ex-
isting components doesn’t exist. Appli-
cation development is still a difficult un-
same complexity and power provides in-
triguing possibilities for harnessing the
potential emergent properties of compo-
skills necessary to develop systems in dertaking. We can’t resolve the issues with nents in the development process itself.
this model. In the world of compo- testing and ensuring correct behavior by But that’s another story.
nents, components are not easy to cre- simply invoking the power of compo-
ate properly, and applications are not nents. The power of simple component
Rebecca Parsons is a technology principle
easy to create, even when using well- interaction contributes to the component and senior architect at ThoughtWorks. Contact her at
designed components. development process’s complexity, requir- rjparson@thoughtworks.com.

SOFTWARE
ENGINEERING Requirements Synonymous with external specification.
engineering domain See also software requirements specification.
GLOSSARY (cont’d from inside
back cover)
nonfunctional requirement: A software requirement that
describes not what the software will do but how the
software will do it—for exam-ple, software perfor-
C a l i f o r n i a S t a t e U n i v e r s i t y, S a c r a m e n t o ■ t h a y e r @ c s u s . e d u

functional requirement: A system or software requirement mance requirements, software external interface re-
that specifies a function that a system/software system quirements, software design constraints, and software
or system/software component must be capable of quality attributes. Nonfunctional requirements are
performing. These are software requirements that de- sometimes difficult to test, so they are usually evaluated
fine system behavior—that is, the fundamental process subjectively. Contrast with functional requirement.
or transformation that the system’s software and hard- Sometimes referred to as design constraints.
ware components perform on inputs to produce out- software specification review (SSR): In software system en-
puts. Contrast with nonfunctional requirement. gineering, a joint acquirer–supplier review conducted
performance requirement: A system or software requirement to finalize software configuration item (SCI) require-
specifying a performance characteristic that a system/soft- ments so that the software developer can initiate the
ware system or system/software component must next step in the software development process. The SSR
possess—for example, speed, accuracy, and frequency. is conducted when SCI requirements have been suffi-
external interface requirement: A system or software ciently defined to evaluate the developer’s responsive-
requirement that specifies a hardware, software, or ness to and interpretation of the system- or segment-
database element with which a system/software level technical requirements. A successful SSR is
system or system/software component must inter- predicated on the developer’s determination that the
face, or that sets forth constraints on formats, tim- software requirements specification and interface speci-
ing, or other factors caused by such an interface. fications form a satisfactory basis for proceeding to the
design constraint (requirements): A software requirement preliminary design phase. [Military Std. 1521B-1985]
that impacts or constrains the design of a software sys- software design specification: A document that specifies
tem or software system component. Examples of de- the design of a system or component. Typical con-
sign constraints are physical requirements, perfor- tents include algorithms, system or component archi-
mance requirements, software development standards, tecture, control logic, data structures, I/O formats,
and software quality assurance (SQA) standards. and interface descriptions. Also called software de-
Richard H. Thayer ■

quality attribute (requirement): A requirement that sign description, internal specifications. Contrast with
specifies the degree of an attribute that affects the software requirements specification, external specifi-
quality that the system or software must possess— cations. [ANSI/IEEE Std. 610.12-1990]
for example, reliability, maintainability, or usability. software requirements phase: The software development
See also software quality attribute (requirement). lifecycle phase during which the requirements for a
requirements specification: In system/software engineer- software product, such as functional and performance
ing, a document that states the functions that software capabilities, are defined, documented, and reviewed.
must perform, the required level of performance requirements traceability: The identification and docu-
(speed, accuracy, and so on), the nature of the re- mentation of the derivation path (upward) and allo-
quired interfaces between the software product and cation/flow-down path (downward) of require-
its environment, the type and severity of constraints ments in the requirements hierarchy. See also
on design, and the quality of the final product. traceability.
—Continued on p. 88

May/June 2003 IEEE SOFTWARE 85


design
Editor: Martin Fowler ■ T h o u g h t Wo r k s ■ fowler@acm.org

Patterns

Martin Fowler

t should come as no surprise that I’m a faced with a design problem, you must be

I big fan of software patterns. After all, I


just finished my second book on the
subject, and you don’t put forth that
kind of effort without believing in what
you’re doing. Working on the book,
however, reminded me of many things about
software patterns that are not fully under-
stood, so this seemed like a good time to
talk about them.
able to focus on something as close to the
problem as you can get. It’s frustrating to find
an explanation of what I need to do buried in
a big example that contains 20 things that I
don’t care about but must understand to
complete the thing I do care about.
So for me an important problem is how
to talk about design issues in a relatively en-
capsulated way. Of course it’s impossible to
The biggest software patterns ignore all the inter-relationships, but I prefer
community is rooted in the object- to minimize them. Patterns can help by try-
oriented world. This community ing to identify common solutions to recur-
includes the people who wrote the ring problems. The solution is really what
classic Gang of Four book (E. the pattern is, yet the problem is a vital part
Gamma et al., Design Patterns, of the context. You can’t really understand
Addison-Wesley, 1995) and the the pattern without understanding the prob-
Hillside group that organized the lem, and the problem is essential to helping
worldwide PloP (Pattern Lan- people find a pattern when they need it.
guages of Programs) conferences Similarly, abstract discussions of princi-
(see http://hillside.net). Most pat- ples—which I often write about in this col-
terns books have come out of this commu- umn—are important, but people need help
nity—but not all. There are good books, such applying these principles to more concrete
as David Hay’s Data Model Patterns (Dorset problems.
House, 1996), written by people who’ve had When people write patterns, they typically
little or no contact with this group. write them in some standardized format—as
Even with the Hillside group, there’s a lot befits a reference. However, there’s no agree-
of disagreement about what’s important ment as to what sections are needed because
about patterns—and that mix of views every author has his or her own ideas. For
grows even larger with those who don’t get me, there are two vital components: the how
involved in the Hillside group’s efforts. So and the when. The how part is obvious—
there are many opinions on what makes a how do you implement the pattern? The
pattern important. Following are my views. when part often gets lost. One of the most
useful things I do when understanding a pat-
Why patterns interest me tern, one I’m either writing or reading, is ask,
Patterns provide a mechanism for render- “When would I not use this pattern?” Design
ing design advice in a reference format. Soft- is all about choices and trade-offs; conse-
ware design is a massive topic, and when quently, there usually isn’t one design ap-

2 IEEE SOFTWARE Published by the IEEE Computer Society 0740-7459/03/$17.00 © 2003 IEEE
DESIGN

proach that’s always the right one to whether they are appropriate for a expert in your field, you might rate
use. Any pattern should discuss alter- particular problem. A library can the quality of a patterns book based
natives and when to use them rather only implement the “how” part of a on how it helps you teach your col-
than the pattern you’re considering. pattern—you still have to answer the leagues rather than on what you
One of the hardest things to ex- “when.” In this case, the presence of learned from it.
plain is the relationship between pat- a library implementation alters the The other value of patterns to ex-
terns and examples. Most pattern de- trade-off. If a library implements a perts is as a standard vocabulary. In
scriptions include sample code solution that isn’t ideal, you can still the OO world, we can talk about sin-
examples, but it’s important to real- choose to use it rather than imple- gletons, strategies, decorators, and
ize that the code examples aren’t the ment the ideal one yourself. proxies, confident that a moderately
pattern. People considering building experienced designer will have a
patterns tools often miss this. Pat- Patterns and the expert good chance of understanding what
terns are more than macro expan- One of the hardest things about we mean without a lot of extra ex-
sions—every time you see a pattern patterns is that they are, by definition, planation. This vocabulary makes it
used, it looks a little different. I often nothing new. If you’ve been working easier to discuss our designs.
say that patterns are half-baked— in a field for a while and have become
meaning you always have to finish very skilled in it, then a patterns book Overuse
them yourself and adapt them to in that field shouldn’t teach you any- One of the things that can be a
your own environment. Indeed, im- thing new. Are patterns at all valuable problem is that people can think that
plementing a pattern yourself for a to experts? They obviously offer less patterns are unreservedly good and
particular purpose is one of the best value to experts than to someone that a test of a program’s quality is
ways to learn about it. coming to grips with the field, but how many patterns are in it. This
there is still something to be gained by leads to the apocryphal story of a
Patterns and libraries looking at patterns that merely cap- hello world application with three
This raises an interesting point—if ture what you already know. decorators, two strategies, and a sin-
a pattern is a common solution, why The primary value is that they can gleton in a pear tree. Patterns are not
not just embed it into libraries or a lan- help you teach those around you. For good or bad—rather, they’re either
guage? Then people wouldn’t need to me, the driving force behind writing appropriate or not for some situa-
know the pattern. Certainly, embed- comes from seeing that there’s tions. I don’t think it’s wrong to ex-
ding patterns into libraries is com- knowledge to be shared. An expert in periment with using a pattern when
mon—indeed, usually, it’s the other a team can use written patterns to you’re unsure, but you should be pre-
way around. Pattern authors see many help educate other team members. pared to rip it out if it doesn’t con-
libraries doing a similar thing and con- The expert can help the team review tribute enough.
sequently identify the pattern. This the general case, which will come
provides value in several ways. with simplified and encapsulated ex-
First of all, it can help people un- amples, but more importantly, he or don’t subscribe to the opinion that
derstand how the library feature
works to extract the library’s specific
context. A library typically combines
she can then show the team how the
patterns should or shouldn’t be used
in the project at hand. So if you’re an
I there are few remaining patterns to
gather. In both of my patterns
books, I felt I did little more than
many things at once, so again you scratch the surface. There is more
run into the problem of having to un- room for people to look at the sys-
derstand a dozen things. A well-writ- tems that were built and try to iden-
ten set of patterns can help explain tify and describe the patterns in-
these concepts. volved. This strikes me as an ideal
Second, people often move be- task for academia, although, sadly,
tween programming environments,
so they might be familiar with a par-
I often say that patterns the fact that patterns are by defini-
tion nothing new seems to make that
ticular solution but not how to im- are half-baked— impossible.
plement it in a new environment. Un- meaning you always As a field we have much to learn,
derstanding the underlying pattern which is why software development
behind library features helps a great
have to finish them is so much fun. But I think it’s frus-
deal in making this connection. yourself and adapt trating when we don’t take the time
Finally, even if a library imple- them to your own to learn from our own efforts
ments a pattern, you must still decide
how to use it. You might also need to environment. Martin Fowler is the chief scientist for ThoughtWorks, an
know more about what implementa- Internet systems delivery and consulting company. Contact him
tion strategies the library uses and at fowler@acm.org.

March/April 2003 IEEE SOFTWARE 3


design
Editor: Martin Fowler ■ T h o u g h t Wo r k s ■ fowler@acm.org

When to Make a Type


Martin Fowler

hen I started programming com- My favorite example is money. A lot of

W puters, I began with fairly primitive


languages, such as Fortran 4 and
various early flavors of Basic. One
of the first things you learn using
such languages—indeed, even us-
ing more up-to-date languages—is which
types your language supports. Being oriented
toward number crunching, Fortran supported
integer and real types, with the in-
computer horsepower is dedicated to manipu-
lating money, accounting, billing, trading, and
so forth—few things burn more cycles. Despite
all this attention, no mainstream language has
a built-in type for money. Such a type could re-
duce errors by being currency aware, helping
us, for example, avoid embarrassing moments
of adding our dollars to our yen. It can also
avoid more insidious rounding errors. It
teresting rule that any variable would not only remove the temptation to use
whose name started with the let- floats for money (never, ever do that) but also
ters I through N was an integer, help us deal with tricky problems such as how
and all other variables were floats. to split $10 equally between three people. In
I’m glad that convention hasn’t addition, it could simplify a lot of printing and
caught on, although Perl is close. parsing code. For more on this (why write the
Furthermore, using object-ori- column if I can’t plug my books?), see Patterns
ented languages, you can define of Enterprise Application Architecture (Addi-
your own types and in the best son-Wesley, 2002).
languages, they act just as well as The nice thing about OO programs is
built-in ones. that you can easily define a type like this if
the language and libraries don’t include it.
Defining types Other such low-level types I’ve often written
I first started playing with computers in are ranges, because I’m sick of writing if
my math classes, where we were all frustrated (x <= top && x >= bottom), quantities
by the fact that these oh-so-numerate com- (to handle things such as “6 feet”), and
puters didn’t understand fractions (and our dates (at least most languages include them
math teachers took a dim view of floating- now, but they are usually incorrect).
point approximations). I was thus delighted Once you start writing these kinds of fun-
to learn that Smalltalk supported fractions damental objects, you begin to ask yourself
naturally—if you divided 1 by 3 you got a where to stop. For example, one person re-
third, not some irritating long-running float. cently asked me whether he should make a
When people talk about design, they of- type for currency, even though the only data
ten don’t talk about little objects such as was the international three-letter code? An-
fractions, presumably because many archi- other person asked about a person class
tects consider such details unworthy of their with an age attribute and whether he should
attention. However, defining such types of- return an integer or define an age type and
ten makes life easier. return that.

12 IEEE SOFTWARE Published by the IEEE Computer Society 0740-7459/03/$19.00 © 2003 IEEE
DESIGN

When is it worth your while? stants. The value of this depends on


When should you make your own how widely people create the objects.
type? To begin with, make a type if it If creating an age only occurs in the
will have some special behavior in its person class, then there’s less value in
operations that the base type doesn’t
have. The attention to rounding in
making age a class than there would
be if ages were created all over the
How to
money offers a good example: rather
than have every user of a number
class remember to round, provide the
code base.
One of the interesting variations to
consider is system evolution. Today,
Reach Us
methods in a money class so you can an integral age might make sense, but Writers
program the rounding once. suppose in six months you need to For detailed information on submitting articles,
Special types are handy when you deal with someone’s age in years and write for our Editorial Guidelines (software@
have bits of data that often go to- months? Here you consider the effect computer.org) or access http://computer.org/
gether. A range object that brings to- of the type on refactoring to make the software/author.htm.
gether top and bottom values is a change. With your own type, chang-
good example. You might argue that ing the data structure is much easier, Letters to the Editor
if a.includes(x) isn’t much better just add an extra field to the age type. Send letters to
than if(x >= min && x <= max), If you return an integer, you have a
Editor, IEEE Software
but using a range communicates that more involved refactoring, but you
10662 Los Vaqueros Circle
the two values fit together. Indeed, can do it steadily in stages. First, keep
Los Alamitos, CA 90720
communication is one of the biggest the method that returns an integer,
software@computer.org
reasons to use a type. If you have a probably renaming it for clarity, and
method that expects to take a cur- provide a new method that returns the Please provide an email address or
rency parameter, you can communi- age type. That way, older code doesn’t daytime phone number with your letter.
cate this more clearly by having a have to change, but newer code can
currency type and using it in the use the new capability. Then, look at On the Web
method declaration. This is valuable all the uses of the integral age and, Access http://computer.org/software for
even if you don’t have static type over time, alter them to use ages information about IEEE Software.
checking, although such checking is rather than integers. This could take a
yet another reason to make a type. matter of minutes or months. Once Subscribe
Some types don’t want to use their you alter them all, you can remove the Visit http://computer.org/subscribe.
full capabilities. Often you’ll find integral age method.
things such as product codes that are Subscription Change of Address
numeric in form. However, even Send change-of-address requests for magazine
though they look like a number, they subscriptions to address.change@ieee.org.
don’t behave like one. Nobody needs Be sure to specify IEEE Software.
to do arithmetic on product codes— n the whole, I’m inclined to say
with a special type you can avoid
bugs, such as using someone’s per-
sonnel number in the arithmetic for
O that when in doubt, make a new
type. It usually requires little ef-
fort but often provides surprising re-
Membership Change of Address
Send change-of-address requests for IEEE
and Computer Society membership to
their paycheck. sults. For a currency, even if only a member.services@ieee.org.
That’s a common thing to watch three-letter string, I’d make the type
for. Even if a currency code looks like for communication reasons. For an Missing or Damaged Copies
a string, if it doesn’t behave like one, age returned by a person, I’d be more If you are missing an issue or you received
it should get a different type. Look at inclined to stick with the integer— a damaged copy, contact help@computer.org.
the string’s interface and ask how providing it wasn’t widely used and
much of it applies to a currency everyone treated it as a number.
Reprints of Articles
code? If most of it doesn’t, then that’s Refactoring from one type to another
For price information or to order reprints,
a good argument for a new type. isn’t a huge deal—particularly if you
send email to software@computer.org or fax
Validation constraints are another make the change as soon as you real-
+1 714 821 4010.
factor to consider. We might want to ize the type is going to be used
throw an exception if someone sets widely.
Reprint Permission
my age to –1 or 300. Some languages
To obtain permission to reprint an article,
have defined types purely on the ba-
contact William Hagen, IEEE Copyrights and
sis of ranges. Currencies often will
Martin Fowler is the chief scientist for ThoughtWorks, an Trademarks Manager, at whagen@ieee.org.
have a fixed list that can be defined Internet systems delivery and consulting company. Contact him
in terms of enums or symbolic con- at fowler@acm.org.

January/February 2003 IEEE SOFTWARE 13


design
Editor: Martin Fowler ■ T h o u g h t Wo r k s ■ fowler@acm.org

Using Metadata
Martin Fowler

occasionally come across people who tedious programming. This is when you

I describe their programming tasks as te-


dious, which is often the sign of a de-
sign problem. One common source of
tedium is pulling data from an external
source. You almost always do the same
thing with the data, but because the data
differs each time, it’s difficult to reduce such
should consider using metadata.
To illustrate the approach, consider a sim-
ple design problem: build a module that will
read data out of a simple file format into
memory. One example of this file is a tab-
delimited format with the first line containing
the names of the fields (see Table 1).

Explicit and implicit reads


class ExplicitReader...
public String FileName; Figure 1 offers perhaps the most
TextReader reader; straightforward approach to this
static char[] SEPARATOR = {‘\t’}; problem—reading each column of
data into a record structure. As a
public ExplicitReader (String fileName) {
program, it’s pretty simple, because
FileName = fileName;
} it’s easy to read and to write. Trou-
public IList ReadBatsmen() { ble rears, however, if you have a lot
IList result = new ArrayList(); of files to read. You have to write
reader = File.OpenText (FileName); this program for each file, which is
reader.ReadLine(); //skip header
a tedious job, and tedium usually
String line;
while ((line = reader.ReadLine()) != null) { has a bad smell—indicating worse
String[] items = line.Split(SEPARATOR); troubles. In this case, the trouble
Batsman bat = new Batsman(); would be duplication—always
bat.Name = items[0]; something worth avoiding.
bat.Matches = Int32.Parse(items[1]);
bat.Innings = Int32.Parse(items[2]);
bat.Runs = Int32.Parse(items[3]); Table 1
result.Add(bat);
} Actual listing 1
return result;
Name Matches Innings Runs
} DG Bradman 52 80 6,996
} RG Pollock 23 41 2,256
public class Batsman... GA Headley 22 40 2,190
public String Name; H Sutcliffe 54 84 4,555
public int Matches;
AC Gilchrist 31 44 2,160
public int Innings;
public int Runs; E Paynter 20 31 1,540
KF Barrington 82 131 6,806
ED Weekes 48 81 4,455
Figure 1. A simple, explicit solution for reading data from a tab-delimited WR Hammond 85 140 7,249
file.

0740-7459/02/$17.00 © 2002 IEEE November/December 2002 IEEE SOFTWARE 13


public class ImplicitReader... Figure 2. An implicit
public String FileName; design solution for
TextReader reader;
reading in data from
static char[] SEPARATOR = {‘\t’};
multiple files.
public ImplicitReader (String fileName) {
FileName = fileName;
}
public IList Read() {
IList result = new ArrayList();
reader = File.OpenText (FileName);
IList headers = parseHeaders();
String line;
while ((line = reader.ReadLine()) != null) {
result.Add(parseLine(headers, line));
}
return result;
}
IList parseHeaders() {
IList result = new ArrayList();
String[] items = reader.ReadLine().Split(SEPARATOR);
foreach (String s in items) result.Add(s);
return result;
}
IDictionary parseLine (IList headers, String line) {
String[] items = line.Split(SEPARATOR);
IDictionary result = new Hashtable();
for (int i = 0; i < headers.Count; i++)
result[headers[i]] = items[i];
return result;
}
abstract class AbstractReader {
public AbstractReader (String fileName);
FileName = fileName;
}
public String FileName;
protected TextReader reader;
protected static char[] SEPARATOR = {‘\t’};

public IList Read() {


IList result = new ArrayList();
reader = File.OpenText (FileName);
skipHeader();
String line;
while ((line = reader.ReadLine()) != null) {
String[] items = line.Split(SEPARATOR);
result.Add(doRead(items));
}
return result;
}
private void skipHeader() {
reader.ReadLine();
}
protected abstract Object doRead (String[] items);
}
class ExplicitReader2 : AbstractReader ...
public ExplicitReader2 (String fileName) : base (fileName){}
override protected Object doRead(String[] items) {
Batsman result = new Batsman();
result.Name = items[0];
result.Matches = Int32.Parse(items[1]);
Figure 3. An explicit de- result.Innings = Int32.Parse(items[2]);
sign that uses substitu- result.Runs = Int32.Parse(items[3]);
tion on the variable part return result;
}
of the program.

Figure 2 offers one approach to advantage is that this single program a hundred of these kinds of files to
avoiding this tedium, a generic way will read in any file, providing it fol- read, writing a single program like
to read in any data from a file. The lows the general format. If you have this takes a lot less effort than writ-

14 IEEE SOFTWARE November/December 2002


public class ReflectiveReader ...
public String FileName;
TextReader reader;
static char[] SEPARATOR = {‘\t’};
public Type ResultType;

public ReflectiveReader (String fileName, Type resultType) {


FileName = fileName;
ResultType = resultType;
}
public IList Read() {
IList result = new ArrayList();
reader = File.OpenText (FileName);
IList headers = parseHeaders();
String line;
while ((line = reader.ReadLine()) != null) {
result.Add(parseLine(headers, line));
}
return result;
}
IList parseHeaders() {
IList result = new ArrayList();
String[] items = reader.ReadLine().Split(SEPARATOR);
foreach (String s in items) result.Add(s);
return result;
}
Object parseLine (IList headers, String line) {
String[] items = line.Split(SEPARATOR);
Object result = createResultObject();
for (int i = 0; i < headers.Count; i++) {
FieldInfo field = ResultType.GetField((String)headers[i]);
if (field == null)
throw new Exception (“Unable to find field: “ + headers[i]);
field.SetValue(result, Convert.ChangeType(items[i],field.FieldType));
}
return result;
}
Object createResultObject() {
Type[] constructorParams = {};
return ResultType.GetConstructor(constructorParams).Invoke(null);
}
}

Figure 4. A reflective programming design.

ing an explicit program (as in Figure could just pass the block of assignment class’s metadata, we can also determine
1) for each file. statements in as a function argument. the types for the target class’s fields.
The problem with this generic style By parameterizing the assignment This lets us handle the type conversions
is that it produces a dictionary, which is statements, you can reduce duplica- properly.
easy to access (especially when your tion. You can also reduce—but not
language supports a simple index mech- eliminate—the tedium. All those as- Two ways of using the
anism as C# does) but is not explicit. signments still must be written, both metadata
Consequently, you can’t just look at a for reading and writing (if you are sup- We can use the metadata in two
file declaration to discover the possible porting both). However, by taking ad- ways: reflective programming and code
fields you must deal with, as you can vantage of the metadata in both the generation. The reflective program-
with the Batsmen class in Figure 1. Fur- target class and file structure, you can ming approach leads us to a program
thermore, you lose all type information. avoid writing any assignments at all. that uses reflection at runtime to set
So, how can you have your explicit The metadata is available in two field values in the target class (see Fig-
cake while eating only a small amount forms. The field heading at the top of ure 4). Many modern platforms pro-
of code? One approach is to parame- the data file is a simple metadata that vide this kind of runtime reflection.
terize the assignment statements from supplies the field names (XML tag The resulting reader class can read any
Figure 1 by enclosing them in a single names give the same information). If file that conforms to the format and
substitutable function. Figure 3 does the target class’s fields match the data has a matching target class.
this with the object-oriented style of an file’s names (or if we can make them The code generation style aims to
abstract superclass. In a more sophisti- match), we have enough to infer the as- generate a class that’s similar to the
cated programming language, you signments. If we can query the target hand-written one in Figure 3. We can

November/December 2002 IEEE SOFTWARE 15


public class ReaderGenerator ...
String DataFileName;
Type Target;
String ClassName;
TextWriter output;
public void Run() {
Console.WriteLine(output);
output = new StringWriter();
writeClassHeader();
writeConstructor();
writeDoRun();
writeClassFooter();
Console.WriteLine(output);
writeOutputFile();
}
void writeClassHeader() {
output.WriteLine(“using System;”);
output.WriteLine(“namespace metadata”);
output.WriteLine(“{“);
output.WriteLine(String.Format(“class {0} : AbstractReader “, ClassName));
output.WriteLine(“{“);
}
void writeClassFooter() {
output.WriteLine(“}”);
output.WriteLine(“}”);
}
void writeConstructor() {
output.Write(String.Format
(“\t public {0} () : base (\”{1}\”)”, ClassName, DataFileName));
output.WriteLine(“{}”);
}
static char[] SEPARATOR = {‘\t’};
void writeDoRun() {
output.WriteLine(“\toverride protected Object doRead(String[] items) {“);
output.WriteLine(String.Format (“\t\t{0} result = new {0}();”, Target));
writeFieldAssignments();
output.WriteLine(“\t\treturn result;”);
output.WriteLine(“\t}”);
}
void writeFieldAssignments() {
TextReader dataReader = File.OpenText (DataFileName);
String[] headers = dataReader.ReadLine().Split(SEPARATOR);
dataReader.Close();
for (int i = 0; i < headers.Length; i++) {
FieldInfo field = Target.GetField((String)headers[i]);
if (field == null)
throw new Exception (“Unknown Field: “ + headers[i]);
output.WriteLine(String.Format(
“\t\t result.{0} = ({1})Convert.ChangeType(“,
headers[i], field.FieldType));
output.WriteLine(String.Format(
“\t\t\titems[{0}],typeof({1}) );”,
i, field.FieldType));
}
}
void writeOutputFile() {
StreamWriter outFile = new StreamWriter(File.Create(ClassName + “.cs”));
outFile.Write(output);
outFile.Close();
}
}

Figure 5. A generator.

use the style presented in Figure 1, be- ure 6 shows the resulting class. Al- languages often make good languages
cause we don’t have to worry about though I’m using the same language in for generation due to their powerful
duplication in the generated code. Fig- this case, there’s no reason why the string handling.
ure 5 shows the kind of class we could generator must be the same language The generator also uses the lan-
use to perform the generation, and Fig- as the class it’s generating—scripting guage’s reflection capabilities to deter-

16 IEEE SOFTWARE November/December 2002


Figure 6. Example using System;
code that Figure 5 namespace metadata
{
generated. class ExplicitReader3 : AbstractReader
{
public ExplicitReader3 () : base (“batsmen.txt”){}
mine the field types; how- override protected Object doRead(String[] items) {
ever, it does it at compile metadata.Batsman result = new metadata.Batsman();
result.Name = (System.String)Convert.ChangeType(
time rather than at runtime. items[0],typeof(System.String) );
The generated classes don’t result.Matches = (System.Int32)Convert.ChangeType(
use the language’s reflection items[1],typeof(System.Int32) );
capabilities. result.Innings = (System.Int32)Convert.ChangeType(
Given these two styles of items[2],typeof(System.Int32) );
result.Runs = (System.Int32)Convert.ChangeType(
metadata-based programs, items[3],typeof(System.Int32) );
the obvious question is return result;
when to use each style. The }
reflective program offers a }
single compact class to }
carry out the mapping.
There are, however, some disadvan- tion is done with every significant wouldn’t bother for a few classes. I’d
tages. Many people find reflection change—the best way of doing this is just use a technique to separate the
somewhat hard to use, and it might to make it part of an automated build varying code from the constant code.
defeat some of your environment’s process. With many files, generation I can’t give a hard number for when
tooling, such as intelligent reference might lead to a larger code bulk, which it’s better to use metadata—it’s more
searches and automated refactorings. might affect footprint and build times. a reflection of the degree to which the
In addition, in some environments, re- I usually prefer generation to reflective assignment’s monotony is affecting
flective calls can be significantly programs, but you have to weigh your development.
slower than direct method calls. decision based on your concerns.
Generation also has its problems.
You need discipline to ensure that de- here’s also the question of whether
velopers don’t hand-edit the generated
files. You must also ensure that genera- T to use metadata-based techniques
at all. For something like this, I
Martin Fowler is the chief scientist for ThoughtWorks, an
Internet systems delivery and consulting company. Contact him
at fowler@acm.org.
design
Editor: Martin Fowler ■ T h o u g h t Wo r k s ■ fowler@acm.org

How .NET’s Custom


Attributes Affect Design
James Newkirk and Alexei A. Vorontsov

n its first release of the .NET Frame- rializable, then it must implement the inter-

I work, Microsoft has provided a de-


fined method for adding declarative in-
formation (metadata) to runtime enti-
ties in the platform. These entities in-
clude classes, methods, properties, and
instance or class variables. Using .NET, you
can also add declarative information to the
assembly, which is a unit of deployment that
is conceptually similar to a .dll or .exe file.
face as follows:

public class
Serializable
MyClass implements

Serialization might have certain behav-


iors associated with it that the class devel-
oper wants to control. However, Java doesn’t
explicitly associate such behavior with the
An assembly includes attributes that de- interface that represents the serialization
scribe its identity (name, version, and cul- contract. At runtime, when the program
ture), informational attributes that provide tells the JVM to serialize this class, it looks
additional product or company informa- to see if the class has implemented the inter-
tion, manifest attributes that describe con- face. It also looks to see if the class has de-
figuration information, and strong name at- fined any special methods associated with
tributes that describe whether the assembly the serializable interface but not directly de-
is signed using public key encryption. The clared in it, such as readResolve, read-
program can retrieve this metadata at run- Object, or writeObject.
time to control how the program interacts The JVM relies on a naming convention
with services such as serialization and secu- and method signatures to locate the methods
rity. Here, we compare design decisions via reflection; if it finds them, it invokes
made using custom attributes in .NET with them. The interface itself does not specify
the Java platform. any methods, because implementors might
then unnecessarily implement methods in the
Marker interfaces simplest case. Because the interface doesn’t
In the Java platform there is a common explicitly specify the methods used to control
design trick called marker interfaces. A the process and thus might incorrectly spec-
marker interface has no methods or fields ify the method signature, this mechanism is
and serves only to identify to the Java Vir- prone to failure. Unfortunately, no compile
tual Machine (JVM) a particular class at- time check will identify this as an error.
tribute. Here is one example: .NET solves this problem by being ex-
plicit. In the simplest case, where the pro-
public interface Serializable {} grammer wants to rely on the provided ca-
pability to serialize an object, there is a
If the class that you are writing must be se- class-level attribute called Serializable

18 IEEE SOFTWARE September/October 2002 0740-7459/02/$17.00 © 2002 IEEE


DESIGN

that marks a class as having that ca- gram finds and calls
pability. For example, testSuccess. [Serializable()]
The code in Figure public class MyClass : ISerializable
[Serializable()] 2b demonstrates a {
public class MyClass {} common design id- public MyClass(
iom used in JUnit SerializationInfo info,
Marking a class serializable implies when the program- StreamingContext context)
nothing else. If the programmer mer wants to verify {
wants to completely control the seri- that the code throws // ...
alization process, then he or she must an exception. Unfor- }
also implement an interface called tunately, the pro- public void GetObjectData(
ISerializable, specifying the meth- grammer will dupli- SerializationInfo info,
ods used to control serialization (see cate such code in StreamingContext context)
Figure 1). At runtime, when the pro- every test case that {
gram tells the Common Language expects an exception, // ...
Runtime to serialize a class, the CLR and the idiom is not }
looks to see if the class was marked as intuitive as you }
with SerializableAttribute. might expect.
The Java and .NET approaches Having the testing
are similar in intent, but .NET’s use framework support Figure 1. Implementing the ISerializable
of attributes is more explicit. Con- such a common case interface, which specifies the methods for
trary to an interface’s basic purpose, directly would be controlling serialization.
the marker interface reuses an exist- nice. However, rely-
ing language construct interface to ing on the naming convention could rivative of JUnit, supports all lan-
represent what the attribute repre- lead to some variation of the code in guages in the .NET framework and
sents. According to the Java Lan- Figure 2c. In this case, we use a nam- uses attributes at the class and
guage Specification (2nd ed., Addi- ing convention to specify not only a method levels. The class attribute is
son-Wesley, 2000), test method but also additional infor- called TestFixture; it tells the pro-
mation about how to interpret the gram that runs the tests to look for
An interface declaration intro- test result. We expect that this test methods in this class. A Test at-
duces a new reference type whose method’s execution will throw MyEx- tribute then identifies test methods.
members are classes, interfaces, ception. This example might seem This overall solution makes for a
constants and abstract methods. somewhat ridiculous, but it demon- more consistent approach.
This type has no implementation, strates the limitations of naming con- In addition, this solution is more
but otherwise unrelated classes can ventions, because of how much infor- extensible because more than one at-
implement it by providing imple- mation the name itself can convey. In tribute can be associated with a
mentations for its abstract methods. fact, JUnit doesn’t implement the method, and attributes can have ad-
functionality to check boundry condi- ditional data. For example, Nunit
tions in this way. Other approaches has another attribute defined for a
Stylistic naming patterns used in Java (such as JavaDoc tags) method that expects an exception.
At the method level, it is common in can provide additional information. This leaves the name not only unen-
the Java platform to use naming con- However, they are not present at run- cumbered by the context in which it
ventions to identify a special method. By time and usually require preprocess- is run but also more relevant to what
virtue of the name, the program finds ing the code to identify and process is being tested (see Figure 3b).
the method at runtime using reflection. the tags.
Once found, the executing program spe- In .NET, stylistic naming patterns
cially interprets this method. For exam- are not needed because, in addition
ple, when a programmer defines to attributes that the Framework ttributes in .NET provide an ele-
a test method in JUnit—a popular unit-
testing framework for Java (www.
junit.org)—the first four letters of a test
specifies, a programmer can create
custom attributes that are defined A gant, consistent approach to
adding declarative information to
and used in the same way. These at- runtime entities. Because the runtime
method must be test (see Figure 2a). tributes are not just names but are entities interact with the supporting
The program that executes the tests first instances of classes that might have services via declarative information,
verifies that the class inherits from additional data. Figure 3a shows a the set of services and supporting at-
TestCase. Then, using reflection, it similar test class defined with Nunit tributes does not have to be closed.
looks for any methods that start with (www.nunit.org), a unit testing tool By providing a standard mechanism
Test. In the code in Figure 2a, the pro- for the .NET platform. Nunit, a de- to extend built-in metadata with cus-

September/October 2002 IEEE SOFTWARE 19


DESIGN

tom attributes, .NET lets program-


public class MyClass extends TestCase mers develop applications that can
{ interact with services not yet defined
public void testSuccess() or supported by CLR. In fact, Nunit
{ /* ... */ } version 2.0 was written with custom
} attributes and provides much of the
(a) flexibility we’ve demonstrated here.
In contrast, the most common ad
public class MyClass extends TestCase hoc mechanisms in Java to add de-
{ clarative information include marker
public void testMyException()
interfaces, stylistic naming patterns,
{
and JavaDoc tags. These inconsis-
try {
/* code that throws exception */ tently solve the problem of adding
fail(“Code should have thrown MyException”); declarative information to runtime
} entities. They are also error prone
catch(MyException e) and too simplistic for today’s appli-
{ /* expected exception — success */ } cations. The Java community recog-
} nizes this limitation and has started
} working on JSR-175 (see www.jcp.
(b) org/jsr/detail/175.jsp), which speci-
fies a similar facility for Java that is
public class MyClass extends TestCase
already in .NET.
{
public void testSuccess_ExpectException_MyException()
James Newkirk is a software project manager for
{ /* ... */ } Thoughtworks. He has been working with the .NET Framework
} since its introduction in the summer of 2000. Contact him at
jim@nunit.org.
(c)

Alexei A. Vorontsov is a software technical lead for


Figure 2. (a) A test method in JUnit (the method’s first four letters Thoughtworks. He has worked on an enterprise transforming
application for the past three years. Contact him at alexei@
must be test); (b) a test for the boundary conditions that verify that nunit.org.
an exception is thrown when expected; (c) a naming convention to
specify not only a test method but also some additional information
about how to interpret the test result. IEEE

[TestFixture]
public class MyClass
{
[Test]
public void Success() FUTURE TOPICS:
{ /* ... */ }
} The Business of
(a)
Visit us
Software Engineering
[TestFixture]
public class MyClass onInspections
Software the
{
[Test]
[ExpectedException(typeof(MyException))]
web
Usability
public void Success() Internationalization
{ /* would throw my exception */ }
}
(b)

Figure 3. A test class (a) defined with Nunit and (b) with another
attribute defined for a method that expects an exception.

20 IEEE SOFTWARE September/October 2002 http://computer.org/software


design
Editor: Martin Fowler ■ T h o u g h t Wo r k s ■ fowler@acm.org

Yet Another Optimization


Article
Martin Fowler

his is a troubling column to write. I Steps for optimization

T hadn’t planned to write on optimiza-


tion, because what I have to say has
already been said numerous times.
Yet, when I give talks, I find there’s
still a surprising number of people
who don’t know, or at least don’t follow, the
advice I’m about to give. So, here goes.
(Many of you have probably seen this ad-
vice before—my thought to you
Optimizing an existing program follows
a specific set of steps. First, you need a pro-
filer—a program that can analyze how
much time your program spends in its var-
ious parts. Software performance has an
80/20 rule: 80 percent of the program’s
time is spent on about 20 percent of the
code. Trying to optimize performance in
the 80 percent of code is futile, so the first
is to ponder why I need to say order of business is to find that 20 percent
this again.) of code. Trying to deduce where the pro-
First, performance matters. Al- gram will spend its time is also futile. I
though relying on Moore’s law to know plenty of experienced programmers
get us out of slow programs has who always get this wrong. You have to
its merits, I find it increasingly an- use a profiler.
noying when I get a new version To give the profiler something to chew on,
of a program and must upgrade perform some kind of automated run that
my hardware for it to work ac- reasonably simulates the program under its
ceptably. The question is, “How usual conditions. An automated test suite is a
do we achieve a fast program?” good starting point, but make sure you simu-
For many programmers, performance is late the actual conditions. My colleague Dave
something you pay continuous attention to Rice has a rule: “Never optimize a multiuser
as you program. Every time you write a system with single-user tests.” Experience has
fragment of code, you consider the perfor- taught us that a multiuser database system
mance implications and code the program to has very different bottlenecks than a single
maximize performance. This is an obvious user system—often focused around transac-
technique—pity it works so badly. tion interactions. The wrong set of tests can
Performance is not something you can easily lead you to the wrong 20 percent of
work on in this way. It involves specific dis- code.
cipline. Some performance work comes Once you’ve found your bottlenecks,
from architectural decisions, some from a you have two choices: speed up the slow
more tactical optimization activity. But things or do the slow things less often. In ei-
what both share is the fact that it is diffi- ther case, you must change the software.
cult to make decisions about performance This is where having a well-designed piece
from just looking at the design. Rather, you of software really helps. It’s much easier to
have to actually run the code and measure optimize cohesive, loosely coupled mod-
performance. ules. Breaking down a system into many

20 IEEE SOFTWARE May/June 2002 0740-7459/02/$17.00 © 2002 IEEE


DESIGN

small pieces lets you narrow down Some exceptions Some have taken this further, com-
the bottlenecks. Having a good auto- Although most performance issues ing up with performance models that
mated test suite makes it easier to are best dealt with in these kinds of you can use to assess different archi-
spot bugs that might slip in during optimizations, at times other forms tectural designs. Although this can be
optimization. of thinking are important—for ex- handy, it’s difficult to take it too far.
It’s worth knowing about various ample, during early architectural It all depends on how good the per-
optimization tricks, many of which stages, when you’re making decisions formance model is, and people usu-
are particular to specific languages that will be costly to reverse later. ally cannot predict the key factors,
and environments. The most impor- Again, the only way to really under- even at a broad level. Again, the only
tant thing to remember is that the stand these performance issues is to real arbiter is measurement.
tricks are not guaranteed to work—as use measurements. In this case, you In the end, however, performance
the saying goes, “Measure twice, cut build exploratory prototypes to per- is not an absolute. Getting a program
once.” Unlike a tailor, however, you form crude simulations of the envi- to run faster costs money, and it’s a
measure before and after you’ve ap- ronments with which you’re going to business decision whether to invest in
plied the optimization. Only then do work and to get a sense of the rela- a quicker program. One value of an
you know if it’s had any effect. It’s re- tive speeds. It’s tricky, of course, to explicit optimization phase is that
vealing how often an optimization has get a good idea of what the actual en- the cost of getting fast performance is
little—or even a negative—effect. If vironment might be, but then it’s more explicit, so businesses can trade
you make an optimization and don’t likely that everything you’re working it against time to market or more fea-
measure to confirm the performance with will be upgraded before you go tures. Much of the reason why I
increase, all you know for certain is live anyway. Experiments are still curse at slow software is because it
that you’ve made your code harder to much better than wild guesses. makes good business sense for the
read. There are also some cases where builder.
This double measurement is all the there are broad rules about slow
more important these days. With opti- things. An example I always come
mizing compilers and smart virtual across is the slowness of remote pro-
machines, many of the standard opti- cedure calls. Because remote calls are
mizing techniques are not just ineffec- orders of magnitude slower than in-
tive but also counterintuitive. Craig process calls, it’s important to mini-
Larman really brought this home mize them, which greatly affects
when he told me about some com- overall design. However, this doesn’t s I’ve said, much of this advice—
ments he received after a talk at
JavaOne about optimization in Java.
One builder of an optimizing virtual
trump measuring. I once came across
a situation where people optimize re-
mote methods only to find their bot-
A in particular, the advice to write a
good clean program first and op-
timize it later—is well worn. (For a
machine said, in effect, “The com- tlenecks were elsewhere. However, longer description of this approach,
ments about thread pools were good, minimizing remote calls has proven read Chapters 28 and 29 of Steve
but you shouldn’t use object pools be- to be a solid rule of thumb. McConnell’s Code Complete, Mi-
cause they will slow down our VM.” crosoft Press, 1993.) Good quotes
Then another VM builder said, “The about the perils of premature opti-
comments about object pools were mization have been around for over
good, but you shouldn’t use thread 20 years. The pity is that some peo-
pools because they slow down our ple still object when I call the same
VM.” Not only does this reinforce the query method twice in a routine. For
need to measure with every optimiza- everyone who finds nothing new in
tion change, it also suggests that you If you make an this column, there exists another
should log every change made for op-
timization (a comment tag in the
optimization and challenge—how to make it so there is
no need to rewrite it in 10 years.
source code is a good option) and don’t measure to
retest your optimizations after up- confirm the performance
grading your compiler or VM. The
optimization you did six months ago
increase, all you know
could be your bottleneck today. for certain is that
All of this reinforces the key rule you’ve made your code
that first you need to make you pro-
gram clear, well factored, and nicely harder to read. Martin Fowler is the chief scientist for ThoughtWorks, an In-
modular. Only when you’ve done ternet systems delivery and consulting company. Contact him at
that should you optimize. fowler@acm.org.

May/June 2002 IEEE SOFTWARE 21


design
Editor: Martin Fowler ■ T h o u g h t Wo r k s ■ fowler@acm.org

Public versus Published


Interfaces
Martin Fowler

ne of the growing trends in software though the method might be used anywhere,

O design is separating interface from im-


plementation. The principle is about
separating modules into public and
private parts so that you can change
the private part without coordinating
with other modules. However, there is a fur-
ther distinction—the one between public and
published interfaces. This distinction is im-
portant because it affects how you
I can easily find the users with a search tool.
If I have one of the new breeds of refactor-
ing tools (see www.refactoring.com for de-
tails) available for Java, I can do it with a
simple menu click—the tool will then auto-
matically update all the callers. So, changing
a public method isn’t a big deal.
However, things rapidly change if I put
that software out on the Web as a compo-
work with the interface. nent, and other people, whom I don’t know,
start building applications on top of it. If I
Public versus published now delete the parameter, everybody else’s
Let’s assume I’m writing an ap- code will break when I upgrade. Now I must
plication in a modern modular do something a little more elaborate. I can
language—to make things more produce the new method with one less para-
concrete, let’s assume this lan- meter but keep the old method—probably
guage is Java. My application thus recoding the old method to call the new one.
consists of several classes (and in- I mark the old method as deprecated, assum-
terfaces), each of which has a pub- ing people will move the code over and that
lic interface. This public interface I can change it in the next release or two.
of a class defines a group of methods that any The two cases are quite different, yet
other class in the system can invoke. there’s nothing in the Java language to tell
While I’m enhancing a public method, I re- the difference—a gap that’s also present in a
alize that one of its parameters is redundant— few other languages. Yet there’s something
I don’t need to use it in the method (maybe I to be said for the public–published distinc-
can get that value through some other route tion being more important than the more
or maybe I just don’t need it anymore). At this common public–private distinction.
point, I can eliminate that value from the The key difference is being able to find
method signature, clarifying the method and and change the code that uses an interface.
potentially saving work for its callers. Because For a published interface, this isn’t possible,
this method is public, any class in the system so you need a more elaborate interface
can call it. Should I remove the parameter? update process. Interface users are either
In this case, I would argue yes, because callers or are classes that subclass or imple-
there are benefits and it isn’t difficult. Al- ment an interface.

18 IEEE SOFTWARE March/April 2002 0740-7459/02/$17.00 © 2002 IEEE


DESIGN

Advice on publishing Publish as little as you can as late as ter from a method, instead of chang-
Recognizing the difference be- you can ing the method, try adding a new
tween public and published leads to Because publishing locks you into method without the parameter. That
an important set of consequences. the slower cycle of changes, limit way, you get an addition rather than a
how much you publish. This is where general alteration, and your clients re-
Don’t treat interfaces as published a language’s inability to distinguish main compatible.
unless they are between public and published be- Additions can still cause prob-
If you need to change an interface comes an issue. The best you can do lems if outside groups have their
and can find and change all users, is declare some modules to be the in- own implementation of your inter-
then don’t bother going through all terface and then counsel your soft- face. If that happens, even adding a
the forwarding and deprecation gam- ware users not to use the other mod- method breaks the alternative im-
bits. Just make the change and up- ules, even if they can see them. Keep plementation. Thus, some compo-
date the users. these interfaces as thin as you can. nent technologies, such as COM,
Publish as late as possible in the de- use immutable interfaces. With an
Don’t publish interfaces inside a team velopment cycle to give yourself time immutable interface, once it’s pub-
I once suggested to somebody to refine the interfaces. One strategy lished, you guarantee not to change
that we change a public method, is to work closely with one or two it. If you want to change the inter-
and he objected because of the prob- users of your components—users face, you must create a second inter-
lems caused by its being published. who are friendly enough to cope with face, and components can then sup-
The real problem was that although sharp interface changes—before you port this interface at their leisure.
there were only three people on the publish to the masses. It’s not the ideal scheme, but it cer-
team, each developer treated his in- tainly has its merits.
terfaces as published to the other Try to make your changes additions
two. This is because the team used a In addition to distinguishing be-
strong form of code ownership in tween published and public interfaces,
which each module was assigned to we can also identify two types of in-
a single programmer and only that terface changes. Generally, changes
programmer could change the mod- can alter any aspect of an interface.
ule’s code. I’m sympathetic to code However, there are some changes that would like to see the public–
ownership—it encourages people to
monitor their code’s quality—but a
strong code ownership model such
only cause additions to an interface,
such as adding a method. Additions
won’t break any of the interface’s
I published distinction appear more
in languages and platforms. It’s
also interesting that environments
as this one causes problems by forc- clients—existing clients have no prob- don’t tend to provide the facilities to
ing you to treat interperson inter- lem using the old methods. Conse- evolve interfaces. Some can deprecate
faces as published. quently, when you make a change, it’s a method that’s due to be removed:
I encourage a weaker ownership worth considering whether you can Eiffel does this as part of the lan-
model in which one person is re- recast it into an addition. For exam- guage, and Java does it (but as part
sponsible for the module but other ple, if you need to remove a parame- of the built-in documentation). I
people can make changes when nec- haven’t seen anyone add a marker to
essary. This lets other developers do a method that warns implementers of
things such as alter calls to changed something that’s going to be added
methods. (You can also use collec- or would let you add something to an
tive code ownership—where anyone interface in a provisional way.
can change anything—to avoid in- That’s part of a more general issue
ternal publishing.) This kind of There’s something in software platforms. So far, plat-
ownership usually requires a config-
uration management system that
to be said for the forms haven’t sufficiently understood
that software is supposed to be soft
supports concurrent writers (such as public–published and thus needs facilities that allow
CVS) rather than one that uses pes- distinction being change. In recent years, we’ve taken
simistic locking. more steps in this direction with
There is a limit to how big a team
more important than component-packaging systems, but
you can run without some form of the more common these are just the early steps.
internal publishing, but I would err public–private
on the side of too little publishing. In
other words, assume you don’t need distinction. Martin Fowler is the chief scientist for ThoughtWorks, an
to publish interfaces, and then adjust Internet systems delivery and consulting company. Contact him
if you find this causes problems. at fowler@acm.org.

March/April 2002 IEEE SOFTWARE 19


design
Editor: Martin Fowler ■ T h o u g h t Wo r k s ■ fowler@acm.org

Avoiding Repetition
Martin Fowler

oftware design is not easy—not easy and removing repetition can lead to many

S to do, teach, or evaluate. Much of


software education these days is
about products and APIs, yet much
of these are transient, whereas good
design is eternal—if only we could
figure out what good design is.

Searching for design principles


One of the best ways to capture and pro-
interesting consequences. I have an increas-
ing sense that a pig-headed determination to
remove all repetition can lead you a long
way toward a good design and can help you
apply and understand the patterns that are
common in good designs.

A simple case: subroutine calls


Take a simple example: subroutine calls.
mulgate good design is to learn You use a subroutine when you realize that
from the patterns community. two blocks of code, in different places, are
Their work, especially the famous or will be the same. You define a subroutine
book Design Patterns (E. Gamma and call it from both places. So, if you
et al., Addison Wesley, Reading, change what you need to, you don’t have to
Mass., 1994), has become a cor- hunt down multiple repetitions to make the
nerstone for many designers of change. Granted, sometimes the duplication
object-oriented software. Pat- is just a coincidence, so you wouldn’t want
terns are not easy to understand, a change in one to affect the other—but I
but they reward the effort of find that is rare and easy to spot.
study. We can learn from the spe- So what if the blocks are similar but not
cific solutions they convey and identical? Maybe some data is different in
from the thinking process that leads to their the two cases. In that case, the answer is ob-
development. The thinking process is hard to vious: you parameterize the data by passing
grasp, but understanding it helps us discover in arguments to a subroutine. One block of
principles that often generate these patterns. code that multiplies by five and another
Over the last year, I’ve been struck by one that multiplies by 10 become one block that
of the underlying principles that leads to multiplies by x, and you replace x with the
better designs: remove duplication. It’s also right number.
been highlighted by mantras in a couple of That’s a simple resolution but it illus-
recent books: the DRY (don’t repeat your- trates a basic principle that carries over into
self) principle in the Pragmatic Programmer more complicated cases. Identify what is
(A. Hunt, and D. Thomas, Addison Wesley, common and what varies, find a way to iso-
1999) and “Once and Only Once” from Ex- late the common stuff from the variations,
treme Programming Explained: Embrace then remove the redundancy in the common
Change (K. Beck, Addison Wesley, 1999). stuff. In this case, separating the commonal-
The principle is simple: say anything in ity and the variability is easy. Many times it
your program only once. Stated blandly like seems impossible, but the effort of trying
that, it hardly bears saying. Yet identifying leads to good design.

January/February 2001 IEEE SOFTWARE 97


DEPT
DESIGN
TITLE

What’s the same and what’s


class Invoice...
different?
What if two routines have the String asciiStatement() {
same basic flow of behavior but dif- StringBuffer result = new StringBuffer();
fer in the actual steps (see Figure 1)? result.append(“Bill for “ + customer + “\n”);
These two routines are similar, but Iterator it = items.iterator();
not the same. So, what is the same while(it.hasNext()) {
and what is different? LineItem each = (LineItem) it.next();
The sameness is the routine’s over- result.append(“\t” + each.product() + “\t\t”
all structure, and the differences are in + each.amount() + “\n”);
}
the steps. In both cases, the structure is
result.append(“total owed:” + total + “\n”);
return result.toString();
■ print some header for the invoice, }
■ loop through each item printing a
line, and
■ print a footer for the invoice. String htmlStatement() {
StringBuffer result = new StringBuffer();
As Figure 2 shows, we can separate result.append(“<P>Bill for <I>” + customer + “</I></P>”);
the two by coming up with some kind result.append(“<table>”);
of printer notion with a common in- Iterator it = items.iterator();
terface for header, footer, and lines while(it.hasNext()) {
LineItem each = (LineItem) it.next();
and an implementation for the ASCII
result.append(“<tr><td>” + each.product()
case. Figure 3a shows that the com-
+ “</td><td>” + each.amount() + “</td></tr>”);
mon part is then the looping structure, }
so we can wire the pieces together as result.append(“</table>”);
shown in Figure 3b. result.append(“<P> total owed:<B>” + total + “</B></P>”);
There’s nothing earth-shattering return result.toString();
about this solution; just apply a poly- }
morphic interface—which is common
to any OO or component-based envi-
Figure 1. Two similar routines with different steps.
ronment that lets you easily plug in
multiple implementations of a com-
mon interface. Design Patterns
junkies will recognize the Template
interface Printer {
Method pattern. If you are a good de-
String header(Invoice iv);
signer and are familiar with polymor- String item(LineItem line);
phic interfaces, you could probably String footer(Invoice iv);
come up with this yourself—as many }
did. Knowing the pattern just gets
(a)
you there quicker. The point is, the
desire to eliminate duplication can static class AsciiPrinter implements Printer {
lead you to this solution. public String header(Invoice iv) {
return “Bill for “ + iv.customer + “\n”;
Duplication and patterns }
Thinking in terms of duplication public String item(LineItem line) {
and its problems also helps you un- return “\t” + line.product()+ “\t\t” + line.amount() + “\n”;
derstand the benefits of patterns. }
Framework folks like patterns be- public String footer(Invoice iv) {
cause they easily let you define new return “total owed:” + iv.total + “\n”;
pluggable behaviors to fit behind the }
}
interface. Eliminating duplication
helps because as you write a new im- (b)
plementation, you don’t have to
worry about the common things that
need to be. Any common behavior Figure 2. (a) A common interface for header, footer, and lines and
should be in the template method. (b) an implementation for the ASCII case (try the HTML case as an
This lets you concentrate on the new exercise on your own).

98 IEEE SOFTWARE January/February 2001


DESIGN

class Invoice...
public String statement(Printer pr) {
StringBuffer result = new StringBuffer();
result.append(pr.header(this));
Iterator it = items.iterator();
while(it.hasNext()) { How to
Reach Us
LineItem each = (LineItem) it.next();
result.append(pr.item(each));
}
result.append(pr.footer(this));
return result.toString();
}
Writers
For detailed information on submitting articles,
(a) write for our Editorial Guidelines (software@
computer.org), or access computer.org/
class Invoice... software/author.htm.
public String asciiStatement2() {
return statement (new AsciiPrinter()); Letters to the Editor
} Send letters to
(b) Letters Editor
IEEE Software
Figure 3. (a) The common part of the routine and (b) the pieces
10662 Los Vaqueros Circle
wired together.
Los Alamitos, CA 90720
dstrok@computer.org
Please provide an e-mail address or
behavior rather than the old. structures, you are more likely to daytime phone number with your letter.
The principle of duplication also spot any duplication in the routines.
helps you think about when to apply Much of the reason why objects are On the Web
this pattern. As many people know, popular is because of this kind of so- Access computer.org/software for information
one of the problems with people who cial effect, which works well when about IEEE Software.
have just read a pattern is that they reinforced by a culture that encour-
insist on using it, which often leads to ages people to look around and fix Subscription Change of Address
more complicated designs. When you duplications when they do arise. Send change-of-address requests for magazine
insist on using a pattern, ask, “What subscriptions to address.change@ieee.org.
repetition is this removing?” Remov- Be sure to specify IEEE Software.
ing repetition makes it more likely o, avoiding repetition is a simple
that you’re making good use of the
pattern. If not, perhaps you shouldn’t
use it.
S principle that leads to good de-
sign. I intend to use this column
to explore other simple principles
Membership Change of Address
Send change-of-address requests for the mem-
bership directory to directory.updates@
computer.org.
Often, the hard part of eliminat- that have this effect. Have you no-
ing duplication is spotting it in the ticed simple principles like this in
first place. In my example, you can your work? If so, please contact Missing or Damaged Copies
spot the two routines easily because me—I’m always happy to repeat If you are missing an issue or you received
they are in the same file and located good ideas. a damaged copy, contact membership@
close to each other. What happens computer.org.
when they are in separate files and
written by different people in differ- Reprints of Articles
ent millennia? For price information or to order reprints, send
This question leads us to think e-mail to software@computer.org or fax +1
Martin Fowler is the chief scientist for ThoughtWorks, an
about how we construct our soft- Internet systems delivery and consulting company. For a decade, 714 821 4010.
ware to reduce the chances of this he was an independent consultant pioneering the use of objects
happening. Using abstract data types in developing business information systems. He’s worked with
technologies including Smalltalk, C++, object and relational
Reprint Permission
is a good way of doing this. Because databases, and Enterprise Java with domains including leasing, To obtain permission to reprint an article, con-
you have to pass data around, you payroll, derivatives trading, and healthcare. He is particularly tact William Hagen, IEEE Copyrights and Trade-
find that people are less likely to du- known for his work in patterns, UML, lightweight methodologies,
and refactoring. He has written four books: Analysis Patterns,
marks Manager, at whagen@ieee.org.
plicate data structures. If you try to Refactoring, Planning Extreme Programming, and UML Distilled.
place routines next to their data Contact him at fowler@acm.org.

January/February 2001 IEEE SOFTWARE 99


design
Editor: Martin Fowler ■ T h o u g h t Wo r k s ■ fowler@acm.org

Separating User Interface


Code
Martin Fowler

he first program I wrote on a salary user interface code as presentation code

T was scientific calculation software in


Fortran. As I was writing, I noticed
that the code running the primitive
menu system differed in style from the
code carrying out the calculations. So
I separated the routines for these tasks,
which paid off when I was asked to create
higher-level tasks that did several of the in-
dividual menu steps. I could just
and the other code as domain code.
When separating the presentation from
the domain, make sure that no part of the
domain code makes any reference to the
presentation code. So, if you write an ap-
plication with a WIMP (windows, icons,
mouse, and pointer) GUI, you should be
able to write a command line interface that
does everything that you can do through
write a routine that called the the WIMP interface—without copying any
calculation routines directly code from the WIMP into the command
without involving the menus. line.
Thus, I learned for myself a de-
sign principle that’s served me Why do this?
well in software development: Following this principle leads to several
Keep your user interface code sep- good results. First, this presentation code
arate from everything else. It’s a separates the code into different areas of
simple rule, embodied into more complexity. Any successful presentation re-
than one application framework, quires a fair bit of programming, and the
but it’s often not followed, which complexity inherent in that presentation
causes quite a bit of trouble. differs in style from the domain with which
you work. Often it uses libraries that are
Stating the separation only relevant to that presentation. A clear
Any code that does anything with a user separation lets you concentrate on each as-
interface should only involve user interface pect of the problem separately—and one
code. It can take input from the user and complicated thing at a time is enough. It
display information, but it should not ma- also lets different people work on the sepa-
nipulate the information other than to for- rate pieces, which is useful when people
mat it for display. A clearly separated piece want to hone more specialized skills.
of code—separate routines, modules, or Making the domain independent of the
classes (based on your language’s organiz- presentation also lets you support multiple
ing structure)—should do calculations, val- presentations on the same domain code, as
idations, or communications should be suggested by the WIMP versus command
done by a clearly separated piece of code. line example, and also by writing a higher-
For the rest of the article, I’ll refer to the level Fortran routine. Multiple presentations

96 IEEE SOFTWARE March/April 2001 0740-7459/01/$10.00 © 2001 IEEE


DESIGN

are the reality of software. Domain the family of platforms for develop- mixing presentation with domain
code is usually easy to port from ing WIMP interfaces: Visual Basic, code. To avoid this, make a separate
platform to platform, but presenta- Delphi, Powerbuilder, and the like. module that contains the domain
tion code is more tightly coupled to These tools were designed for code and only make simple calls
operating system or hardware. Even putting WIMP interfaces onto SQL from the server page to that module.
without porting, it’s common to find databases and were very successful. For a simple set of pages, there is an
that demands to changes in the pre- The key to their success was data- overhead (although I would call it a
sentation occur with a different aware widgets, such as a pop-up small one), but as the set gets more
rhythm than changes in the domain menu bound to a SQL query. Such complicated, the value of the sepa-
functionality. tools are very powerful, letting you ration grows.
Pulling away the domain code quickly build a WIMP interface that This same principle, of course, is at
also makes it easier to spot—and operates on a database, but the the heart of using XML. I built my
avoid—duplication in domain code. tools don’t provide any place to ex- Web site, www.martinfowler.com, by
Different screens often require sim- tract the domain code. If straight writing XML and converting it to
ilar validation logic, but when it’s updates to data and view are all you HTML. It lets me concentrate on the
hidden among all the screen han- do, then this is not a problem. Even structure of what I was writing in one
dling, it’s difficult to spot. I remem- as a certified object-bigot, I always place, so I could think about its for-
ber a case where an application recommend these kinds of tools for matting later (not that I do any fancy
needed to change its date valida- these kinds of applications. How- formatting.) Those who use content-
tion. The application had two parts ever, once domain logic gets compli- oriented styles in word processors are
that used different languages. One cated, it becomes hard to see how doing much the same thing. I’ve
part had date validation copied to separate it. reached the point where that kind of
over its date widgets and required This problem became particularly separation seems natural. I’ve had to
over 100 edits. The other did its obvious as the industry moved to become a bit of an XSLT whiz—and
validation in a single date class and Web interfaces. If the domain logic is the tools for that aren’t even adoles-
required just a single change. At the stuck inside a WIMP interface, it’s cent yet.
time, this was hyped as part of the not possible to use it from a Web The general principle here is that
massive productivity gain you could browser. of separating concerns, but I find
get with object-oriented software— However, the Web interfaces of- such a general principle hard to ex-
but the former non-object system ten encourage the same problems. plain and follow. After all, what
could have received the same bene- Now we have server page technolo- concerns should you separate? Pre-
fit by having a single date valida- gies that let you embed code into sentation and domain are two sepa-
tion routine. The separation yielded HTML. As a way of laying out how rable concerns I’ve found straight-
the benefit. generated information appears on forward to explain—although that
Presentations, particularly WIMPs the page, this makes plenty of sense. principle isn’t always easy to fol-
and browser-based presentations, can The structure starts breaking down low. I think it’s a key principle in
be very difficult to test. While tools ex- when the code inside the server page well-engineered software. If we ever
ist that capture mouse clicks, the re- is more complicated. As soon as see engineering codes for software,
sulting macros are very tricky to main- code starts making calculations, I’d bet that separation of presenta-
tain. Driving tests through direct calls running queries, or doing valida- tion and domain will be in there
to routines is far easier. Separating the tions, it runs into that same trap of somewhere.
domain code makes it much easier to
test. Testability is often ignored as a
criteria for good design, but a hard-to-
test application becomes very difficult
to modify.

The difficulties
Pulling away the
So why don’t programmers sepa- domain code also Martin Fowler is the chief scientist for ThoughtWorks, an
rate their code? Much of the reason makes it easier to Internet systems delivery and consulting company. For a decade,
lies in tools that make it hard to he was an independent consultant pioneering the use of objects
maintain the separation. In addi- spot—and avoid— in developing business information systems. He’s worked with
technologies including Smalltalk, C++, object and relational
tion, the examples for those tools
don’t reveal the price for ignoring
duplication in databases, and Enterprise Java with domains including leasing,
payroll, derivatives trading, and health care. He is particularly
the separation. domain code. known for his work in patterns, UML, lightweight methodologies,
and refactoring. He has written four books: Analysis Patterns,
In the last decade or so, the Refactoring, Planning Extreme Programming, and UML Distilled.
biggest presentation tool has been Contact him at fowler@acm.org.

March/April 2001 IEEE SOFTWARE 97


design
E d i t o r : M a r t i n F o w l e r, T h o u g h t Wo r k s ■ fowler@acm.org

Protected Variation:
The Importance of Being
Closed
Craig Larman

he Pattern Almanac 2000 (Addison- OCP and PV formalize and generalize a

T Wesley, 2000) lists around 500 soft-


ware-related patterns—and given this
reading list, the curious developer has
no time to program! Of course, there
are underlying, simplifying themes and
principles to this pattern plethora that de-
velopers have long considered and dis-
cussed. One example is Larry Constantine’s
coupling and cohesion guidelines
common and fundamental design principle
described in many guises. OCP and PV are
two expressions of the same principle—
protection against change to the existing
code and design at variation and evolution
points—with minor differences in emphasis.
I am nominating the term protected varia-
tion for general use, as it is short and clear.
In OCP, the term module includes all dis-
(see “Structured Design,” IBM crete software elements, including methods,
Systems J., vol. 13, no. 2, 1974). classes, subsystems, applications, and so forth.
Yet, these principles must contin- Also, the phrase “closed with respect to X”
ually resurface to help each new means that clients are not affected if X
generation of developers and ar- changes. For example, “The class is closed
chitects cut through the apparent with respect to instance field definitions.” PV
disparity in myriad design ideas uses the term interface in the broad sense of an
and help them see the underlying access view—not exactly a Java or COM in-
and unifying forces. terface, for example.
One such principle, which
Bertrand Meyer describes in Ob- Information hiding is PV,
ject-Oriented Software Construction (IEEE not data encapsulation
Press, 1988), is the Open–Closed Principle: “On the Criteria To Be Used in Decom-
Modules should be both open (for extension posing Systems Into Modules” is a classic
and adaptation) and closed (to avoid modifi- that is often cited but seldom read. In it, Par-
cation that affect clients). OCP is essentially nas introduces information hiding. Many
equivalent to the Protected Variation pattern: people have misinterpreted the term as mean-
Identify points of predicted variation and cre- ing data encapsulation, and some books er-
ate a stable interface around them. Alistair roneously define the concepts as synonyms.
Cockburn did not know of OCP when he Parnas intended it to mean hide informa-
first wrote about PV (see “Prioritizing Forces tion about the design from other modules,
in Software Design,” Patterns Languages of at the points of difficult or likely change. To
Program Design, vol. 2, Addison-Wesley, quote his discussion of information hiding
1996). Furthermore, OCP is what David Par- as a guiding design principle:
nas really meant by information hiding (see
“On the Criteria to Be Used in Decomposing We propose instead that one begins with a
Systems into Modules” Comm. ACM, vol. list of difficult design decisions or design
12, no. 2, Dec. 1972). decisions which are likely to change. Each

0740-7459/01/$10.00 © 2001 IEEE May/June 2001 IEEE SOFTWARE 89


DESIGN

module is then designed to hide tional mapping, property files, reading guage services protect the system from
such a decision from the others. in window layouts, and much more. the impact of logic or external code
The system is protected from the im- variations. We could also consider this
That is, Parnas’s information hiding is pact of data, metadata, or declarative a special case of data-driven designs.
the same principle expressed in PV or variations by externalizing the variant,
OCP—it is not simply data encapsula- reading the behavior-influencing data Pick your battles
tion, which is but one of many tech- in, and reasoning with it. As an example of PV’s application,
niques to hide design information. a client explained that the logistical
However, the term has been so Service lookup support application used by an airline
widely reinterpreted as a synonym for Service lookup includes techniques was a maintenance headache. There
data encapsulation that it is no longer such as using naming services (for ex- was frequent modification of the
possible to use it in its original sense ample, JNDI) or traders to obtain a business logic to support the logistics.
without misunderstanding it. This arti- service (such as Jini). This approach How do you protect the system from
cle should be called, “The Importance uses the stable interface of the lookup variations at this point? From the
of Information Hiding,” in honor of service to protect clients from varia- mechanisms to support PV (data en-
Parnas’s description of the PV princi- tions in the location of services. It is a capsulation, interfaces, indirection,
ple. Dijkstra earlier alludes to the prin- special case of data-driven designs. …), a rule-based design was chosen:
ciple in the “THE” project, but Parnas A rules engine was added to the sys-
gave it focus and shape (Dijkstra, “The Interpreter-driven designs tem, and an external rule editor let
Structure of the ‘THE’ Multiprogram- Interpreter-driven designs include the subject matter experts update the
ming System,” Comm. ACM, 1968). rule interpreters that execute rules read rules without requiring changes to the
from an external source, script or lan- source code of the system.
Mechanisms motivated by PV guage interpreters that read and run Low coupling and protection
PV is a root principle motivating programs, virtual machines, neural net- against variations is not motivated in
most of the mechanisms and patterns work engines that execute nets, con- all areas. You must pick your battles
in programming and design that pro- straint logic engines that read and rea- in design, be they at the macro-archi-
vide flexibility and protection from son with constraint sets, and so forth. tectural level or the humble instance
variations. Here are some examples. This approach lets you change or para- field. A good designer can identify the
meterize a system’s behavior through likely points of instability or variation
Familiar PV mechanisms external logic expressions. The system and apply PV to those points but not
PV motivates data encapsulation, is protected from the impact of logic others. Otherwise, effort is wasted
interfaces, polymorphism, indirec- variations by externalizing the logic, and complexity may arise (and with
tion, and standards. Components reading it in (for example, rules or a it, the chance for defects).
such as brokers and virtual machines neural net), and using an interpreter. For example, I recall being surprised
are complex examples of indirection. by the occasional use of static public fi-
Reflective or metalevel designs nal fields in the Java technology li-
Uniform access An example of a reflective or meta- braries (after spending many years with
Languages such as Ada, Eiffel, and level design includes using the java. the Smalltalk libraries). Some might be
C# support a syntactic construct to beans.Introspector to obtain a Bean- poorly conceived, but some, such as
express both a method and field ac- Info object, asking for the getter the Color static fields red, black, white,
cess in the same way. For example, Method object for bean property X and so forth, are extremely stable; the
aCircle.radius might invoke a ra- (that is, the method getX), and calling likelihood of instability is so low that
dius():float method or directly refer Method.invoke. Reflective algorithms making them private and adding ac-
to a public field, depending on the that use introspection and metalan- cessing methods is just object purism.
definition of the class. You can As a counterexample, I know of
change public fields to access meth- a pager-message-handling system in
ods without changing the client code. which the architect added a fancy
You must scripting language and interpreter to
Data-driven designs pick your battles support some flexibility. However, dur-
Data-driven designs cover a broad ing rework in an incremental release,
family of techniques, including reading
in design, be they at the the complex (and inefficient) scripting
codes, values, class file paths, class macro-architectural was removed—it wasn’t needed.
names, and so forth, from an external
source in order to change the behavior
level or the humble Judicious PV and the
of or “parameterize” a system in some instance field. Diamond Sutra
way at runtime. Other variants include Constantine’s guideline to design
style sheets, metadata for object-rela- with low coupling is a truly core prin-

90 IEEE SOFTWARE May/June 2001


DESIGN

ciple of design, and it can be argued and brittle designs. If the need for PV is a fundamental design principle
that PV derives from it. We can priori- flexibility and PV is immediately ap- that applies to everything from the
tize our goals and strategies as follows: plicable, then applying PV is justified. largest architectural concerns to the
However, if you’re using PV for smallest coding decision. Furthermore,
1. We wish to save time and money, speculative future proofing or reuse, it underlies the motivation and advice
reduce the introduction of new then deciding which strategy to use is of most other patterns and principles.
defects, and reduce the pain and not as clear-cut. Novice developers As Parnas explained 30 years ago—
suffering inflicted on overworked tend toward brittle designs, and inter- and as has resurfaced in the writings of
developers. mediates tend toward overly fancy Meyer and Cockburn—each genera-
2. To achieve this, we design to min- and flexible generalized ones (in ways tion of software developers needs help
imize the impact of change. that never get used). Experts choose seeing mountains as mountains again
3. To minimize change impact, we de- with insight—perhaps choosing a sim- —especially after four years of com-
sign with the goal of low coupling. ple and brittle design whose cost of puter science and 500 patterns!
4. To design for low coupling, we change is balanced against its likeli-
design for PVs. hood. The journey is analogous to the
well-known stanza from the Diamond Acknowledgments
Low coupling and PV are just one Sutra: OCP, as described here, was brought to my
set of mechanisms to achieve the goals attention by Bob Martin in The Open-Closed
Principle: C++ Report, SIGS Publications,
of saving time, money, and so forth. Before practicing Zen, mountains 1996.
Sometimes, the cost of speculative fu- were mountains and rivers were
ture proofing to achieve these goals rivers.
outweighs the cost incurred by a sim-
ple, highly coupled “brittle” design While practicing Zen, mountains
that is reworked as necessary in re- are no longer mountains and Craig Larman is director of process and methodology at
Valtech, an international consulting group. He holds a BSc and
sponse to true change pressures. That rivers are no longer rivers. an MSc in computer science, with research emphasis in artificial
is, the cost of engineering protection intelligence. He is the author of Applying UML and Patterns: An
at evolution points can be higher than After realization, mountains are Introduction to Object-Oriented Analysis and Design, and he is
writing a second edition that will include OCP/PV as one of the
reworking a simple design. mountains and rivers are rivers fundamental design principles. He is a member of the IEEE and
My point is not to advocate rework again. ACM. Contact him at clarman@acm.org.

How to
Reach Us
Writers Subscription Change of Address
For detailed information on submitting articles, write for Send change-of-address requests for magazine subscriptions to
our Editorial Guidelines (software@ computer.org), or address.change@ieee.org. Be sure to specify IEEE Software.
access computer.org/software/author.htm.
Membership Change of Address
Letters to the Editor Send change-of-address requests for the membership directory to
Send letters to help@computer.org.
Letters Editor
IEEE Software Missing or Damaged Copies
10662 Los Vaqueros Circle If you are missing an issue or you received a damaged copy, contact
Los Alamitos, CA 90720 help@computer.org.
software@computer.org
Reprints of Articles
Please provide an email address or daytime phone num- For price information or to order reprints, send email to
ber with your letter. software@computer.org or fax +1 714 821 4010.

On the Web Reprint Permission


Access computer.org/software for information about To obtain permission to reprint an article, contact William Hagen,
IEEE Software. IEEE Copyrights and Trademarks Manager, at whagen@ieee.org.

May/June 2001 IEEE SOFTWARE 91


design
Editor: Martin Fowler ■ T h o u g h t Wo r k s ■ fowler@acm.org

Reducing Coupling
Martin Fowler

ne of the earliest indicators of design communicate in some way—otherwise, you’d

O quality was coupling. It appeared, to-


gether with cohesion, in the earliest
works in structured design, and it has
never gone away. I still always think of
it when considering a software design.
There are several ways to describe cou-
pling, but it boils down to this: If changing
one module in a program requires changing
another module, then coupling
just have multiple programs. Coupling is de-
sirable, because if you ban coupling between
modules, you have to put everything in one
big module. Then, there would be lots of cou-
pling—just all hidden under the rug.
So coupling is something we need to con-
trol, but how? Do we worry about coupling
everywhere, or is it more important in some
places than others? Which factors make
exists. It might be that the two coupling bad, and which are permissible?
modules do similar things at one
point, so the code in one module Look at dependencies
is effectively a duplicate of the I concern myself most with coupling at the
code in the other. This is an ex- highest-level modules. If we divide a system
ample of the primary and obvi- into a dozen (or fewer) large-scale pieces,
ous sin of duplication. Duplica- how are these pieces coupled? I focus on the
tion always implies coupling, coarser-grained modules, because worrying
because changing one piece of about coupling everywhere is overwhelming.
duplicate code implies changing The biggest problems come from uncon-
the other. It can also be hard to trolled coupling at the upper levels. I don’t
spot, because there might not be an obvious worry about the number of modules coupled
relationship between the two pieces of code. together, but I look at the pattern of depen-
Coupling also occurs when code in one dency relationship between the modules. I
module uses code from another, perhaps by also find a diagram very helpful.
calling a function or accessing some data. At When I use the term dependency, I use it as
this point, it becomes clear that, unlike dupli- defined in the Unified Modeling Language
cation, you can’t treat coupling as something (UML). So, the UI module depends on the do-
to always avoid. You can break a program main module if any code in the UI module ref-
into modules, but these modules will need to erences any code in the domain model—by

Figure 1. (a) A simple


package diagram and
(b) a mapper package
User User
that insulates the Domain Database Domain Mapper Database
interface interface
domain and database
(a) (b)
packages from each
other.

102 IEEE SOFTWARE July/August 2001 0740-7459/01/$10.00 © 2001 IEEE


DESIGN

ICSE 2002
User Mapper
Domain
interface interface

Mapper Database
implementation

Figure 2. Introducing an database causes a big enough


interface implementation split. change in the domain that the do-
main’s interface also changes.
calling a function, using some data, Figure 1a shows how I’d diagram
or using types defined in the domain this using UML notation. The UML
module. If someone changes the do- is designed for an OO system, but
main, there is a chance the UI model the basic notion of modules and de-
will also need to change. A depen- pendencies applies to most styles of
dency is unidirectional: The UI software. The UML name for this
module usually depends on the do- kind of high-level module is pack-
main module, but not the other way age, so I’ll use that term from now May 19-25, 2002
around. We would have a second on (so the UML police won’t arrest
dependency if the domain module me!). Because these are packages, I Buenos Aires
also depended on the UI module. call this kind of diagram a package
UML dependencies are also non-
transitive. If the UI module depends
diagram (although strictly in UML,
it’s a class diagram).
Argentina
on the domain module, and the do-
main module depends on the data-
What I’m describing here is a
layered architecture, which should

base module, we can’t assume that be familiar to anyone who works in Conference Website
the UI module depends on the data- information systems. The layers in
base module. If it does, we must de-
scribe this with an extra dependency
an information system make good
fodder for describing things we

directly between UI and database must consider when thinking about http://www.icse-
modules. This nontransitivity is im- dependencies.
portant because it lets us show that A common piece of advice re-
conferences.org/2002/
the domain model insulates the UI garding dependency structures is to
from changes in the database. Thus, avoid cycles. Cycles are problem- 
if the database’s interface changes, atic, because they indicate that you
we don’t immediately have to worry can get in a situation in which every
Call For Participation
about a change in the UI. The UI change breeds other changes that
will only change if the change in the come back to the original package. 
Such systems are harder to under- http://www.icse-
Figure 3. Defining an interface stand because you have to go
in one package that’s around the cycle many times. I conferences.org/2002/
implemented by another. don’t view the need to avoid cycles
cfp.pdf
Domain

User
interface
Store 
Mapper

Store Database
implementation
DESIGN

between packages as a strict rule—I’ll that the domain package will work
tolerate them if they’re localized. A with any mapper that chooses to im-
cycle between two packages in the plement the store interface.
How to same layer of an application is less of
a problem.
Defining an interface in a module
that a separate module intends to im-
Reach Us A mapper package
plement is a fundamental way to
break dependencies and reduce cou-
In Figure 1a, all the dependencies pling. This approach appears in many
run in a single direction. This is a forms, the most primitive of which is
Writers sign—but not requirement—of a well- the call back. In this form, the caller
For detailed information on submitting controlled set of dependencies. Figure is asked to supply a reference to a
articles, write for our Editorial Guidelines 1b shows another common feature of function with a certain signature,
(software@ computer.org), or access information systems, when a mapper which is called later. A common ex-
computer.org/software/author.htm. package separates the domain from ample in the Java world is a listener.
the database. (A mapper is a package Because listeners are classes, they are
Letters to the Editor that provides insulation in both direc- more explicit, which clarifies things.
Send letters to tions.) The mapper package provides Another example is a module defin-
Letters Editor insulation in both directions, which ing an event that it passes out, to
IEEE Software lets the domain and database change which others can react. You can think
10662 Los Vaqueros Circle independently of each other. As a re- of an event as defining an interface to
Los Alamitos, CA 90720 sult, you often find this style in more which the listening module conforms.
software@computer.org complex OO models. The caller of the call back function, the
Of course, if you think of what definer of the listener interface, and
Please provide an email address or day- happens when you load and save the producer of the event know noth-
time phone number with your letter. data, you realize that this picture isn’t ing about the module that actually is
quite right. If a module in the domain called, so there’s no dependency.
On the Web needs some data from the database,
Access computer.org/software for infor- how does it ask for it? It can’t ask the ’m left feeling a lack of closure, be-
mation about IEEE Software.

Subscription Change of Address


Send change-of-address requests for mag-
mapper, because if it could, it would
introduce a dependency from the do-
main to the mapper, which would be
I cause much of what I’ve said in-
volves weasel words such as “well-
controlled dependencies.” It’s difficult
a cycle. To get around this problem, I to offer hard pieces of guidance when
azine subscriptions to address.change@ need a different kind of dependency. trying to define a well-controlled set
ieee.org. Be sure to specify IEEE So far, I’ve talked about dependen- of dependencies. Certainly, it’s about
Software. cies in terms of code using other parts reducing the amount of dependencies,
of code. But there’s another kind— but that’s not the whole issue. The di-
Membership Change of Address the relationship between an interface rection of the dependencies and the
Send change-of-address requests for the and its implementation. An imple- way they flow, such as to avoid big cy-
membership directory to help@ mentation depends on its interface cles, is also important. In addition, I
computer.org. but not vice versa. In particular, any treat all dependencies the same, with-
caller of an interface depends only on out considering the interface’s width.
Missing or Damaged Copies the interface, even if a separate mod- It seems that worrying too much
If you are missing an issue or you ule implements it. about what you depend on is less im-
received a damaged copy, contact Figure 2 illustrates this idea. The do- portant than the fact that there is a de-
help@computer.org. main depends on the interface but not pendency there.
the implementation. The domain won’t The basic rule that I follow is to
Reprints of Articles work without some mapper implemen- visualize my high-level dependencies
For price information or to order tation, but only changes in the interface and then rationalize them, separating
reprints, send email to software@ would cause the domain to change. the interface and implementation to
computer.org or fax +1 714 821 4010. In this situation, there are separate break dependencies I don’t want.
packages, but this isn’t necessary. Like so many design heuristics, this
Reprint Permission Figure 3 shows a store package con- seems awfully incomplete. Yet, I have
To obtain permission to reprint an article, tained within the domain, imple- found it useful—and in the end, that
contact William Hagen, IEEE Copyrights mented by a store implementation is what counts.
and Trademarks Manager, at whagen@ contained within the mapper. In this
ieee.org. case, the domain defines the interface Martin Fowler is the chief scientist for ThoughtWorks, an
Internet systems delivery and consulting company. Contact him
for the mapper. It’s essentially saying at fowler@acm.org; http://martinfowler.com.
design
Editor: Martin Fowler ■ T h o u g h t Wo r k s ■ fowler@acm.org

To Be Explicit
Martin Fowler

oftware is an odd medium in which Attributes and dictionaries

S to construct something. Because few


physical forces make you design one
way or another, many design deci-
sions sadly resist any form of objec-
tive analysis. Where design counts is
often not in how the software runs but in
how easy it is to change. When how it runs
is important, ease of change can be the
biggest factor in ensuring good performance.
Let’s say we want a person data structure.
We can accomplish this by having specific
fields, as Figure 1 shows. Of course, to make
this work, we must define the variables in the
person class. Like many modern languages,
Ruby provides a dictionary data structure
(also knows as a map, associative array, or
hash table). We could use Ruby instead to
define the person class, using the approach in
This drive toward change- Figure 2. (This is slower, but let’s assume this
ability is why it’s so important section of code isn’t performance critical.)
for a design to clearly show Using a dictionary is appealing because it
what the program does—and lets you change what you store in the person
how it does it. After all, it’s hard without changing the person class. If you
to change something when you want to add a telephone number, you can do
can’t see what it does. An inter- it without altering the original code.
esting corollary of this is that Despite this, the dictionary doesn’t make it
people often use specific designs easier to modify the code. If I’m trying to use
because they are easy to change, the person structure, I can’t tell what is in it.
but when they make the pro- To learn that someone’s storing the number of
gram difficult to understand, the dependents, I must review the entire system. If
effect is the reverse of what was intended. the number of dependents is declared in the

class Person
attr_accessor :lastName, :firstName, :numberOfDependents
end

def frag1
martin = Person.new
martin.firstName = “Martin”
martin.lastName = “Fowler”
martin.numberOfDependents = 1
print (martin.firstName, “ “, martin.lastName, “ has “,
martin.numberOfDependents, “ dependents”)

Figure 1. Explicit end


fields (using Ruby).

10 IEEE SOFTWARE November/December 2001 0740-7459/01/$10.00 © 2001 IEEE


Figure 2. Dictionary fields (using
Ruby). class Person
attr_accessor :data
def initialize()
@data = {}
class, then I only have to look in the end
person class to see what it supports. end
The key principle is that explicit
code is easier to understand—which def frag2
makes the code easier to modify. As martin = Person.new
Kent Beck puts is, the explicit code is martin.data[“firstName”] = “Martin”
intention revealing. martin.data[“lastName”] = “Fowler”
This dictionary example is small martin.data[“numberOfDependents”] = 1
in scale, but the principle holds at al- print (martin.data[“firstName”],“ “,
most every scale of software design. martin.data[“lastName”], “ has “,
martin.data[“numberOfDependents”],
Events and explicit calls
“ dependents”)
Here’s another example, on a end
slightly bigger scale. Many platforms
support the notion of events to com-
municate between modules. Say we
have a reservation module that, when events that affect a reservation, and any the reservation class to get something
canceled, needs to get a person mod- object that wants to do anything when else to happen when you cancel a reser-
ule to send email to that person. an event occurs can build a handler to vation. As long as other objects put
We can do this using an event, as Fig- react when it occurs. This approach is handlers on the event, it’s easy to extend
ure 3 shows. We can define interesting appealing because you need not modify the behavior at these points.

public delegate void ReservationHandler (IReservation source);


public class Reservation ...
public String Id;
public event ReservationHandler Cancelled;
public Person client {
get {
return client;
}
set {
value.AddReservation(this);
}
}
public void Cancel(){
Cancelled (this);
}

public class Person ...


public String EmailAddress;
public readonly ArrayList reservations;

public void SendCancellationMessage(Reservation arg) {


// send a message
}

public void AddReservation(Reservation arg) {


//invoke SendCancellationMessage when the cancelled event occurs on arg
arg.Cancelled +=
new ReservationHandler(SendCancellationMessage);
}

Figure 3. Cancellation using events (using C#).

November/December 2001 IEEE SOFTWARE 11


DESIGN

However, there is a cost to using that it’s hard to determine what the dency from the class triggering the
events—I can’t see what happens at program does when you call a event to the one that needs to react.
cancellation by reading the code in the method. This becomes particularly This lack of a dependency is valuable
cancellation method. To find out what awkward when you’re debugging, when the two classes are in different
happens, I have to search for all the because behavior pops up suddenly packages and you don’t want to add
code that has a handler for the event. in places you don’t expect. a dependency. The class case of this is
The explicit code for this (see Figure 4) I’m not saying that you shouldn’t when you want to modify a window
clearly shows in the cancel method the use events. They let you carry out be- in a presentation when some domain
consequences of cancellation, at the havior without changing a class, object changes. Events let you do this
cost of modifying the reservation class which makes them useful when while preserving the vital separation
when I need to change the behavior. working with library classes you of the presentation and domain.
I’ve seen a few code examples that can’t modify. They are also valuable Those forces both suggest events,
use events heavily, and the problem is because they don’t create a depen- but in their absence, the lack of explic-
itness of events becomes more domi-
nant. So, I would be reluctant to use
events between two application classes
that can be aware of each other.
As you can see, explicitness is not
always the dominant force in design
decisions. In this example, packaging
and dependency forces are also im-
portant. People often underestimate
the value of explicitness. There are
times when I would add a dependency
to make code more explicit, but, as al-
ways with design, each situation has
its own trade-offs to consider.

Data-driven code and explicit


subclasses
My final example is on yet a bigger
scale. Consider a discounting scheme
for orders that uses different discount-
ing plans. The blue plan gives you a
fixed discount of 150 if you buy
goods from a particular group of sup-
pliers and the value of your order is
over a certain threshold. The red plan
gives you a 10 percent discount when
delivering to certain US states.
Figure 5 presents explicit code for
this. The order has a discounter with
specific subclasses for the blue and
red cases. The data-driven version in
Figure 6 uses a generic discounter
that is set up with data when the or-
der is created.
The generic discounter’s advantage
is that you can create new kinds of dis-
counters without making new classes
by writing code—if the new classes fit
in with the generic behavior. For the
sake of argument, let’s assume they
can. Is the generic case always the best
choice? No, again because of explicit-
ness. The explicit subclasses are easier
to read and they make it easier to
Figure 4. An explicit reaction to
cancel (using C#). public class Reservation ...

public String Id;


public Person client;

public void Cancel(){


client.SendCancellationMessage(this);
}
Figure 5. Explicitly programmed
discount logic (using C#).

public class Order ...


public Decimal BaseAmount;
public String Supplier;
public String DeliveryState;
public Discounter Discounter;

public virtual Decimal Discount {


get {
return Discounter.Value(this);
}
}
}
abstract public class Discounter {
abstract public Decimal Value (Order order);
}
public class BlueDiscounter : Discounter {
public readonly IList DiscountedSuppliers = new ArrayList();
public Decimal Threshold = 500m;
public void AddDiscountedSupplier(String arg) {
DiscountedSuppliers.Add(arg);
}
public override Decimal Value (Order order) {
return (DiscountApplies(order)) ? 150 : 0;
}
private Boolean DiscountApplies(Order order) {
return DiscountedSuppliers.Contains(order.Supplier) &&
(order.BaseAmount > Threshold);
}
}
public class RedDiscounter : Discounter {
public readonly IList DiscountedStates = new ArrayList();
public void AddDiscountedState (String arg) {
DiscountedStates.Add(arg);
}
public override Decimal Value (Order order) {
return (DiscountedStates.Contains(order.DeliveryState)) ?
order.BaseAmount * 0.1m : 0;
}
}

// to set up a blue order


BlueDiscounter bluePlan = new BlueDiscounter();
bluePlan.AddDiscountedSupplier(“ieee”);

blue = new Order();


blue.Discounter = bluePlan;
blue.BaseAmount = 500;
blue.Supplier = “ieee”;

November/December 2001 IEEE SOFTWARE 13


DESIGN

public class GenericOrder : Order ...


public Discounter Discounter;
public override Decimal Discount {
get {
return Discounter.Value(this);
}
}

public enum DiscountType {constant, proportional};

public class Discounter ...


public DiscountType Type;
public IList DiscountedValues;
public String PropertyNameForInclude;
public String PropertyNameForCompare;
public Decimal CompareThreshold;
public Decimal Amount;

public Decimal Value(GenericOrder order) {


if (ShouldApplyDiscount(order)) {
if (Type == DiscountType.constant)
return Amount;
if (Type == DiscountType.proportional)
return Amount * order.BaseAmount;
throw new Exception (“Unreachable Code reached”);
} else return 0;
}

private Boolean ShouldApplyDiscount(Order order) {


return PassesContainTest(order) &&
PassesCompareTest(order);
}
private Boolean PassesContainTest(Order order) {
return DiscountedValues.Contains
(GetPropertyValue(order, PropertyNameForInclude));
}
private Boolean PassesCompareTest(Order order){
if (PropertyNameForCompare == null) return true;
else {
Decimal compareValue =
(Decimal) GetPropertyValue(order, PropertyNameForCom-
pare);
return compareValue > CompareThreshold;
}
}
private Object GetPropertyValue (Order order, String propertyName) {
FieldInfo fi = typeof(Order).GetField(propertyName);
if (fi == null)
throw new Exception(“unable to find field for “ + property-
Name);
return fi.GetValue(order);
}
}

Figure 6. Data-programmed discount logic (using C#).

14 IEEE SOFTWARE November/December 2001


DESIGN

//to set up a blue order


GenericDiscounter blueDiscounter = new GenericDiscounter();
String[] suppliers = {“ieee”};
blueDiscounter.DiscountedValues = suppliers;
blueDiscounter.PropertyNameForInclude = “Supplier”;
blueDiscounter.Amount = 150;
blueDiscounter.PropertyNameForCompare = “BaseAmount”;
blueDiscounter.CompareThreshold = 500m;
blueDiscounter.Type = DiscountType.constant;

blue = new Order();


blue.BaseAmount = 500;
blue.Discounter = blueDiscounter;

understand the behavior. With the xplicitness is not an absolute in de- what makes good design have evolved
generic case, you must look at the
generic code and setup code, and it’s
harder to see what’s happening—and
E sign, but clever designs often be-
come hard to use because they
aren’t explicit enough. In some cases,
(hopefully in the right direction).

even harder for more complicated bits the cost is worth it, but it’s always
of behavior. Of course, we can extend something to consider. In the last few
Martin Fowler is the chief scientist for ThoughtWorks, an
the generic order without “program- years, I’ve tended to choose explicit de- Internet systems delivery and consulting company. Contact him
ming,” but I’d argue that configuring signs more often because my views of at fowler@acm.org.
that data is a form of programming.
Debugging and testing are often both
difficult and overlooked with data-dri-
ven behavior.
The generic case works when you
have dozens of discounters. In such Boston University
cases, the volume of code becomes a
problem, while greater volumes of
If you have significant academic or industrial experience in developing large
data are less problematic. Sometimes software systems and you are committed to improving the practice of software
a well-chosen data-driven abstrac- engineering, we want to talk to you about a faculty appointment at Boston Uni-
tion can make the logic collapse into versity in Computer Systems Engineering. Our graduate program teaches the
a much smaller and easier-to-main- engineering skills necessary for the effective development of large-scale com-
tain piece of code. puter systems in which software provides essential functionality. We teach stu-
dents to apply engineering principles to the design of a full range of computer
Ease of deploying new code is also a products from embedded systems, to data communication networks, to soft-
factor. If you can easily add new sub- ware products. Three types of appointments are available in the Department of
classes to an existing system, explicit Electrical and Computer Engineering (ECE) starting in September 2002:
behavior works well. However, generic • Research oriented tenure-track and tenured appointments.
behavior is a necessity if new code • Non-tenure track positions, which require extensive experience in
practicing software engineering.
means long and awkward compile and • Adjunct (part-time) positions for Boston-area experts who are interested in
link cycles. teaching their specialty at the graduate level.
There’s also the option of combin- All positions require a commitment to excellence in teaching at the undergrad-
ing the two, using a data-driven uate and graduate levels. For additional information on the College of Engi-
generic design for most of the cases neering and ECE Department visit the College’s homepage at
http://www.bu.edu/eng/.
and explicit subclasses for a few hard To learn more about opportunities for a non-tenure track OR adjunct posi-
cases. I like this approach because it tions, please e-mail: besaleh@bu.edu and a faculty member will call to discuss
keeps the generic design much sim- our opportunities. For tenure-track OR tenured appointments, send your Cur-
pler, but the subclasses give you a lot riculum Vita to: Professor Bahaa E. A. Saleh, Chair, Department of Electrical and
of flexibility when you need it. Computer Engineering, Boston University, 8 Saint Mary’s Street, Boston, MA
02215.

November/December 2001 IEEE SOFTWARE 15


A Conversation with Martin Fowler

Search | Articles | News | Weblogs | Buzz | Forums


Please take our Snappy Survey.

A Conversation with Martin Fowler


by Bill Venners
December 9, 2002

In this six-part interview, Martin Fowler, chief scientist at


Thoughtworks, Inc. and author of numerous books on
software design and process, discusses refactoring,
design, testing, and extreme programming.

Part I: Refactoring with Martin Fowler Part IV: Flexibility and Complexity
Martin Fowler on the business case Martin Fowler on how to combat design
for refactoring and testing, and the decay, the cost of flexibility and reusability,
interplay between refactoring, design, four criteria for a simple system, and test-
and reliability. first design of interfaces.
Part II: Design Principles and Code
Ownership
Part V: Test-Driven Development
Martin Fowler on design principles of
Martin Fowler on the unhurried quality of
avoiding duplication, separating
test-first design and monological thinking,
presentation and domain logic, being
and the difference between unit and
explicit, and describes how
functional testing.
refactoring depends on code
ownership.
Part III: Evolutionary Design Part VI: Tuning Performance and Process
Martin Fowler on planned and Martin Fowler on balancing maintainability
evolutionary design, refactoring bad and efficiency, creating tunable software,
smells in code, and how good design the role of patterns, and the Agile Software
can help you program faster. Manifesto.

http://www.artima.com/intv/martin.html (1 of 2)05/12/2003 15:38:47


A Conversation with Martin Fowler

Sponsored Links

For way fewer bugs: Ask Adaption about Test-Driven


Development
Download Artima SuiteRunner Now - It's FREE!
Full version of Crystal Enterprise Professional 9 for FREE.

Search
Last Updated: Sunday, November 30, 2003
URL: http://www.artima.com/intv/martin.html
Copyright © 1996-2003 Artima Software, Inc. All Rights
Artima.com is created by Bill Venners
Reserved.

http://www.artima.com/intv/martin.html (2 of 2)05/12/2003 15:38:47


Reflection vs. code generation

Advertisement: Support JavaWorld, click here!

FEATURED NEWS & JW ABOUT


November 2001 HOME
TUTORIALS
COLUMNS
REVIEWS
FORUM
RESOURCES JW

Reflection vs. code generation


Avoid runtime reflection when marshaling data
ARCHIVE
Summary
TOPICAL INDEX Developers try to avoid tedious, redundant programming
Core Java at all costs. Solid coding principles such as inheritance,
Enterprise Java
polymorphism, and design patterns help developers
Micro Java
avoid code redundancy. But in the uncertain realm of
Applied Java
Java Community
software development, these principles cannot eliminate
the need for code maintenance and rewrites. To a large
JAVA Q&A INDEX extent, maintenance is unavoidable, and attempts to
JAVA TIPS INDEX create software that never requires maintenance only
results in software guaranteed never to work. However,
JAVA BOOK INDEX this article shows that you can use the power of Java's
Reflection API to reduce tedious code writing, and use
JavaWorld Services active code generation to overcome reflection
Free JavaWorld limitations. (3,000 words; November 2, 2001)
newsletters
ProductFinder
By Michael J. Rettig with Martin Fowler
Education Resources

White Paper Library


Printer-friendly version | Mail this to a friend

Page 1 of 3

ata Advertisement
marshaling
(pulling data from
an outside source
and loading it into
http://www.javaworld.com/javaworld/jw-11-2001/jw-1102-codegen.html? (1 of 8)05/12/2003 15:38:53
Reflection vs. code generation

a Java object) can


utilize the
benefits of
reflection to
create a reusable
solution. The
problem is simple
enough: load data
from a file into an
object's fields.
Now, what if the
target Java
classes for the
data change on a
weekly basis? A
straightforward
solution still
works, but you
must continually maintain the loading procedures to reflect any
changes. To further complicate the situation, the same problem
may crosscut the system's breadth. Anyone who has dealt with a
large system using XML has encountered this problem. Coding a
load procedure is often tedious and subject to frequent updates and
rewrites due to changes to the source data or the target Java class.
A solution using reflection, which I'll describe here, often requires
less coding, and updates itself when changes are made to the target
Java class.

Originally, I intended to demonstrate a solution using reflection


during runtime for data marshaling. Initially a dynamic, reflection-
based program was far more attractive than a simpler approach.
Over time, the novelty faded to reveal the complexity and risk of
runtime reflection. This article charts this evolution from runtime
reflection to active code generation.

From simplicity to complexity


My first solution used a loading class to load the objects' data from
a flat file. My source code contained several dozen calls for the next
token of a StringTokenizer object. After several refactorings (see
Martin Fowler's Refactoring), my coding logic became
straightforward, nearly systematic. The class structure dictated

http://www.javaworld.com/javaworld/jw-11-2001/jw-1102-codegen.html? (2 of 8)05/12/2003 15:38:53


Reflection vs. code generation

code. My initial solutions showed me that I needed only to account


for three basic objects:

1. Strings
2. Objects
3. Arrays of objects

You could map the class's objects to generalized code blocks, as


shown in the following table:

Objects mapped to generalized code blocks

Field type Code block

fileIterator.nextString();
String

Vector collector = new Vector();


while(fileIterator.hasMoreDataForArray()){
Object data = initializeObject(fileIterator)collector.add(data);
Object[] }
Object[] objArray = new Object[collector.size()];
collector.copyInto(objArray);

initializeObject(fileIterator);
Object

Having coded the solution several times, I knew the solution and
the code structure before I wrote any of the code. The difficulty
arose from the classes' changing landscape. The class names,
compositions, and structures could change at any moment, and any
change could force a rewrite. Given these changes, the structure
and loading process still remained the same; I still knew the code
structure and composition before I wrote the code. I needed a way
to translate the coding processes in my head into a reproducible,
automated form. Since I am an efficient (i.e., lazy) programmer, I
quickly tired of writing nearly identical code. Reflection came to my
rescue.

Marshaling usually requires source and target data maps. Maps can
take the shape of a schema, DTD (document type definition), file
format, and so on. In this case, reflection interprets an object's
class definition as the target map for our mapping process.
http://www.javaworld.com/javaworld/jw-11-2001/jw-1102-codegen.html? (3 of 8)05/12/2003 15:38:53
Reflection vs. code generation

Reflection can duplicate the code's functionality during runtime. So


during a required rewrite, I replaced the load procedure with
reflection in the same amount of time it would have taken me to do
the rewrite.

The load process can be summarized in the following steps:

1. Interpret: A map decides what you need to construct an


object.

❍ If you need to construct other objects first, recurse;


repeat step 1.

2. Request data: To fulfill construction requirements, a call is


made to obtain data.

3. Pull: Data is extracted from source.

4. Push: Data is stuffed into an object's new instance.

5. If necessary, repeat step 1.

You need the following classes to fulfill the steps above.

● Data classes: Instantiate with the data from the ASCII files.
The class definitions provide the map for the data. The
following must be true of data classes:

❍ They must contain a constructor that takes all the


required arguments to construct the object in a valid
state.

❍ They must be composed of objects that the reflective


procedure knows how to handle.

● Object loader: Uses reflection and the data class as a map to


load the data. Makes the data requests.

● Load manager: Acts as an intermediary between the object


loader and the source data by translating requests for data
http://www.javaworld.com/javaworld/jw-11-2001/jw-1102-codegen.html? (4 of 8)05/12/2003 15:38:53
Reflection vs. code generation

into a data-specific call. This enables the object loader to be


data-source independent. Communicates through its interface
and a loadable class object.

● Data iterator interface: The load manager and load class


objects use this interface to pull the data from its source.

Once you create the supporting classes, you can create and map an
object with the following statements:

FooFileIterator iter = new FooFileIterator(fileLocation,


log);
LoadManager manager = new FooFileLoadManager(iter);
SubFooObject obj =
(SubFooObject)ReflectiveObjectLoader.initializeInstance
(SubFooObject.class, manager,log);

With just this bit of magic, you create a new instance of a


SubFooObject containing the file contents.

Limitations
Developers must decide on how best to solve a problem; often, the
toughest part is deciding which solution to use. Below are some
limitations to keep in mind when considering using reflection for
data marshaling:

1. Do not make a simple problem complex. Reflection can be


a hairy beast, so only use it when necessary. Once a
developer understands reflection's power, he or she may want
to use it to solve every problem. Be careful not to solve a
problem with reflection that you can solve more easily, and
more quickly, without it (even if it means writing more code).
Reflection is as dangerous as it is powerful.

2. Consider performance. Reflection can be a performance hog


because it takes time and memory to discover and manipulate
class properties during runtime.

Next page >


Page 1 Reflection vs. code generation

http://www.javaworld.com/javaworld/jw-11-2001/jw-1102-codegen.html? (5 of 8)05/12/2003 15:38:53


Reflection vs. code generation

Page 2 Reassess the solution


Page 3 Compare working solutions

Printer-friendly version | Mail this to a friend

Resources
● Obtain the source code for this article:
http://www.javaworld.com/javaworld/jw-11-2001/codegen/jw-
1102-codegen.zip
● The Pragmatic Programmer, Andrew Hunt and David Thomas
(Addison-Wesley, 2000; ISBN: 020161622X) is an excellent
source for advanced programming practices and principles
such as code generation:
http://www.amazon.com/exec/obidos/ASIN/020161622X/
javaworld
● "Continuous Integration," Martin Fowler with Matthew
Foemmel, provides an informative look at successful
continuous integration, plus more information on how to use
Ant for a painless integration effort:
http://www.martinfowler.com/articles/continuousIntegration.
html
● Refactoring: Improving the Design of Existing Code, Martin
Fowler (Addison-Wesley, 1999; ISBN: 0201485672) -- without
well-factored code, the realization that code generation is
even a possibility is an impossibility:
http://www.amazon.com/exec/obidos/ASIN/0201485672/
javaworld
● Visit the Ant homepage to learn how to use Ant to automate
your build process:
http://jakarta.apache.org/ant/
● JUnit -- a simple, free unit-testing tool:
http://junit.org
● "Make an EJB from Any Java Class with Java Reflection," Tony
Loton (JavaWorld, December 2000):
http://www.javaworld.com/javaworld/jw-12-2000/jw-1215-
anyclass.html
● "Code Generation Using Javadoc," Mark Pollack (JavaWorld,
August 2000):
http://www.javaworld.com/javaworld/jw-08-2000/jw-0818-
http://www.javaworld.com/javaworld/jw-11-2001/jw-1102-codegen.html? (6 of 8)05/12/2003 15:38:53
Reflection vs. code generation

javadoc.html
● For more articles on Object-Oriented Design and
Programming, check out JavaWorld's Topical Index:
http://www.javaworld.com/channel_content/jw-oop-index.
shtml
● For more articles on Java APIs, visit JavaWorld's Topical
Index:
http://www.javaworld.com/channel_content/jw-apis-index.
shtml
● Subscribe to JavaWorld's free weekly email newsletters:
http://www.idg.net/jw-subscribe
● Speak out in our Java Forum:
http://forums.devworld.com/webx?13@@.ee6b802
● You'll find a wealth of IT-related articles from our sister
publications at IDG.net

Top Offers
Airports and Travel Guide: QuickAid.com Airport Directory and commuter
information. Browse airport or city for hotel and car rental discounts. USA
and major world destinations.

Mortgage Lenders Plus.com

#1-Refinance.com

Discount Hotels Discount Hotels Online features discount hotel reservations in top cities
around the world including New York, Las Vegas, Orlando, and London.

Nitro Electricals Buy cheap electrical appliances using Nitro Electricals price comparison
search engine. Find the cheapest fridges, hifi, TV's, DVD's and digital cameras.

Payday Loans & Cash Advance Get up to $500 instantly deposited into your bank
account in just two minutes, regardless of your credit!

Coupons & Coupon Codes- Get discounts & coupon codes for online merchants.

http://www.javaworld.com/javaworld/jw-11-2001/jw-1102-codegen.html? (7 of 8)05/12/2003 15:38:53


Reflection vs. code generation

Advertisement: Support JavaWorld, click here!

HOME | FEATURED TUTORIALS | COLUMNS | NEWS & REVIEWS | FORUM | JW RESOURCES | ABOUT
JW | FEEDBACK

Copyright © 2003 JavaWorld.com, an IDG company

http://www.javaworld.com/javaworld/jw-11-2001/jw-1102-codegen.html? (8 of 8)05/12/2003 15:38:53


Enterprise Transforming Projects That Don't Kill the Enterprise

About Contact
Home Blog Articles Books ThoughtWorks
Me Me

Enterprise Transforming Projects That Don't Kill


the Enterprise
Last Significant Update:

This article is based on a talk I gave at LOMA, an insurance industry conference, in 2001. In it I examine
a few software development projects that ThoughtWorks has done which are, to some degree "enterprise
transforming". The talk (and paper) are aimed at a non-technical audience. From the projects I draw out
some common lessons learned. In essence these are: Deliver Frequently, Expect Surprises, Get High Level
Executive Support, Treat Business and Software Development as Partners, Choose Technology for the
Future, People are The Critical Success Factor, and Keep Learning. A version of this article was recently
published in Resource magazine.

| Turkish |

● Project Sketches
❍ Project Chardonnay

❍ Project Grenache

❍ Project Temprenillo

❍ Project St Emilion

● The Lessons Learned


❍ Deliver Frequently

❍ Expect Surprises

❍ Get High Level Executive Support

❍ Treat Business and Software Development as Partners

❍ Choose Technology for the Future

❍ People are The Critical Success Factor

❍ Keep Learning

● Agile Development

In developing business software, from time to time you come across projects that are "enterprise
transforming". Such projects are special because they are projects that alter the business processes of key
parts of a business. As such they go well beyond software that automates some existing process or makes
general information available. These are the projects that cause job descriptions to change, process to be
done in different ways. Done well these projects that make a significant difference to the bottom line and

http://www.martinfowler.com/articles/enterpriseTransformation.html (1 of 12)05/12/2003 15:38:55


Enterprise Transforming Projects That Don't Kill the Enterprise

the competitive position of a company.

But doing these projects is peppered with risks. Software development is a tricky business at the best of
times, but when the consequences are so vital all the risks go up. Furthermore they are compounded by the
changes in business process, which would be risky even without the software. As a result enterprise
transforming projects have their set of special issues to bear in mind.

Over the last few years, ThoughtWorks has been involved in several enterprise transforming projects.
Most (but not all) have been successful. All have taught us lessons, both in things gone well and in things
gone badly. In this essay I'll explore some case studies (with names changed to protect the guilty). Then
we'll explore some general points from this and other experiences I've come across in the industry.

Project Sketches
Here's a quick overview of the projects. I'm not going to go into detail here, just enough to give you an
outline of what the projects are so you'll recognize them when I talk about the lessons learned later on. I've
given them all code names using names inspired by one of my preferred activities. I'll use the code name
(eg Chardonnay) to refer to the project, and something like Chardonnay-Corp to mean the client company
for that project.

Project Chardonnay

Chardonnay-Corp is a well known manufacturer who produces expensive items (I have to be vague!).
Increasingly much of their revenue comes from leasing these items rather than selling them. Leasing is an
arcane and complicated business. As their leasing business grew, their computer systems needed to grow
too. That's where we came in - to build what's referred to as a front end leasing system. A front-end
leasing system handles all the stuff that occurs before you sign (or in leasing lingo, book) the lease. This
includes credit checking the lessor, quoting the deal, origination, and producing the documents. Before we
started most of these operations were semi-automated at best.

The system we've built would satisfy the dreams of many technologists. It uses all the latest Enterprise
Java technology - EJB, JSP, and other TLAs. The important thing, of course, is what it's done to the
business. It's allowed Chardonnay-Corp to consolidate its offices moving from several regional offices to a
single office, reduced the amount of people (while retaining the amount of leases processed), brought
more consistency to the process, and improved the cycle time - getting a quote used to take two days, now
it takes 45 minutes. Also the wonder of the Internet has allowed Chardonnay-Corp's dealers to access the
system directly for quotes, which helps make Chardonnay-Corp's products more attractive to customers

Project Grenache

Grenache-Corp is a major retailer, one of those that has a branch in every boring mall in America, not to
mention every chique shopping street I've ever tried to elbow my way through. Like any retailer they are

http://www.martinfowler.com/articles/enterpriseTransformation.html (2 of 12)05/12/2003 15:38:55


Enterprise Transforming Projects That Don't Kill the Enterprise

very concerned with their supply chain. They have to get goods to their affluent customers from their less
affluent suppliers. They have warehousing complexities that are a nightmare. Every SKU has multiple
different varieties.

Although I'll refer to Grenache as a single project, in fact it's a series of projects each of six-nine months in
length carried out over the course of four years. Each project worked on a particular problem, such as
hordes of containers arriving at a distribution center before Christmas and sitting there for days while
people worked out what relationship the items in the containers had to items the retailers were actually
expecting (the answer is "less than you'd think"). We built the systems using Forte technology built on a
common relational database.

Project Temprenillo

Temprenillo-Corp rents out shipping containers - containers that vary from plain metal boxes to complex
and cavernous refrigerators. A shipping company rents the containers, moves them around the world for a
while, and then drops them off. An important role computers can play helping track where the containers
are and when they are going to be picked up. Temprenillo-Corp's existing system wasn't Y2K compliant,
and initially a new system was seen as the cheapest way to fix this. It didn't take long, however, before this
evolved into an enterprise transforming system. We developed this in Forte (we used to do a lot of work
with Forte).

Project St Emilion

St Emilion looks rather like Chardonnay - well at least the projects do. Big company, front end leasing
system, Enterprise Java with bells on, there's a lot of overlaps. (And yes there was some reuse involved.)
Differences include the fact that St Emilion-Corp's very expensive items are also technologically very
advanced, so they become obsolete the moment they start manufacturing them. So a big benefit of St
Emilion was allowing better control of inventory, which we did by tying into their ERP system. Also St
Emilion-Corp's leasing business was less mature than Chardonnay-Corp's, so there was a greater benefit in
putting together a consistent approach to quoting. Having salespeople put together deals on spreadsheets
was flexible, but caused havoc in accounting and profit management.

The Lessons Learned

Deliver Frequently

If there's any one thing that's struck me as a common difference between success and failure between these
kinds of projects, it lies in frequent delivery. I've often ran into people who talk about the major enterprise
transforming initiative they are currently working on. They speak with great enthusiasm about how well
things are going now that they're two years into a five year program. Although I'm not a statistically valid
sample, I find it significant that I've yet to meet this level of enthusiasm five years into a five year
program. The best I usually get is "we would have succeeded if...."

http://www.martinfowler.com/articles/enterpriseTransformation.html (3 of 12)05/12/2003 15:38:55


Enterprise Transforming Projects That Don't Kill the Enterprise

The common theme of our successful projects is that of frequent delivery of working software throughout
the life of the project. Indeed the growing theme is that the more recent the project, the more frequently
we've tried to deliver. Grenache, the older project of the bunch, delivered every six to nine months.
Although this was a grand plan to overhaul the supply chain, each project was a separate project, designed
to be a viable business proposition all on its own. The informal tale was that typically these projects would
pay for themselves twice within a year. Chardonnay is a more recent example, highlighting the trend to
shorten the cycle. Here we deploy new software every two or three months.

Why is this important? For a start it's about building credibility. Businesses are not famous for being
patient while they put a lot of money into an initiative. Even when you do get somebody who's prepared to
sponsor a five year plan for overhauling the company, that person is not likely to last the whole five years.
Often the big new initiative becomes a millstone around their neck sometime about year three. Unless
somebody can show viability at that stage either the project is sacrificed, or the sponsor and the project
find themselves without a home.

On the other hand deliveries build credibility, especially if you see benefits: reduced costs, increased
timeliness - these count far more than hoped benefits. As people see the system in action they can see the
value it brings, and also the changes it forces. This visibility also helps the credibility of the software
developers. There's nothing worse than the business folks lamenting that while they hear confident project
briefings, they don't actually know if the project is on track. Deployed software is tangible, and gives a
clear statement of progress. Sometimes this isn't so good, if things are going slower than hoped. Yet even
in this case I find it's worthwhile. If development slows down you can only hide it for so long. Eventually
reality has a nasty habit of catching up with you. But if people see steady progress they are either more
understanding of delay, or will cancel a project earlier. Either of which is better for the business than a
long drawn out failure.

Frequent delivery also allows you to learn from your development. That sounds like an odd phrase to
many, yet our experience is that when doing this kind of project, nobody really knows what the whole
picture is. You can know where you're going if you've ploughed that route before, but enterprise
transformation means going into a whole new world. One that's unpredictable for client and contractor
alike. While at St Emilion we were able to bring our experience of front-end leasing software to bear (it
was our fourth such system), the truth is that at that scale every business has enough different twists to be
a new journey.

This is compounded by the fact that enterprise transforming projects often involve very new technology
(I'll discuss why later). In this case the early deliveries should focus on allowing the technologists to learn
about the technology and explore some of the high risk areas.These discoveries will be both good and bad,
so make them early so you can adjust your plans accordingly.

There is an alternative to exploring new ground. That is to not try an enterprise transforming project until
others have trod the ground before you. That way, of course, you have some idea of where to go. The
problem with that, of course, is by the time you get to the party, all the food's gone.

http://www.martinfowler.com/articles/enterpriseTransformation.html (4 of 12)05/12/2003 15:38:55


Enterprise Transforming Projects That Don't Kill the Enterprise

As I've talked about this, I've talked about delivery in terms of delivery to the business, that of putting the
software into production. However this notion can be extended further. Even within a deployment cycle of
several months, the software developers can build the software in tighter cycles: as short as a few weeks.
While you may not want to put each of these cycles into production you can still get many of the learning
and tracking benefits with these development iterations. In the last year or so we've been using these kinds
of short internal cycles on several of our projects, and as we see more success with this we are doing it
more and more.

Expect Surprises

As I've alluded to earlier, enterprise transformation is not a predictable exercise. New business processes
mean you're heading into territory that is only known vaguely, if at all. With these kinds of projects come
surprises. Some these can be bad surprises, some of them good. Only by reacting to them can you avoid
the damage of the bad ones, and maximize the gains of the good.

Temprenillo provided examples of both kinds. On the bad side of the coin there was the unpleasant
discovery about repairs. When the project was initially planned, it was expected that the tracking of the
repairs to containers would be a small part of the project. As the project went on we found out that about
half the work was in tracking repairs. This caused a big increase the costs and timelines of the project. In
this circumstance the only thing to do was to look at problem squarely and rework the plans.

I've seen the alternative, trying to carry on as if the original plan is still valid in order to avoid the failure
of deviating from the plan. It leads to a divergence between the plan and reality. You can sustain this for a
while, occasionally you may even get back on track due to other more pleasant surprises. But more often
the divergence continues until the difference is so big that reality can't be ignored any longer. The fall out
is usually very painful.

For the happier alternative, these can come in many ways. Greg, our project manager on Temprenillo, tells
the story of the business folks looking at the fact that we now had a relational database for tracking the
containers. Suddenly they realized that they were a simple SQL query away from finding all the
companies that were being laggardly in doing, and paying for, repairs on containers. The access to this
information was simple, yet saved Temprenillo-Corp a considerable amount of money. This benefit was
simply overlooked in the project plans, yet turned out to be a significant benefit of the new system, worth
a short detour to realize.

Temprenillo also had a bigger example of this. Temprenillo-Corp does a lot more than rent containers, and
a new executive management decided to sell off parts of the container renting business. As they did this
they discovered that the pieces to sell off were the unusual containers, such as the enormous fridges. The
new system made it possible to easily separate these lines of business, which would have been a nightmare
in the old system. Not just that, but it was not difficult to modify the system so that Temprenillo-Corp
could sell off the business for the "tanks" (transport chemicals, food products, etc.) and still use the system
to manage the containers for the buyer, thus getting money at both ends of the bargain. No amount of in
depth requirements analysis could have predicted this change, because it was a deep business change.

http://www.martinfowler.com/articles/enterpriseTransformation.html (5 of 12)05/12/2003 15:38:55


Enterprise Transforming Projects That Don't Kill the Enterprise

Faced with this unpredictability, it's tempting to conclude that planning is hardly worth the effort. After all
if plans are likely to be discarded part way though the project, what value do they have? But in reality we
find that planning is all-important in these unpredictable projects. It's just that planning is done with
different emphasis, in particular it becomes a continuous planning process, where plans are reworked at
regular intervals. In this environment long term plans are both volatile and sketchy, but still help set
directions. Short term plans are more stable, although still open to shifts when needed.

Chardonnay is an excellent example of this kind of process. While the team is working on the software for
the current two month deployment, an analyst team works out what needs to be done for the next two
months. I asked Scott, Chardonnay's project manager, what he knew of the tasks for six months ahead. "A
list of bullet points, I don't know what most of them mean, and I don't think the customer does either." Yet
this project has continued to be a success for both ThoughtWorks and Chardonnay-Corp.

Get High Level Executive Support

This is no surprise, or at least it shouldn't be. Big changes in business process need commitment from the
top of the business management tree. Without it, nothing's going to happen. Transforming change is rarely
welcome, but human beings naturally prefer the devil they know to the unknown future, however nice
people tell them it'll be. Overcoming this natural resistance requires leadership, and plenty of it.

High level leadership is also needed to provide a vision for the future. This may not be a very detailed
vision, but given the nature of these projects it doesn't need to be. What it does need is something to guide
progress, even as plans are changing. This involves setting priorities, making hard choices about what to
do and what not do. We've also found it's important to maintain a commitment to the frequent deliveries
that I talked about earlier. Often there is the temptation to put off a deployment, to make time for some
really neat features. But one neat feature leads to another, and soon you get led into the trap of not
delivering and losing the credibility and learning advantages. Here it helps to have very frequent
deployments. If Chardonnay has to skip a feature in the current deployment, it's only a two month wait to
the next one. With that short time interval it's easier to make the hard decision of what not to do.

What happens if you can't get the high level business support you need. Our advice overwhelmingly is:
don't bother with the project. That may sound a little harsh, especially if the project is one that you're
convinced is good for the company. Yet there's only so much executive attention around, and without it
enterprise transformation has about as much chance of success as putting your salary on 15 at Las Vegas.

Even if a project gets executive support, it's not at all certain that it'll keep it. At Grenache, the original
leaders moved on to new pastures. That's not surprising - successful people like to move on to new
challenges. The new leader fancied a different approach relying on ERP systems rather than custom
software. Again this is a natural human behavior, new people often prefer to take a different approach to
their predecessor even if the current set up is working. As a result the Grenache initiative has ended before
revamping the whole supply chain. Frequent delivery is again a valuable technique. Even though the
whole grand plan of Grenache hasn't been realized, since all the constituent projects were successful, and

http://www.martinfowler.com/articles/enterpriseTransformation.html (6 of 12)05/12/2003 15:38:55


Enterprise Transforming Projects That Don't Kill the Enterprise

gave an excellent ROI, the business has benefited from the work so far. Not just is the money not wasted,
it's delivered well on the investment.

Treat Business and Software Development as Partners

Perhaps one of the hardest things to do in an enterprise transforming project is to ensure there's a true
partnership between the business and technology sides of the project. Of course we notice this because we
are a separate company to our clients, but you often find this on an in-house project as well. Business
people and technical people are different personalities with different aims and personality styles.

Even with an in-house technology group there is a strong desire to make the arrangement one of a fixed
price contract. Here's what we need, go ahead and build it, tell us when you're done. But as I've indicated
already, these kinds of project aren't like that - there's too many surprises involved. I agree completely that
a fixed price contract would be better, if only it would work. However a fixed price contract depends on
very well understood set of requirements. There are software projects that have these, but you don't find
these in enterprise transforming projects. Hence the need for a different approach to planning - and a
different approach to the business/technology relationship.

The partnership I'm talking about requires the kind of joint planning which I've talked earlier. One that
expects that new requirements will appear, that problems both in business and technology will crop up. As
soon as the two parties start battling over what they agreed to, the project is in serious trouble. In this kind
of relationship you have to rely on trust, if that trust breaks down, then the project will go with it. Now
that may happen, I've certainly seen cases where the technology supplier wasn't delivering the goods. In
that case the project needs to be terminated, or at least put into mothballs until a new supplier's found.

So how do you find a supplier that you can trust? (I'll try to resist the urge to just say "call
ThoughtWorks".) The obvious advice is to try to do the project in-house. That's odd advice for someone in
a technology provider company to give, but at the risk of giving our sales VP an apoplexy I'll give it
anyway. With an in-house team you take away a substantial piece of commercial tug-of-war. Indeed I used
to believe that these kinds of projects should be done in house rather than with a technology company such
as ourselves.

What changed my mind? (Other than the monthly pay check.) The problem is that many companies just
don't have the resources to do this work in house. Technology companies can offer software professionals
a greater range of interesting projects using leading edge technologies than most businesses. They also
offer a free wheeling environment that's more geared to geeks like me. As a result of this they get better
geeks. In enterprise transforming projects you usually need the best geeks you can get, so this is an
important thing to bear in mind.This doesn't mean you have to give the project over entirely to a
technology company. We do a lot of work that uses teams that are a combination of ThoughtWorkers and
client staff - both Grenache and Temprenillo succeeded with this model.

It's important to realize that it's not just a bunch of smart geeks that you need. People who work well
together are far more effective than a brighter group of people who don't work together. So don't look for a

http://www.martinfowler.com/articles/enterpriseTransformation.html (7 of 12)05/12/2003 15:38:55


Enterprise Transforming Projects That Don't Kill the Enterprise

bunch of clever bodies, but for a team of people who have a common culture and have worked together
before. It's also good to find managers and analysts who are also part of this culture and are used to
working with this kind of group.

So if you need to shop outside, how do you select your technology provider for a project like this? One
factor is the quality of their people. Make sure that they really do have the staff to carry the job out.
Looking at resumes isn't usually enough. Often a good way is to find a project where they can send in
some of their people to work on for a few months. During this time you can evaluate their skills and get to
know their culture. Look at their previous projects. The business domain is less important here, although it
certainly helps if they've done this business before. The key thing is to see if they've succeeded in working
with a client in this partnership style. Checking references is the obvious and wise step. Look at their
reaction to working with people from other technology providers. I've found that companies that seek to
get rid of people from outside usually do so out of a well-deserved lack of confidence.

Of course once you select your technology provider, you have to monitor how things go. Ronald Reagen's
famous quote "trust but verify" comes to mind. You need tangible signs of progress. A clear project plan
with milestones that you can verify is the key here, and you shouldn't be surprised when I repeat my
refrain of frequent deliveries. There's nothing better than working software to measure progress.

Also expect snags, and expect the technology provider to be up front about them. Temprenillo provides an
excellent example of why this is important. As I've mentioned earlier we were four months away from
delivery when it became clear that the repair part of Temprenillo was far more complex than anyone
realized. The project had to slip several months. Being open about the situation was important, as was a
client project manager who evaluated the situation and agreed with the assessment. While this meant the
project was later than hoped for in giving full function, it was still a success and by using iterative delivery
we were still able to ship partial but still useful software.

Notice that this example shows the importance of having a business project manager who is deeply
involved with the project and is thus able to understand the issues that come up. While this isn't
completely essential, we often manage without one, it certainly helps.

Of course when things go wrong they're occasionally our fault, after all we're not perfect. But again the
key is to work to find a solution. On St Emilion we made the mistake of under estimating the complexity
of the job and ended up putting in an initial team that weren't experienced enough. When we discovered
this, the project was in difficulties. While we did a part by sending a squad of more experienced folks that
were prepared to take emergency measures, it was also vital that our client also helped by re-planning the
work. From the beginning we had been very open about the risks and that openness helped to develop the
necessary trust. In the end St Emilion succeeded, but it took both of us to make some sacrifices to make it
so.

Choose Technology for the Future

There is a particular problem with choosing technology for a project such as this. You can't make the

http://www.martinfowler.com/articles/enterpriseTransformation.html (8 of 12)05/12/2003 15:38:55


Enterprise Transforming Projects That Don't Kill the Enterprise

decision on what is the best technology now, you have to evaluate what the best technology will be for
when the project is in full flow, several years later. With technology changing as it has, that's a tricky
choice.

Grenache and Chardonnay are interesting contrasts here. Grenache started in the mid 1990's and selected
Forte. In many ways Forte was an excellent choice because it was a maturing platform for multi-tiered
information systems. It has many features that more popular platforms don't have now. As it turned out,
however, Forte got hit by the Java steamroller and is now a technology without a future. In 1995 this was
impossible to predict (Java only started to appear that year) so it was only a poor decision in 20/20
hindsight.

Chardonnay's an example of the right choice. In 1997 enterprise Java technology was a risky choice. The
tools and technologies were very immature, much less mature then Forte, or established client server tools
like Powerbuilder and VB. Yet things panned out very well. The immaturity of both tools and knowledge
about enterprise Java certainly made things slower than they could have been, but now enterprise Java has
proven a stable platform with a future that has many companies behind it.

Not just is the platform choice one of tools in the longer term, it also affects the people you can get.
Software developers tend to be intelligent, especially the better ones. As such they know that working with
dying technology is a career limiting move. So they will gravitate away from technologies that seem to
have a doubtful future. It got harder and harder to find people prepared to work on Grenache, even before
the Java world really began to catch up technologically.

In the face of this, it becomes important to pick an integration strategy rather than a full technological
platform. In Grenache this was apparent from the beginning since the projects that made it up were done
separately. For Grenache this platform was a relational database. Every project was expected to work with
a common relational database that acted as the shared base of the data. As a result the different projects
could operate with a fair degree of independence. Such an approach also gives Grenache a way out of the
Forte problem, future development could be done in Java, although Forte is still needed to modify the
existing system.

In our enterprise Java we've made extensive use of using XML for communication between processing
units as well as working more and more with the Java platform. As well as the good prognosis for Java we
see XML as something that also has the potential to be around for a long time. XML receives a fair
amount of hype, but it has an important place in enterprise development.

Although it's slightly tangential to this theme, this is a good moment to throw in some advice about that
most-touted benefit of object-oriented platforms: reuse. Over the years I've run into plenty of people
who've talked about building a foundation of reusable frameworks on which they intend to build the next
generation of applications. I've run into hardly any successes. That's even not taking into account the
problems when technology platforms disappear. The problem is that it's very hard to build frameworks
from scratch. Grenache has a typical example: a sophisticated security framework that took a long time to
build and ended up being more complicated than it needed to be.

http://www.martinfowler.com/articles/enterpriseTransformation.html (9 of 12)05/12/2003 15:38:55


Enterprise Transforming Projects That Don't Kill the Enterprise

For a while now my view, and that of quite a few other frameworkers, is that frameworks need to be
evolved as part of the applications that use them. Build a couple of applications and then harvest a
framework from the commonalities. The resulting framework is then designed for known needs rather than
speculation. I need to warn you that this isn't easy, indeed it's no easier than building an initial foundation -
the only difference is that it's much more likely to work.

People are The Critical Success Factor

What really makes a project like this succeed is the people who are doing and how they work together. In
the end this is the single most important factor. Technology choices, methodologies, business volatility, all
these play second fiddle. A good group of people who work well together will find ways to surmount the
insurmountable problems, while a poor team won't try to get over a six foot wall. So if you're responsible
for such a project the most important thing to do is get good people, keep good people, and ensure they
work together well.

Getting and keeping good people is primarily about giving them the responsibility to carry out their job
properly. I've heard a lot talked about empowerment and new approaches to managing people, but in
practice this rarely seems to get beyond providing free coffee.

What people find difficult is actually stepping back and allowing a team to make the choices about what
they know about, and to ensure the people who make decisions are the ones who have knowledge to make
them. Technologists need to be trusted to make the technical decisions, business experts need to be trusted
to make the business decisions. The role of management is often to ensure that the right people make the
right decisions.

The other key role of management is to ensure that there is a rich and regular flow of information. Look
for organizational and physical barriers to communication and remove them. A lot of this lies in simple
things. Make sure people who work together sit closely to each other. Make sure there are plenty of
meeting rooms for collaborative work. Invest in team building activities. A team that gels is worth a lot of
effort to create

Particularly important here is regular contact between business experts and the development team.
Grenache followed the practice of assigning a business expert full time to the team for the duration of the
project. Chardonnay has a large group of ThoughtWorks leasing experts who work with Chardonnay-
Corp's business experts, identifying key supervisors who know the hows and whys of Chardonnay-Corp's
business process.. What's needed is regular face to face contact, typically you'll find daily interaction
between business people and developers. This is often ignored to a project's cost as communications and
trust breaks down. The business side has to put in people to the project if they want it to be a success.

The key test of whether this arrangement is working is the reaction to bad news. Inevitably there will come
times when the developers on the ground will run into problems, often those that will hit the schedule. If
the management's reaction is to hide things or to tell everyone to just "work harder", then you haven't got

http://www.martinfowler.com/articles/enterpriseTransformation.html (10 of 12)05/12/2003 15:38:55


Enterprise Transforming Projects That Don't Kill the Enterprise

the kind of management that will work effectively. An honest reaction to problems and an openness to
them is important both to work effectively with developers and to be a good partner to the business.

Keep Learning

Working in a complex and new ground inevitably leads to discoveries. As I've discussed above, the
important thing to do with surprises is to learn from them. Indeed a key theme of a successful long term
project is a notion of continuous learning. This learning is about the needs of the business, the technology
we're working with, and process with which were doing the work.

One of the common discoveries of software development is the fact that people change their mind about
requirements once they see early versions of a system. This is a natural effect because the presence of the
system clarifies things for business people. As a result they learn about both their needs and about what
technology can provide. One of the benefits of frequent deliveries is that it accelerates this learning
process. The business people should use these deliveries, and their immersion in the development process,
as a vehicle to learn more about what would be valuable as the software develops. Both Chardonnay and
St Emilion gained a great deal from the short development cycles to help the business folks guide the
project to deliver the most valuable functionality

Continuous learning also applies to technology. Since enterprise transforming projects often use newer
technologies, learning is essential to make the best use of technology. When technologies are new or
evolving rapidly (and what isn't these days) many of the best ways of using the technology are not clear
early on. Also there's bound to be some hidden gotchas that also don't appear early on. A good team looks
at the technology it's using and alters their approach as the project continues to use the technology in the
best way. St Emilion and Chardonnay were a couple of the earliest serious projects using enterprise Java.
Both teams learned a great deal about how enterprise Java should be used and evolved the system to take
advantage of that learning, and learning from other ThoughtWorks projects and flood of articles on using
Java.

Often the easiest form of learning to miss is the importance of learning about the development process. At
regular intervals it's important to look at how the team is working and for the team to think about how to
improve. St Emilion had a number of key retrospectives where both the development team and the client
team reviewed the process and decided how to improve. These process checks were essential in turning
the project around from a project in trouble to a banner success. On the other hand Grenache became a
victim of its own success, and later projects did not evolve enough to take advantage of its own
experiences, which has led to less effectiveness in the last year or so.

Agile Development
These are ThoughtWorks's experiences, but these experiences are not alone to ThoughtWorks. The earlier
of these projects, particularly Grenache and Temprenillo, biased ThoughtWorks to what we'd now call an
agile style of software development. Outside ThoughtWorks there was a growing band of software leaders

http://www.martinfowler.com/articles/enterpriseTransformation.html (11 of 12)05/12/2003 15:38:55


Enterprise Transforming Projects That Don't Kill the Enterprise

that had come to similar conclusions. These conclusions have led in the last few years to the appearance of
a new breed of methodologies that are called agile methodologies.

These agile methods have also influenced ThoughtWorks. St Emilion in particular was influenced to the
point of adopting one of these methodologies: XP (Extreme Programming). XP puts a lot of emphasis on a
large amount of testing that's integrated into the programming cycle.This testing improved not just the
quality of St Emilion's code base, but also increased the speed of the development team by reducing the
time spent hunting for errors. It also gave a solid base that allowed St Emilion to evolve the design from
one that was a little too quick and dirty, to a design that will be a solid base for future development.

Both ThoughtWorks as a company, and I as an individual have come to the conclusion that agile
development is essential to success in enterprise transformation. We also both know that in the next few
years we will learn more about success in this demanding field. And that perhaps points to one of the most
important qualities for any organization that seeks to do this kind of work: a constant desire to improve.

© Copyright Martin Fowler, all rights reserved

http://www.martinfowler.com/articles/enterpriseTransformation.html (12 of 12)05/12/2003 15:38:55


Writing with XML

About Contact
Home Blog Articles Books ThoughtWorks
Me Me

Writing with XML


Last Significant Update: January 2003

For quite a while now, I've been doing most of my writing using XML - even to the point of writing my last
book in XML. As I've mentioned this to people they've asked me a number of questions about my
experiences, and that's been enough to prompt this little article on the whole thing.

● How I got started


❍ First steps - the refactoring catalog

❍ A web site and a book

● Typing in the text


● Converting to HTML
● Converting to print
● Diagrams
● Automatic Code Import
● Collaboration and Versioning
● Final Thoughts

How I got started

First steps - the refactoring catalog

I began working with XML around 2000, when my refactoring book came out. I'd already set up a web
site, and decided to add a new site to act as a portal of information about refactoring. On that site I list all
the refactorings in my book (together with a few others) and decided to use XML to store the refactorings,
that way I hoped that it would be easier to edit and update them.

On the whole I found web site work a bit of a pain. Writing in HTML is awkward, particularly if I want to
make global changes or to search the HTML files for useful information. Furthermore I couldn't easily
prepare material for both HTML and print use. My dream was always to write where I could have a single
piece of text that could be formatted either in HTML or in a good print form. None of the tools I had
available to me at that time really did a good job of both.

I've always been a fan of logical styles when writing. As soon as I start doing anything non-trivial in a

http://www.martinfowler.com/articles/writingInXml.html (1 of 6)05/12/2003 15:38:56


Writing with XML

word processor I like to set up logical styles that match the way the content of my writing is structured.
That way I can think about content and formatting separately - although as you can tell my HTML format
is hardly sophisticated. So the idea of writing text marked up with XML and then formatting separately for
HTML appealed to me a lot.

Although my efforts with the refactoring catalog were somewhat crude (or at least they seem that way to
me now) I was very pleased with how the process all worked. I wrote the book using framemaker and the
version then allowed a primitive, but effective, way to save the frame data in XML. The resulting XML
was okay, but it wasn't exactly how I wanted it, since it tagged the elements in Framemaker's vocabulary,
rather than the tags I wanted to use for the site. Fortunately XSLT is just perfect for fixing this problem,
and even though I was unused to XSLT, it was easy to write a stylesheet that would transform the
elements I wanted to keep, while filtering out the ones I didn't want on the site.

Once I had the files together, I was able to write another XSLT stylesheet to display the files as HTML.
One stylesheet formatted the lot, and should I want to change it, again I had only one place to change.
(The DRY principle is a good thing!)

Since each file was textual and well structured, I could also write a program to create the catalog index
file. This is Java program that reads each catalog file in the directory and writes out selected information
from each refactoring in the index. That way if I ever add or alter a refactoring, I just run the program to
update the index. By putting all this into an ant script, I can regenerate the whole site by just running ant's
build process. All in all I was very pleased with the whole experience

A web site and a book

Happy with my success with the refactoring catalog, I started to use XML and XSLT on my web site. I
started to write articles in XML and transform them into HTML. I like this because I don't have to bother
with all the formatting codes of HTML, I can just write with a simple set of tags in XML and let the
stylesheet take care of the rest. I can also use XSLT do tasks like automatically generate a table of
contents for each article.

So as 2001 went on I became steadily more skilled in this environment, and figured out how bend XSLT
to my will. It occurred to me that this might be time to work on a book in XML. So far all my book
writing had been done in Framemaker. Framemaker has its faults, but for me it's strengths were it solidity
and its awesome cross-referencing capabilities. However I was frustrated by its closed file formats, that
often meant I couldn't do tasks that weren't supported by the tool. You also can't script in Frame without
expensive and awkward add on software. The real issue for me, however, was that I wanted to put my
emerging book on the web in HTML, and I wasn't happy with Frame's conversion process, certainly not
compared with XML/XSLT.

So I embarked on my P of EAA book in XML, and all in all I liked the way it turned out. Suffice to say
that my next book will be written in XML too. I found it useful not just for me, but also there a few tricks
that were handy when collaborating with a co-author, particular when Dave Rice ended up in Australia.

http://www.martinfowler.com/articles/writingInXml.html (2 of 6)05/12/2003 15:38:56


Writing with XML

The strength wasn't so much XML, as the fact that XML is a plain text format, which opens up tools that
work well with plain text.

Typing in the text


It seems the first question people ask is "what do you type in the text with". The answer seems pretty
obvious to me - a text editor. As a programmer I'm pretty familiar with many text editors, and one of the
strengths of XML as a format is that you can use whatever text editor you like to type things in with. This
was great for collaborators since I didn't have to worry about getting expensive software to them to
contribute their sections to the book.

While I was writing the book, my text editor of choice was TextPad - surely the best $30 I've ever spent on
a piece of software. It's fast and full of simple but handy features. I found its clips library was really good
at tagging the text the way I wanted it.

I considered other XML editing tools, but wasn't keen on the various alternatives. Most of them wanted
DTDs to do anything interesting, and I only started using DTDs late in the game.

Just this last few months I've started using XEmacs. I've used emacs off and on for many years, but mostly
off as every computer I used seemed to either not have it, or the windows ports were very unknowing of
the rest of the system (I consider cut and paste to be basic functionality.) Xemacs 21.4 on windows is
pretty windows friendly. The SGML major mode works quite nicely for text based documents, particularly
if you have a DTD - which I now do. Of course you have to be used to emacs key combinations, which
seem very retro these days.

I've tried XML spy a couple of times, but it doesn't really suit my purposes. It's more focused on data
oriented XML and isn't really as nice for typing text. Once I got used to the key combinations I missed the
nice ones in XEmacs.

I'll see how things develop in the future. I could certainly imagine a better tool that a simple text editor,
but so far the text editors have beaten some very fancy and expensive tools.

Converting to HTML
This approach works particularly wonderfully when you are producing HTML pages. Writing in XML and
transforming with XSLT works very well for me.

It didn't start that way. XSLT is a pain of a language - a wonderful reason why you shouldn't use anything
XML based as a programming language. Some may find its lisp-like quality of data/program similarity to
be appealing. I just find it very hard to write and work with. It's also pretty complex, which doesn't help at
all.

http://www.martinfowler.com/articles/writingInXml.html (3 of 6)05/12/2003 15:38:56


Writing with XML

Despite its faults, XSLT is powerful. But there are a few tips to make your life saner

● remember that XSLT is like a functional programming language, it doesn't allow variables in the
normal way, so you use recursion when you want to loop.
● use it to match patterns not to drive the output. So prefer <xsl:template match = "foo"> to <xsl:for-
each>. (You'll be more comfortable with this if you've ever used awk.)
● Get Michael Kay's XSLT Programmer's reference. It's a dauntingly large book, but it is a very fine
reference. It isn't the greatest book to learn XSLT from, but I find it great in answering detailed
questions.

For producing HTML, and indeed in lots of other places, I relied on build scripts. For the book I had ant
scripts that built the code and built the book pages automatically. Having a build script made life much
easier.

All in all, however, I really like the separation that XML/XSLT gives me. I find it much easier to write
with a simple set of logical tags, even though my pages are very simple in their formatting. One day I'll
maybe have a fancy web site.

Converting to print
While converting to HTML is simple and obvious, books require a print style format. That was rather
more of an issue

My first attempt was to use XSL-FO with apache's FOP. At that time (early 2002) I found that while XSL-
FO clearly had all the capabilities I needed, FOP had limitations that defeated me - particularly for such a
large book. Another issue with the FOP route, at least at the moment, was that the publisher wasn't really
ready for it.

I see these issues as temporary. As we get better XSL-FO tools, then that will be an obvious way to
produce print-ready output. When I next need to produce print ready output, I'll give XSL-FO another look.

What I ended up doing was reverting to my trusty Framemaker. I did this by generating Framemaker files
automatically from the XML. I did this in two stages. The first was an XSLT transform that converted the
tags I used for P of EAA to tags that mirrored the subset of Frame I was using. Then I used a Ruby script
to convert from the Frame like XML to Frame's textual MIF format file. Using XSLT for the first step
worked well in doing all the hard futzing with the transform, but XSLT isn't good for handling the precise
text format needed by Frame. The combination of XSLT and Ruby worked perfectly.

Another option that's now available for XML to print is to use Open Office. Open Office's file formats are
zipped XML and they take care to separate content from formatting. As such it should be straightforward
to use XSLT to transform the content and add the formatting separately in Open Office. The future version
of Microsoft Word may well also support this kind of thing.

http://www.martinfowler.com/articles/writingInXml.html (4 of 6)05/12/2003 15:38:56


Writing with XML

Diagrams
My writing often contains diagrams, particularly UML diagrams, and I'm often ask what I use for that. I've
long avoided fancy CASE tools in preference to Visio - and even with Visio I don't use the standard UML
templates that come with the product. The trouble with CASE tools, and with Visio's UML templates, is
that they try to be intelligent. However their intelligence about UML is a lot less than the average
developer, so instead the tools just get in the way.

As a result I use a different set of templates developed by Pavel Hruby (see my links page for the link).

The big frustration with Visio is that it has annoying glitches on its output. When you output to gif, for
example, the results are not too good, frequently chopping the very top line of the figure. I'm looking
forward to more browser support for SVG and will probably experiment with Open Office's draw
capabilities in the future to see if it produces a better result.

One big thing I didn't do right away, was to have a script to automatically export all Visio diagrams to gif.
I did this later on (it checks to see if the Visio file was modified after the corresponding gif was produced).
Once I had the script life was much easier - fortunately Visio is really easy to drive with pretty much any
scripting language (in my case, Ruby).

Automatic Code Import


One of the nicest things about using this scheme was automatic code import for my sample code. Most
authors have nightmares on sample code, almost always something goes wrong and they have sample code
that isn't consistent or doesn't compile - just due to the difficulties of keeping copy and pasted code in sync.

I was able to do things much better. All my code examples were kept in directories where I could use Ant
to build and test the whole directory. I could then tag the source code file with commented tags to mark
sections of code to import into the book. I then wrote some simple Java code to whip through the source
files and produce XML files that contained the fragments from the source code. These fragments could
then be easily imported into output when I ran the XSLT. It was a wondrous removal of what otherwise is
such a messy process, and allowed me to confidently change my code examples whenever I needed to.

Collaboration and Versioning


I collaborated with several people on P of EAA - most noticeably David Rice who wrote a large section of
the book. With us both modifying both text and code examples we needed to coordinate our work
carefully.

The answer was CVS. Since XML files are just text, CVS proved a perfect way to handle our
collaboration. Any time we modified anything we uploaded the files to CVS. This became essential as we

http://www.martinfowler.com/articles/writingInXml.html (5 of 6)05/12/2003 15:38:56


Writing with XML

pushed against the deadline with David working in Australia.

Of course CVS was useful just for me personally. It allowed me to safely mess with the text any time I
liked, knowing there was always a solid version history of every file. We versioned everything, including
the various java libraries and .NET assemblies that our stuff depended on. Just as programmers should
always work with version control, so should authors!

Final Thoughts
Even in these early days of XML related technologies, I found XML a really good way to write a major
book. I now use it without hesitation for almost all the writing I do - including this article. (The main
exception is when I'm doing my IEEE Software column, they like to receive Word files and it's short
enough that I don't get the other usual problems.)

If you're wondering about using XML for a web site, report, or book; I'd warmly recommend it if you're a
geek and happy to mess around with XSLT, scripts and the like. If you're less geeky then I'd wait for the
moment - but keep a sharp eye on XML-aware word processors. If the new Word is anything like the
rumors, things will get interesting.

Revision History

Here's a list of the major updates to this paper

● January 2003:

© Copyright Martin Fowler, all rights reserved

http://www.martinfowler.com/articles/writingInXml.html (6 of 6)05/12/2003 15:38:56


$B7QB3E*%$%s%F%0%l!<%7%g%s(B

$B7QB3E*%$%s%F%0%l!<%7%g%s (B
$B86Bj (B: Continuous Integration

Martin Fowler
Chief Scientist, ThoughtWorks

Matthew Foemmel
ThoughtWorks

$B!V3NR2p$9$k!#$3$N%W%m%;%9$OA4

● $B7QB3E*%$%s%F%0%l!<%7%g%s$N287C (B
● $B$?$/$5$s$d$k$[$&$,K>$^$7$$ (B
● $B!V@.8y$7$?%S%k%I!W$H$O!) (B
● $B%7%s%0%k%=!<%9%]%$%s%H (B
● $B<+F02=$5$l$?%S%k%I%9%/%j%W%H (B
● $B<+8J%F%9%HMQ%3!<%I (B
● $B%^%9%?!<%S%k%I (B
● $B%A%'%C%/%$%s (B
● $B7k8l (B

$B5DO@$K$OEP$k$,!"/$J$$!V%Y%9%H%W%i%/%F%#%9!W$,%=%U%H%&%'%"3+H/$K$O$$$C$Q$$$"$k!#$=$NCf$G$b!"$b$C
$H$b4pK\E*$+$D=EMW$J$b$N0l$D$,!"!V40A4$K<+F02=$5$l$?%S%k%I$H%F%9%H%W%m%;%9!W$@!#$3$l$O!"%W%m%8%'%/
%H%A!<%`$,<+J,$N%=%U%H%&%'%"$N%S%k%I$d%F%9%H$r0lF|$K2?EY$b9T$&$3$H$r2DG=$K$9$k$b$N$G$"$k!#$b$A$m
$s!"KhF|$N%S%k%I!J%G%$%j!<%S%k%I!K!"$H$$$&9M$($,5DO@$5$l$?$N$O$3$l$,=i$a$F$G$O$J$$!# (BMcConnnell $B$O%G%$
%j!<%S%k%I$r%Y%9%H%W%i%/%F%#%9$H$7$F?d>)$7$F$*$j!"$^$?%^%$%/%m%=%U%H$G$N3+H/%"%W%m!<%A$NFCD'$H
$7$F$bD9$/CN$i$l$F$$$k!#$7$+$72f!9$O!" (BXP $B%3%_%e%K%F%#$N@<$K$J$i$C$F!"!V%G%$%j!<%S%k%I!W$O:G>.8B
$NMW7o$G$7$+$J$$!"$H

XP $B$N%W%i%/%F%#%9$N0l$D$H$7$F7G$2$i$l$F$$$k!V (B $B7QB3E*%$%s%F%0%l!<%7%g%s (B $B!W$H$$$&C18l$r2f!9$O;


HMQ$7$F$$$k!#$7$+$7!"$3$N%W%i%/%F%#%9<+BN$O (BXP $B$K4X78$J$/:#$^$G$b$:$C$H$"$C$?$o$1$@$7!"$^$? (BXP $B$r<
+J,$N;E;v$K;H$*$&$H$O@dBP$K;W$o$J$$$h$&$J?M!9$G$b!"$3$N%W%i%/%F%#%9$r;H$C$F$$$k?M$bB?$$!#2f!9$O (B XP $B
$r<+J,$?$A$N%=%U%H%&%'%"3+H/%W%m%;%9$N5,=`$H$7$F:NMQ$7$F$$$k$N$G!"2f!9$N8@MU;H$$$d%W%i%/%F%#%9$K
$O (B XP $B$N1F6A$r?<$/Ho$C$F$$$k!#$7$+$7!"$"$J$?$,B>$N (BXP $B%W%i%/%F%#%9$K$O=>$o$J$+$C$?$H$7$F$b!"$3$N!
V7QB3E*%$%s%F%0%l!<%7%g%s!W$rMQ$$$k$3$H$O2DG=$G$"$k (B -- $B

$B<+F02=$5$l$?%G%$%j!<%S%k%I$N

● $BA4$F$N%=!<%9%3!<%I$,3JG<$5$l!"C/$G$b:G?7$N!J$=$7$F2a5n$N!K%=!<%9$r
● $B%S%k%I%W%m%;%9$r<+F02=$7$F!"C/$G$b!"%3%^%s%I0l$D$G%=!<%9$+$i%7%9%F%`$r:n$j=P$9$3$H$,$G$-$k$3$H (B
● $B%F%9%H:n6H$r<+F02=$7$F!"%3%^%s%I0l$D$G$$$D$G$b%F%9%H%9%#!<%H$r
● $B8=9T$N

$B>e$K7G$2$?$b$N$N

$B7QB3E*%$%s%F%0%l!<%7%g%s$N287C (B
$B7QB3E*%$%s%F%0%l!<%7%g%s$K$D$$$F8l$k:]$K!"8@MU$GEA$($K$/$$ItJ,$,$"$k!#$=$l$O!"7QB3E*%$%s%F%0%l!<%7%g%
s$O3+H/A4BN$K4X$o$k!V%Q%?!<%s!W$X$N0\9T$r$b$?$i$9$b$N$@$H$$$&$3$H$G$"$j!"$3$l$P$+$j$O!"

http://objectclub.esm.co.jp/eXtremeProgramming/Cont-j.html (1 of 7)05/12/2003 15:39:02


$B7QB3E*%$%s%F%0%l!<%7%g%s(B

$B$"$k?M$N:n$C$?%P%0$,B>$N?M$N:n6H$K1F6A$7$F$7$^$$!"$7$+$b$=$N$3$H$KEv?M$?$A$,5$$E$$$F$$$J$$!"$H$$$&>u67
$G$N%G%P%C%0:n6H$K;~4V$ro$KFq$7$$!#%P%0$,!"0l?M$NC4EvHO0OFb$G$O$J$/!"Fs$D$N:n6H7k2L$,0z$-5/$3$9Aj8_:nMQ
$NCf$K@x$s$G$$$k$+$i$G$"$k!#;~4V$N7P2a$,$3$NLdBj$r$5$i$K:$Fq$J$b$N$K$9$k!#$3$N

$B7QB3E*%$%s%F%0%l!<%7%g%s$r;H$($P!"$3$N/$J$/$H$b0lJ}$NB&$rC4$&%b%8%e!<%k$,$I$l$+$H$$$&$3$H$bB(:B$KH=L@
$9$k!#$3$&$J$l$P!"%P%0$NA\:wHO0O$OBgI}$K69$a$k$3$H$,$G$-$k!#2>$K%P%0$,8+$D$+$i$J$+$C$?$H$7$F$b!"%P%0M-$j%3!
<%I$r@=IJ$KF~$l$J$$$h$&$K$9$k$3$H$O$G$-$k$N$G!":G0-$G$b!V$^$@%P%0$Nu67$b$"$m$&$,!"$7$+$7$=$N>l9g$G$b!">pJs
$rF@$?>e$G$NH=CG (B(informed choice) $B$r9T$&$3$H$,$G$-$k!K!# (B

$B$b$A$m$s!"$3$NJ}K!$G%$%s%F%0%l!<%7%g%s$KMm$`%P%0$OA4$FJaB*2DG=$@$HJ]>c$9$k$b$N$G$O$J$$!#$3$NJ}K!$O%
F%9%H$r$9$k$@$1$G!"%F%9%H$O!V%(%i!<$,B8:_$7$J$$!W$3$H$r>ZL@$G$-$J$$!#=EMW$J$3$H$O!"7QB3E*%$%s%F%0%l!<
%7%g%s$O%3%9%H$K8+9g$&$@$1$N==J,$J?t$N%P%0$rJaB*$7$F$/$l$k!"$H$$$&$3$H$@!# (B

$B$3$l$i$rAH$_9g$o$;$k$H!"%$%s%F%0%l!<%7%g%s$K$+$i$`%P%0$NDI@W$KHq$d$5$l$k;~4V$,@aLs$5$l$k$3$H$+$i!"@8;:@-
$,A}Bg$9$k$3$H$K$J$k!#$3$NE@$r2J3XE*$J%"%W%m!<%A$G8&5f$7$??M$O;d$NCN$k8B$j$$$J$$$h$&$@$,!"Hs>o$KM-NO
$J7P83E*>Z5r$J$i$"$k!#7QB3E*%$%s%F%0%l!<%7%g%s$O!V%$%s%F%0%l!<%7%g%sCO9v!W$G2a$4$5$6$k$rF@$J$$;~4V$r8:
$i$7$F$/$l$k!#$=$l$I$3$m$+!"$3$NCO9v$r!"$"$j$-$?$j$N2?$G$b$J$$$3$H (B(non-event) $B$KJQ$($F$/$l$k$N$@!# (B

$B$?$/$5$s$d$k$[$&$,K>$^$7$$ (B
$B7QB3E*%$%s%F%0%l!<%7%g%s$,5Z$\$9:,K\E*$J1F6A$K$O!"D>46$rN"@Z$k$H$3$m$,$"$k!#$=$l$O!V$h$j$R$s$Q$s$K%$%s%
F%0%l!<%7%g%s$r9T$&$[$&$,!"$^$l$K$7$+9T$o$J$$$h$j$bK>$^$7$$!W$H$$$&$3$H$@!#

$B$^$l$K$7$+!"Nc$($P0lF|0J>e$N4V3V$G$7$+%$%s%F%0%l!<%7%g%s$r9T$o$J$$$N$G$"$l$P!"%$%s%F%0%l!<%7%g%s$O;
~4V$HO+NO$rHq$d$9$d$C$+$$;v$G$"$k!#$"$^$j$K$d$C$+$$$J$N$G!"$3$l$r$b$C$HIQHK$K$d$m$&$J$I$H$O;W$o$J$$$@$m$&!
#!V%W%m%8%'%/%H$,$3$l$@$1Bg$-$/$J$k$H!"%G%$%j!<%S%k%I$J$s$FIT2DG=$@$h!W$H$$$&%3%a%s%H$r;d$?$A$b$h$/J9$
$$?$b$N$@!# (B

$B$7$+$7e$b%S%k%I$r9T$C$F$$$k!#%^%$%/%m%=%U%H$O?t@iK|9T$N%3!<%I$,$"$k%W%m%8%'%/%H$G!"$3$N%G%$%j!<%
S%k%I$r9T$C$F$$$k!# (B

$B$J$<$3$l$,2DG=$J$N$+!)%$%s%F%0%l!<%7%g%s$K$+$+$kO+NO$O!"%$%s%F%0%l!<%7%g%s$r9T$&4V3V$ND9$5$KBP$7
$F;X?t4X?tE*$KA}$($F$$$/$+$i$@!#$I$N$h$&$JB,EY$,$U$5$o$7$$$+$ODj$+$G$J$$!#$7$+$7!"$3$l$N0UL#$9$k$H$3$m$O!"=5
$K0l2s$N%$%s%F%0%l!<%7%g%s$OF|$K0l2s$N%$%s%F%0%l!<%7%g%s$N#5G\$+$+$k!"$o$1$G$O$J$/!"$*$=$i$/#2#5G\$O$+$
+$C$F$7$^$&$H$$$&$3$H$G$"$k!#$"$J$?$,$b$7!"%$%s%F%0%l!<%7%g%s$,$d$C$+$$$@$H46$8$F$$$?$H$7$F$b!"$3$l$r!V$5$i
$KB?$/$N2s?t$N%$%s%F%0%l!<%7%g%s$J$I$G$-$k$O$:$,$J$$!W$3$H$N>Z5r$H$7$F$H$i$($k$Y$-$G$O$J$$!#$&$^$/$d$l$P!"2?
2s$b%$%s%F%0%l!<%7%g%s$r9T$&:n6H$O3Z$K$J$k$7!"$^$?%$%s%F%0%l!<%7%g%s$=$N$b$N$K$+$+$k;~4V$b$:$C$H>/$J$/
$J$k$N$@!# (B

$B$3$3$G=EMW$H$J$k$N$O!V<+F02=!W$G$"$k!#$[$H$s$I$N%$%s%F%0%l!<%7%g%s$O<+F02=$G$-$k$7!"$^$?$=$&$9$Y$-$J
$N$@!#%=!<%9$rC$7$F$+$i%S%k%I$9$l$P!":#EY$O@.8y$9$k$O$:$@!#$J$K$bF,$r;H$o$J$/$F$b!"!VF0$/!W%S%k%I$r:n@.$G$-$k
$o$1$@!# (B

$B$3$&$$$C$?<+F02=%W%m%;%9$,$"$l$P!"2?2s$b9%$-$J$@$1%S%k%I$r$9$k$3$H$,$G$-$k!#@)Ls$H$J$k$N$O!"0l2s$N%S%k%I
$K$+$+$k;~4V$@$1$@!# (B

$B!V@.8y$7$?%S%k%I!W$H$O!) (B
$B2?$r$b$C$F!V@.8y$7$?%S%k%I!W$H$_$J$9$N$+!)$3$l$r7h$a$k$3$H$O=EMW$G$"$k!#$=$s$J$b$N$OEv$?$jA0$@$H;W$o$l$k$
+$b$7$l$J$$$,!"$3$l$,$J$+$J$+l$K$$$F!"H`$,$5$i$KFM$C9~$s$G!V%S%k%I$N%(%i!<$,5/$-$?>l9g$O$I$&$9$k$N$+!)!W$H?V$$$?!
#Ez$($O!VC4Ev$7$F$$$k?M$K (BE $B%a!<%k$GDLCN$9$k!W$H$$$&$b$N$G$"$C$?!D!D

$B;d$?$A$OHs>o$KM_D%$j$JDj5A$r!V@.8y$7$?%S%k%I!W$K2]$9$3$H$K$9$k!# (B

● $BA4$F$N:G?7$N%=!<%9%U%!%$%k$,9=@.4IM}%7%9%F%`$+$i%A%'%C%/%"%&%H$5$l$k (B

http://objectclub.esm.co.jp/eXtremeProgramming/Cont-j.html (2 of 7)05/12/2003 15:39:02


$B7QB3E*%$%s%F%0%l!<%7%g%s(B

● $BA4$F$N%U%!%$%k$,!"$^$C$5$i$J>uBV$+$i%3%s%Q%$%k$5$l$k (B
● $B@8@.$5$l$?%*%V%8%'%/%H%U%!%$%k!J$3$N>l9g$O (B Java $B%/%i%9%U%!%$%k (B) $B$,!" (B $B%j%s%/$5$l$Fl=j
$XG[CV$5$l$k!J (Bjar $B%U%!%$%k$NCf$KF~$l$i$l$k!K (B
● $B$G$-$?%7%9%F%`$Nl9g$O!"Ls (B150 $B8D$K5Z$V%F%9%H%/%i%9!K$r
● $B$b$7>e5-$NA4$F$N%9%F%C%W$,!"%(%i!<$b5/$3$5$:$K!"$^$??M$N

$BIaDL$N?M$O!"%3%s%Q%$%k:n6H$H%j%s%/:n6H$N$3$H$r%S%k%I$@$H9M$($F$$$k!#$7$+$7;d$?$A$O!"%S%k%I$K$O>/$J$/
$H$b!V%"%W%j%1!<%7%g%s$rMcConnnell $B$O$3$l$r!V%9%b!<%/%F%9%H!W$H8F$s$G$$$k (B -- $B%9%$%C%A$rF~$l$?$i1l
$,%b%/%b%/!D!D!"$J$I$H$O$J$i$J$$$,$3$H$r3N$+$a$F$$$k$o$1$@!#!K!#$3$l$i$K2C$($F!"$5$i$KE0DlE*$J%F%9%H$r9T
$($P!"7QB3E*%$%s%F%0%l!<%7%g%s$N$b$?$i$92ACM$O$h$jBg$-$J$b$N$H$J$k$N$G!"$=$l$bJ;$;$F9T$&$[$&$,K>$^$7$$$@
$m$&!# (B

$B%7%s%0%k%=!<%9%]%$%s%H (B
$B4JC1$K%$%s%F%0%l!<%7%g%s$r9T$&$?$a$K$O!"$"$i$f$k3+H/e$G%3!<%I$r%3%T!<$7$F!"$5$F$3$l$O$"$N%G%#%l%/%H%
j$K$*$$$F!D$J$I$HG[CV$r9M$($?$j$7$J$$$H%S%k%I$,;O$a$i$l$J$$$H$$$&$N$O:GDc$G$"$k!# (B

$BK~$?$9$Y$-4p=`$O4JC1$@!'!V$@$l$G$b!"??$C?7$J%^%7%s$r0lBfMQ0U$7$F!"%M%C%H%o!<%/$K$D$J$2$P!"8e$O3+H/Cf$N
%7%9%F%`$N%S%k%I$KI,MW$J:G?7$N%=!<%9%U%!%$%k$NA4$F$r%3%^%s%I0lH/$G8F$S=P$;$k!#!W$3$l$G$"$k!# (B

$B$3$NLdBj$NL@$i$+$J!J$H?.$8$?$$$,!K2r7hJ}K!$O!"9=@.4IM}!J%=!<%9%3!<%I4IM}!K%7%9%F%`$rMQ$$$F!"$3$3$KA4$F$N
%3!<%I$r$*$/$3$H$@!#$U$D$&9=@.4IM}%7%9%F%`$O%M%C%H%o!<%/1[$7$K;HMQ$5$l$k$3$H$rA0Ds$H$7$F$$$k$7!"%=!<
%9$N?JE8$rDI@W$9$k$?$a$N%D!<%k$bMQ0U$7$F$$$k!#$5$i$K!"HG4IM}$N5!G=$bIU$$$F$$$F!"3F%U%!%$%k$N5lHG$rCVS
$B$H$$$&%*!<%W%s%=!<%9$N$9$0$l$?9=@.4IM}%D!<%k$,$"$k$+$i$@!# (B

$B$3$l$,5!G=$9$k$K$O!"A4$F$N%=!<%9%U%!%$%k$r9=@.4IM}%7%9%F%`$KF~$l$kI,MW$,$"$k!#$3$N!VA4$F!W$K$O!"$U$D
$&$KA[Dj$5$l$F$$$k0J>e$N$3$H$,4^$^$l$k!'%9%/%j%W%H!"B0@-%U%!%$%k!"%G!<%?%Y!<%9%9%-!<%^$rDj5A$7$? (BDLL
$B!"%$%s%9%H!<%kMQ%9%/%j%W%H!"$H$b$+$/??$C?7$J%^%7%s>e$G%S%k%I$r9T$&;~$KI,MW$J$b$N!VA4$F!W$G$"$k!
#4IM}2<$K$"$k%3!<%I$O8+$D$+$C$?$,!"4N?4$J%U%!%$%k$G8+$D$+$i$J$$$b$N$,$"$j!"C5$5$J$/$F$O$$$1$J$$!"$H$$$&$3$H
$,$h$/$"$k$+$i$@!# (B

$B$@$+$i!"A4$F$N$b$N$,!"$?$@0l$D$N%=!<%9%3!<%I%D%j!<2<$K$"$k$h$&$K$9$k$Y$-$@!#$h$/!"JL8D$N%3%s%]!<%M%s%
H$KBP$7$F9=@.4IM}%7%9%F%`$NJL!9$N%W%m%8%'%/%H$r3d$jEv$F$k?M$,$$$k!#$3$l$@$H!V$I$N%3%s%]!<%M%s%H$N$I
$N%P!<%8%g%s$,!"B>$N%3%s%]!<%M%s%H$N$I$N%P!<%8%g%s$H$&$^$/F0$/$N$+!W3P$($F$$$J$/$F$O$J$i$J$$!#$I$&$7$F
$b%=!<%9$rJ,$1$J$/$F$J$$$1$J$$>u67$b$"$k$@$m$&!#$7$+$7$=$s$J>u67$O;W$o$l$F$$$k$h$j$:$C$H$^$l$G$"$k!#%=!<%9%3!
<%I%D%j!<$r0l$D$K$7$F$b!"$=$3$+$iJ#?t$N%3%s%]!<%M%s%H$N%S%k%I$r9T$&$3$H$O2DG=$@$+$i$@!#$3$&$$$&$3$H
$O!"J]B8NN0h$N9=B$$GJ,$1$k$N$G$O$J$/!"%S%k%IMQ%9%/%j%W%H$N=hM}$G$U$j$o$1$k$Y$-$J$N$@!# (B

$B<+F02=$5$l$?%S%k%I%9%/%j%W%H (B
$B#1%@!<%9$+$=$3$i$N%U%!%$%k72$+$i$J$k>.5,LO$N%W%m%0%i%`$r=q$$$F$$$k$J$i!"%"%W%j%1!<%7%g%s$N%S%k%I
$J$I!" (Bjavac *.java $B$H$$$C$?%3%s%Q%$%i5/F0$N%3%^%s%I0lH/$G$9$`OC$@$m$&!#Bg5,LO$J%W%m%8%'%/%H$G$O
$=$&$O$$$+$J$$!#%U%!%$%k$O$?$/$5$s$N%G%#%l%/%H%j$KJ,;6$7$F$$$k!#@8@.$5$l$?%*%V%8%'%/%H%U%!%$%k$,@5$7
$$>l=j$KCV$+$l$k$3$H$r3NG'$7$J$/$F$O$J$i$J$$!#%3%s%Q%$%k$@$1$G$J$/%j%s%/:n6H$b$"$k$@$m$&!#%3%s%Q%$%k
$NA0$K!"B>$N%3!<%I$+$i@8@.$7$F$*$+$J$1$l$P$J$i$J$$%3!<%I$b$"$k!#%F%9%H$b!"<+F0E*$K

$BBg$-$J%S%k%I$K$O;~4V$,$+$+$k$b$N$@!#$@$+$i!"2C$($?JQ99$,>/$J$+$C$?$H$-$J$I$O%S%k%I$NA4It$N%9%F%C%W$r$N
%*%V%8%'%/%H%U%!%$%k$b:F%S%k%I$9$kI,MW$,$"$k!#%3%s%Q%$%i$O$3$N$h$&$J5!G=$r%5%]!<%H$7$F$$$k$+$b$7$l$J
$$$7!"$7$F$$$J$$$+$b$7$l$J$$!# (B

$BI,MW$K1~$8$F!"JL$N$b$N$r%S%k%I$9$k$3$H$,$"$k!#%F%9%H%3!<%IIU$-!"$^$?$OL5$7$N%7%9%F%`$d!"IaDL$O;HMQ$7$J
$$%F%9%H$r4^$a$?%7%9%F%`$J$I$G$"$k!#C1FH$G%S%k%I2DG=$J%3%s%]!<%M%s%H$b$"$k!#%S%k%I%9%/%j%W%H$O!
V8DJL$N%1!<%9$K1~$8$FJL8D$N%?!<%2%C%H$r%S%k%I$9$k!W$H$$$&MW5a$rK~$?$9$b$N$G$J$/$F$O$J$i$J$$!# (B

$B%3%^%s%I%i%$%s$+$i$NF~NO$rB46H$7$?$i!"$"$H$O%9%/%j%W%H$,=E2Y$rIiC4$7$F$/$l$k!#$3$l$i$r%7%'%k%9%/%j%W%
H$G=q$$$?$j!"$^$?$O (B perl $B$d (Bpython $B$H$$$C$?$h$j9b5!G=$J%9%/%j%W%H8@8l$G=q$$$F$$$k$+$b$7$l$J$$!#$7$+$7

http://objectclub.esm.co.jp/eXtremeProgramming/Cont-j.html (3 of 7)05/12/2003 15:39:02


$B7QB3E*%$%s%F%0%l!<%7%g%s(B

$=$N$&$A!"$3$NL\E*$G@_7W$5$l$?4D6-!"Nc$($P (BUnix $B$N (BMake $B$J$I$r;H$&$N$,$h$$!"$H$$$&$3$H$K$J$k$O$:$@!# (B

$B$7$+$7;d$?$A$,9T$C$? (BJava $B$h$k3+H/$G$O!"$9$0$K!"$h$jE0Dl$7$?2r7h0F$r9M$($kI,MW$KD>LL$7$?!#Ant $B$K@Z$jBX


$($k$3$H$K$7$?!# (BAnt $B$O (B $BHs>o$K (BJinx $B$K@_7W$,;w$F$*$j!"$I$A$i$b!" (BJava $B%U%!%$%k$r%3%s%Q%$%k$7$F
$=$N%Q%C%1!<%8$r (B Jar $B$KF~$l$k:n6H$r$7$F$/$l$k$H$$$&$b$N$G$"$k!# (BAnt $B$KFH<+$N3HD%$r=q$-$/$o$($F!"%S%k
%IFb$GJL$N:n6H$r9T$o$;$k$3$H$bMF0W$@$C$?!# (B

$B2f!9$N%A!<%`$NCf$G$b!" (BIDE $B!JLuCm!'E}9g3+H/4D6-!K$r;H$C$F$$$k?M$OB?$$!#$=$7$F!"$$$/$D$+$N (BIDE $B$K$O%S


%k%I4IM}%W%m%;%9$_$?$$$J$b$N$,AH$_9~$^$l$F$$$k!#$7$+$7!"$=$N4IM}%W%m%;%9$N2aDx$G (BIDE $B@lMQ$N%U%!%$
%k$rMQ$$$F$*$j!"$3$l$i$O@He$G

$B<+8J%F%9%HMQ%3!<%I (B
$B%W%m%0%i%`$r%3%s%Q%$%i$KDL$7$^$7$?!"$H$$$&$@$1$G$OIT==J,$@!#6/$/7?IU$1$5$l$?8@8l$N%3%s%Q%$%i$OB?$/
$NLdBjE@$r;XE&$7$F$/$l$k$@$m$&$,!"$=$l$G$b!"%3%s%Q%$%k$,@.8y$7$?$H$-$K8+Mn$H$5$l$F$7$^$&4V0c$$$N?t$O$"$^$j
$K$bB?$$!#$3$l$i$N4V0c$$$r8+$D$1$k'F;$5$l$F$$$k%W%i%/%F%#%9$N0l$D (B -- $B$H$$$&5,N'$K=>$&$3$H$G$"$k!# (B

XP $B$G$O%F%9%H$r!"!VC1BN%F%9%H!W$H!VJ}$N%F%9%H$r;H$&$7!"$^$?$I$A$i$N%F%9%H$K4X$7$F$b!"$G$-$k8B$j<
+F02=$r9T$C$F$$$k!# (B

$B%S%k%I$N0lIt$H$7$F!" (B"BVT"(Build Verification Tests: $B%S%k%I8!>Z%F%9%H (B) $B$H8F$s$G$$$k%F%9%H%9%#!<%H$r

$B!V3+H/ $B!V%F%9%H$,@h!W (B $B$H$$$&%W%m%0%i%_%s%0!&%9%?%$%k$r:NMQ$9$k$@$m$&!':G=i$O<:GT$9$k$h$&$J


%F%9%H$,=q$->e$,$k$^$G!"%3!<%I$r=q$$$F$O$$$1$J$$!#?7$7$$5!G=$r%7%9%F%`$K2C$($h$&$H$7$?$i!"$^$:$O!"$=$N5!G=
$,

$B2f!9$O!" (BJava $B$G%F%9%H$r=q$$$F$$$k!#$3$l$O!"3+H/$K;H$C$F$$$k8@8l$HF1$8$G$"$k$+$i!"!V%F%9%H=q$-!W$b!V%


3!<%I=q$-!W$bF1$8$H$$$&$3$H$K$J$k!#%F%9%H$N:n@.$d@0M}$N$?$a$N%U%l!<%`%o!<%/$K$O!" (B JUnit $B$r;H$C$F$$$k!
# (BJUnit $B$O%7%s%W%k$J%U%l!<%`%o!<%/$G$"$j!"$3$l$r;H$&$H!"$A$g$C$H%F%9%H$r=q$$$?$j!"$=$l$r%F%9%H%9%#!
<%H$K2C$($?$j!"BPOC7?$+%P%C%A7?$+A*$s$G%9%#!<%H$rxUnit $B%U%!%_%j!<$N (BJava $BHG$J$N$G$"$k!K!# (B

$B3+H/.$5$$$O$:$J$N$G!"%P%0$r8+$D$1$k$N$b4JC1$J$O$:$@!# (B

$BA4$F$N?M$,87L)$J (BXP $B%9%?%$%k$N!V%F%9%H$,@h!W$G:n6H$7$F$$$k$o$1$G$O$J$$$,!"$=$l$G$b!"%F%9%H$H%3!<%


I$rF1;~$K=q$/$3$H$NMxE@$OBg$-$$!#F1;~$K=q$/$3$H$O!"8D?M$N:n6H$r%9%T!<%I%"%C%W$9$k$P$+$j$+!"$h$jB?$/$N%(%
i!<$rJaB*$9$k$?$a$N (BBVT $B$r:n$j>e$2$F$/$l$k$+$i$@!# (B BVT $B$OF|$K2?EY$b

$B$b$A$m$s!"%F%9%H$GA4It$,%+%P!<$G$-$k$H;W$C$F$O$$$1$J$$!#$h$/8@$o$l$k$h$&$K!"!V%F%9%H$O%P%0$NIT:_
$r>ZL@$7$J$$!W$N$@!#$H$O$$$(!"40A4$r4|$5$J$$8B$j!V$h$$ (BBVT $B$r=q$/$3$H$KBP$7$F$N8+JV$j!W$rK>$a$J$$!"$H$$$&
$o$1$G$O$J$$!#IT40A4$J%F%9%H$@$C$F!"IQHK$K

$B4XO"$7$?LdBj$K!V3+H/4|4V$,C;$/$J$/$F$O$J$i$J$$!JLuCm!'B>?M$K%F%9%H:n@.$rMj$`$H;~4V$,$+$+$j$9$.$k!K!#%F%9%?!
<$rJ,N%$9$k$3$H$h$j$bC;$$2sE>4|4V$N$[$&$,=EMWEY$,9b$$$N$@!#$H$$$&$o$1$G (BBVT $B$K4X$7$F$O!"3+H/

$B%^%9%?!<%S%k%I (B
$B%S%k%I$N<+F02=$O!"8D!9$N3+H/

$B$^$::G=i$N%9%F%C%W$O!"%^%9%?!<%S%k%I$rAv$i$;$k%^%7%s$rA*$V$3$H$G$"$k!# (B $B2f!9$O!"$[$H$s$I%S%k%I@l6H
$H$$$C$F$h$$!" (BTrebuchet $B$H$$$&L>A0 (B("Age Of Empires" $B$O2?EY$b%W%l%$$7$?$b$N$@ (B) $B$N (B4-CPU $B%5!<%
P!<%^%7%s$r;H$C$F$$$k!J%S%k%I$KHs>o$K;~4V$,$+$+$C$?=i4|$N$3$m$O!"$3$l$/$i$$$N%^%7%s%Q%o!<$,IT2D7g$G$"$C$?!
K!# (B

$B%S%k%I%W%m%;%9$O!">o$K5/F0$5$l$F$$$k$"$k (B Java $B%/%i%9$NCf$K5-=R$5$l$F$$$k!#%S%k%Il9g$K$O!"%S%k%I%W


%m%;%9$O (Bwhile $B%k!<%W$NFbIt$GBT5!$7$F!"?tJ,$4$H$K%l%]%8%H%j$r%A%'%C%/$9$k!#:G8e$N%S%k%I$r$7$?;~E@$+

http://objectclub.esm.co.jp/eXtremeProgramming/Cont-j.html (4 of 7)05/12/2003 15:39:02


$B7QB3E*%$%s%F%0%l!<%7%g%s(B

$iC/$b%3!<%I$r%A%'%C%/%$%s$7$F$$$J$$>l9g$K$O!"BT5!$KLa$k!#?7$7$$%3!<%I$,%l%]%8%H%j$K$"$l$P!"%S%k%I$r3+;O$9
$k!# (B

$B%S%k%I$O!"%l%]%8%H%j$+$iA4$F$r%A%'%C%/%"%&%H$9$k$H$3$m$+$i;O$^$k!# (BStarteam $B$,MQ0U$7$?BP (BJava


$BMQ$N (BAPI $B$OHs>o$K$9$0$l$F$$$k$N$G!"%l%]%8%H%j$K%U%C%/$r$+$1$k$3$H$O4JC1$G$"$C$?!#%S%k%I%G!<%b%s
$,!"8=:_;~9o$+$i8^J,A0$N%l%]%8%H%j$N>uBV$r8+$F!"!V$=$N8^J,4V$N4V$KC/$+%A%'%C%/%$%s$r9T$C$?$+$I$&$+!W$rD4
$Y$k!#$b$7F~$l$F$$$l$P!"0BA4$N$?$a$K8^J,A0$N%3!<%I$r%A%'%C%/%"%&%H$9$k!J$3$l$G!"%l%]%8%H%j$r%m%C%/$7$J$$
$^$^$KC/$+$,%A%'%C%/%$%s$r$7$F$$$k??$C:GCf$K%A%'%C%/%"%&%H$r9T$&$3$H$rKI;_$G$-$k!K!# (B

$B%G!<%b%s$O!" (BTrebuchet $B>e$N%G%#%l%/%H%j$K%A%'%C%/%"%&%H$r9T$&!#A4$F%A%'%C%/%"%&%H$G$-$?$i!"%


G!<%b%s$O (Bant $B$G=q$+$l$?%9%/%j%W%H$r$=$N%G%#%l%/%H%j>e$G%@!<%9$KEP$k (Bjar $B%U%!%$%k$KJ,N`$7
$F!" (BEJB $B%5!<%P!<72$X$NG[CV$KHw$($k$H$3$m$^$G (B ant $B$G=q$+$l$?%9%/%j%W%H$,9T$C$F$7$^$&!# (B

ant $B$K%3%s%Q%$%k$HG[CV$^$G9T$o$;$?$i!"%S%k%I%G!<%b%s$O?7$7$$ (B jar $B%U%!%$%k$G$b$C$F (BEJB $B%5!<%P!


<$r5/F0$7!"$5$i$K (BBVT $B%F%9%H%9%#!<%H$re$,$j$H$J$k!#%S%k%I%G!<%b%s$O (BStarteam $B$KLa$C$F!"%A%'%C%/
%"%&%H$5$l$?%=!<%9$K%S%k%IHV9f$G%i%Y%kIU$1$r9T$&!#$5$i$K%S%k%ICf$KC/$+%A%'%C%/%$%s$7$F$$$J$$$+D4$Y
$F!"$b$7$$$?$i!"$5$i$K

$B%S%k%I$,40N;$7$?$i!"%S%k%I%G!<%b%s$O!"$=$N%S%k%I$G?7$?$K%U%!%$%k$r%A%'%C%/%$%s$7$?A4$F$N3+H/u67$K
$D$$$F$N$^$H$a$,=q$$$F$"$k!#%3!<%I$r%A%'%C%/%$%s$7$??M$O!"$3$N%a!<%k$rl$rN%$l$F2H$K5"$C$F$O$$$1$J$$!"$H$$
$&$3$H!K (B

$B%G!<%b%s$O!"3F%9%F%C%W$N%m%0$rA4$F (BXML $B7A<0$N%m%0%U%!%$%k$K=q$-=P$9!# (BTrebuchet $B>e$K$O%5!


<%V%l%C%H$,Av$C$F$*$j!"$3$N%5!<%V%l%C%H$+$i%m%0$,GA$1$k$N$G!"C/$G$b%S%k%I$N>u67$,$o$+$k$H$$$&$o$1$G
$"$k!# (B

http://objectclub.esm.co.jp/eXtremeProgramming/Cont-j.html (5 of 7)05/12/2003 15:39:02


$B7QB3E*%$%s%F%0%l!<%7%g%s(B

$B?^#1 (B: $B%S%k%I3NG'%5!<%V%l%C%H (B

$B%9%/%j!<%s$K$O!"8=:_\:Y$r8+$k$K$O!"$=$N%S%k%I$r%/%j%C%/$9$l$P$h$$!# (B

$BB?$/$N3+H/$N>pJs$b:\$;$h$&$+$H9M$($F$$$k$,!"$?$@!"$=$l$@$H$^$H$^$j$,$J$/$J$k62$l$b$"$k!# (B

$B=EMW$J$N$O!"$I$N3+H/

$B$3$3$G!"%^%9%?!<%S%k%I$O%/%j!<%s$K!"$9$J$o$A!"A4$F%=!<%9$+$i:n@.$9$k$+!"$=$l$H$b%$%s%/%j%a%s%?%k$K:
n@.$7$F$b$h$$$+!"$H$$$&LdBj$rLd$&$3$H$,$G$-$k$@$m$&!#%$%s%/%j%a%s%?%k%S%k%I$N$[$&$,$:$C$HB.$/$9$`$,!"0lIt$r
%3%s%Q%$%k$7$J$+$C$?$3$H$+$i$/$k>c32$,H/@8$9$k4m81$,;D$k!#$5$i$K!"$=$N%S%k%I$r:F8=$G$-$J$/$J$C$F$7$^
$&2DG=@-$b$"$k!#2f!9$N$H$3$m$G$O%S%k%I$O==J,$KB.$$$N$G!J#2#0K|9T$N%3!<%I$KBP$7$FLs#1#5J,$[$I!K!"Kh2s%/%j!<
%s%S%k%I$r9T$C$F$bITK~$O$J$$!#$7$+$7!"$[$H$s$I$N>l9g$O%$%s%/%j%a%s%?%k%S%k%I$G$9$^$7$F!"Dj4|E*$K!J:GDc$G
$b0lF|0l2s!K%/%j!<%s%S%k%I$r9T$&$3$H$GIT2D;W5D$J%(%i!<$,8=$l$k;vBV$KHw$($k!"$H$$$&%=%U%H%O%&%9$b$"$k$@
$m$&!# (B

$B%A%'%C%/%$%s (B
$B<+F02=$5$l$?%S%k%I$r:NMQ$9$k$H!"3+H/$C$F%=%U%H%&%'%"$N3+H/$r9T$&$h$&$K$J$k!#$3$N%j%:%`$N:G=EMW%Q!
<%H$O!"%$%s%F%0%l!<%7%g%s$r!VDj4|E*$K!W9T$&$3$H!"$G$"$k!#2f!9$,K,$l$?$"$kItBb$G$O!"%G%$%j!<%S%k%I$r

$B?7$7$$%?%9%/$r;O$a$kA0$K$O!"$^$:$O!"3+H/c$9$k$o$1$@!#8E$$%=!<%9%3!<%I$N>e$K?75,DI2C$r9T$C$F$b%H%i%V%k
$H:.Mp$r4,$-5/$3$9$@$1$G$"$k!# (B

$BF14|$r

$B%$%s%F%0%l!<%7%g%s$r$9$k$K$O!"$^$::n6H$7$?%3%T!<$H%l%]%8%H%j$NFbMF$H$NF14|$r:F$Se$GFbMF$,JQ$o$C$?%
U%!%$%k$OA4$F:n6H%G%#%l%/%H%j$K%3%T!<$5$l!"$+$D%3%s%U%j%/%H$,$"$l$P9=@.4IM}%7%9%F%`$,%o!<%K%s%0
$r=P$9!#3+H/

$B$3$3$^$G$G$-$F!"3+H/l9g$K$O!"$^$:$OJQ99$r

$B%A%'%C%/%$%s$NFbMF$K$h$C$F$O!"=gHV$rDj$a$F%A%'%C%/%$%s:n6H$r9T$&!J (Bserialization of the check-in process $B!


KI,MW$,$"$k!"$H$$$&>l9g$,$"$k!#$3$N$H$-$K$O!"F1;~$KFs?M0J>e$N3+H/e$N3+H//$J$+$C$?$N$G!"2f!9$O%S%k%I%H!<%/%s
$rMQ$$$J$+$C$?!#F1$8%^%9%?!<%S%k%I$KBP$7$FFs?M0J>e$N3+H/o$K$^$l$@$C$?$7!"5/$-$?$H$7$F$b=$@5$O$9$09T$&$3
$H$,$G$-$?!# (B

$B$^$?!"%A%'%C%/%$%s$K:]$7$F$I$3$^$GCm0U$rJ'$&$+!"$H$$$&E@$K4X$7$F$b!"8D!9$N3+H/C$7!"$I$3$,$*$+$7$$$+FM$-;_
$a$J$/$F$O$J$i$J$/$J$k!# (B -- $B$3$N$h$&$K!"H/@8$7$F$b$9$08+$D$1$F4JC1$K

$B7k8l (B
$B$-$A$s$H$7$?<+F02=%S%k%I%W%m%;%9$r3NN)$9$k$3$H$O!"$-$A$s$H%W%m%8%'%/%H$r@)8f$9$k>e$GI,?\9`L\$G$"$k (B
-- $BB?$/$N%=%U%H%&%'%"!&%0%k (B( $B;XF3l$G$O!"u67$@!# (B

$B%-%b$H$J$k$N$O!"K\Ev$K!VA4$F!W$r<+F02=$7$F!"$+$D%W%m%;%9$r!VIQHK$K!W9T$&$3$H$G!"%$%s%F%0%l!<%7%g%
s$K4X$o$k%(%i!<$rAa4|$K8+$D$1$k$3$H$G$"$k!#$=$&$9$l$P!"C/$K$H$C$F$b!"I,MW$JJQ99$r2C$($k$3$H$,MF0W$K$J$k!#!V$b
$72>$K<+J,$,%$%s%F%0%l!<%7%g%s%(%i!<$r0z$-5/$3$7$?$H$7$F$b$=$l$O$9$08+$D$1$FD>$;$k$N$@!W$H<+?.$,;}$F$k$+$i
$@!#$3$N$3$H$N287C$O$"$^$j$K6/NO$@!#$@$+$i!"$$$C$?$sCN$C$F$7$^$C$?$,:G8e!"$3$N287C$re$2$i$l$=$&$J>lLL$G
$O!"$"$J$?$O$-$C$H!"K=$l$?$j!"6+$s$@$j$9$k$K0c$$$J$$!D (B

http://objectclub.esm.co.jp/eXtremeProgramming/Cont-j.html (6 of 7)05/12/2003 15:39:02


$B7QB3E*%$%s%F%0%l!<%7%g%s(B

© Copyright Martin Fowler, all rights reserved

$BK]Lu!'>.Ln!!9d (B $Id: Cont-j.html,v 1.4 2000/11/30 02:38:48 ono Exp $

http://objectclub.esm.co.jp/eXtremeProgramming/Cont-j.html (7 of 7)05/12/2003 15:39:02


Analysis Patterns 2 - Work in Progress

Analysis Patterns 2 - Work in Progress

● Temporal Patterns
● Quantityand Range
● Accounting patterns: a (considerable) update of the material in the Analysis Patterns book.
● Accountability narrative and patterns

‚µ‚΂ç‚-‚ÌŠÔ•AŽ„‚Í‚¸‚Á‚ƃAƒiƒŠƒVƒXƒpƒ^•[ƒ“‚ÌŽdŽ–‚ð‚µ‚Ä‚¢‚½•BŒ»•Ý‚Ì‚Æ
‚±‚ë•AƒAƒiƒŠƒVƒXƒpƒ^•[ƒ“‚Ì‘æ‚Q”Å‚Ì—\’è‚Í‚È‚©‚Á‚½‚ª•AŽdŽ–‚Ńpƒ^•[ƒ“‚ð•‘‚-‚æ‚è‚à‚Þ‚µ‚ë–{‚ð•‘‚-
‚Ù‚¤‚ª•d—v‚¾‚ÆŽv‚Á‚½•B‚±‚ê‚Í•AƒIƒŠƒWƒiƒ‹‚̃AƒiƒŠƒVƒXƒpƒ^•[ƒ“–{‚©‚ç‚Ì‘è•Þ‚¾‚¯‚Å‚È‚-•A•V‚µ
‚¢‚à‚Ì‚àŠÜ‚ñ‚Å‚¢‚é•BŒ»•ÝŽ„‚ª•l‚¦‚Ä‚¢‚邱‚Æ‚Í•A‚ ‚鎞“_‚Å‚Ì•A•V‚µ‚¢ƒAƒiƒŠƒVƒXƒpƒ^•[ƒ“–{‚ð•»•ì
‚·‚é‚‚à‚肾‚ª•A‚»‚ê‚Í‘æ‚P”Å‚Ì‚Ù‚ñ‚̈ꕔ•ª‚Ì’u‚«Š·‚¦‚Å•AŒµ–§‚É‚Í‚Ü‚¾Œˆ‚ß‚Ä‚¢‚È‚¢•B

‚â‚Á‚ƃAƒiƒŠƒVƒXƒpƒ^•[ƒ“‚Ì‘è•Þ‚Æ‚µ‚Ä•A’Ç‚¢‚‚¢‚Ä‚«‚½•B‚â‚Á‚ÆŽg‚¤‚½‚ß‚Ì•î•ñ‚ª•o‚»‚ë‚Á‚½•B
‚»‚ê‚ç‚̃tƒB•[ƒhƒoƒbƒN‚𓾂½‚¢‚Æ•l‚¦‚Ä‚¢‚é•BŽ„‚Í•Aƒpƒ^•[ƒ“‚ðŽg‚¤•û•X‚ÌŒoŒ±‚É‚Æ‚Ä‚à‹»–¡‚ª
‚ ‚é•B‚ ‚È‚½‚̓pƒ^•[ƒ“‚ðŽg‚Á‚½Ž–‚ª‚ ‚è‚Ü‚·‚©•H‚»‚ê‚ç‚ÍŽg‚¢‚â‚·‚¢‚Å‚·‚©•H‚¨‚à‚µ‚ë‚¢ƒoƒŠƒG•
[ƒVƒ‡ƒ“‚̃pƒ^•[ƒ“‚É•o‚-‚킵‚½‚±‚Æ‚ª‚ ‚è‚Ü‚·‚©•H‚Ç‚¤‚©‹³‚¦‚Ä‚-‚¾‚³‚¢•AŽ„‚Í‚±‚̃TƒCƒg‚Ì‘è•Þ
‚ɃRƒ•ƒ“ƒg‚ðƒtƒB•[ƒhƒoƒbƒN‚µ‚Ä•s‚±‚¤Žv‚Á‚Ä‚¢‚é•B

‚Í‚é‚©‚È‚éƒpƒ^•[ƒ“
Ž„‚ª•ì‚Á‚½—˜—p‰Â”\‚È•Å•‰‚̃pƒ^•[ƒ“‚̃Zƒbƒg‚Íaccountability patterns‚Å•A ƒAƒiƒŠƒVƒXƒpƒ^•
[ƒ“‚Ì‚Q•Í‚©‚ç•AŽ„‚ª•¡Žg‚Á‚Ä‚¢‚é•V‚µ‚¢Œ`‚Ö‚Æ•A–{Ž¿“I‚ɉü’ù‚·‚é•B ‚±‚ê‚ç‚̃pƒ^•[ƒ“‚Í•A‚Q‚Â
‚Ìpdfƒtƒ@ƒCƒ‹•F narrative and a collection of patterns‚É‚È‚Á‚Ä‚¢‚é•BŽ„‚Ípdfƒtƒ@ƒCƒ‹‚ðŽg‚¤‚±‚Æ‚ð
‚â‚ß•A‚±‚ê‚©‚ç•ì‚ç‚ê‚éƒpƒ^•[ƒ“‚É‚Íhtml‚ðŽg‚¤‚‚à‚肾•B-‚µ‚©‚µ‘½•ªŽ©‘R‚ȃtƒH•[ƒ}ƒbƒg‚É•Ï‚¦‚Ä‚ä‚-
‚É‚Í‚µ‚΂ç‚-ŽžŠÔ‚ª‚©‚©‚邾‚낤•B

Quantity ‚Æ Range‚Ì‚Q‚‚͕A•¬‚³‚¢‚ª‚Æ‚Ä‚à‹¤’Ê“I‚ȃpƒ^•[ƒ“‚Å‚ ‚é•B‚±‚ê‚ç‚Í•¬‚³‚-•AŠî–{“I‚ȃpƒ^•


[ƒ“‚Å•A‚©‚È‚è•L‚¢”͈͂Ŏg‚í‚ê‚é•B‚à‚µ‚ ‚È‚½‚ªOOƒVƒXƒeƒ‚ð•‘‚-‚È‚ç‚΂»‚ê‚ç‚̃pƒ^•[ƒ“‚Í•Aƒc•
[ƒ‹ƒLƒbƒg‚Ì‚¤‚¿‚̈ꕔ‚É•í‚É•\‚ê‚Ä‚¢‚邾‚낤•B

‚ЂƂ‚̌^‚Ü‚½‚Í‚»‚êˆÈŠO‚ÌŒ^‚ÌAccounting‚Í•AŽ„‚Ì•¶ŠU‚ÅŒˆ‚µ‚Ä•I‚í‚ç‚È‚¢ƒe•[ƒ}‚¾‚ÆŽv‚í‚ê
‚é•B ƒAƒiƒŠƒVƒXƒpƒ^•[ƒ“‚Å‚Í•Aaccounting ƒpƒ^•[ƒ“‚Ì•Í‚ª‚ ‚é•B‚»‚̌コ‚ç‚ɃAƒCƒfƒA‚ª•o‚Ä‚«‚½•B
‚»‚ꂪaccounting pdf ƒtƒ@ƒCƒ‹‚Å‚ ‚é•B •o‚¾‚µ‚É‚Í•A‚¢‚-‚‚©‚̃pƒ^•[ƒ“‚ª•o‚Ä‚-‚é•B ‚»‚êˆÈŠO‚̃pƒ^•
[ƒ“‚Æ‚µ‚Ä‚Í•Aƒpƒ^•[ƒ“‚ÌŠT—v‚ð•æ‚É“Ç‚ñ‚Å‚-‚¾‚³‚¢•B‚»‚¤‚·‚ê‚ΕA•Ú•×‚Ü‚Å•[‚-Œ@‚艺‚°‚ăpƒ^•

http://www.tech-arts.co.jp/martinfowler/ap2/index.html (1 of 3)05/12/2003 15:39:04


Analysis Patterns 2 - Work in Progress

[ƒ“‚ðŽg‚¤‚±‚Æ‚ª‚Å‚«‚邾‚낤•B ‚»‚ê‚ç‚Í‹Ž”N‚ÌŽ„‚̃AƒiƒŠƒVƒXƒpƒ^•[ƒ“ƒ`ƒ…•[ƒgƒŠƒAƒ‹‚Ì”¼“ú•ª
‚¾•Bƒpƒ^•[ƒ“‚̕ڕׂ͂»‚±‚Řb‚µ‚½‚à‚Ì‚ª”½‰f‚³‚ê‚Ä‚¢‚邾‚낤•B

Ž„‚̕ŋ߂̃pƒ^•[ƒ“‚̃Zƒbƒg‚Í•A—ðŽj“I‚È•î•ñ‚Ì‚½‚߂̃pƒ^•[ƒ“‚Ì‘g‚Ì‚¤‚¿‚̈ê‚‚¾•B—ðŽj‚ð•ß‚炦‚鎖
‚Í•Aƒ‚ƒfƒ‹‚É‘½‚-‚Ì•¡ŽG‚³‚ð‰Á‚¦‚邱‚Æ‚Å‚ ‚è•A‚»‚ê‚ç‚̃pƒ^•[ƒ“‚Í‚»‚Ì—ðŽj“I‚È–â‘è“_‚ð‰ðŒˆ‚·‚é
‚±‚Æ‚ð••‚¯•A‚»‚ê‚ç‚𕪂¯‚Ĉµ‚¤‚±‚Æ‚ð‰Â”\‚É‚µ‚Ä‚¢‚é•B“¯Žž‚Ƀpƒ^•[ƒ“‚Í‹¤’Ê‚ÌŽÀ‘•‹Z•p‚ð˜A‘z‚³‚¹
‚é•B

•V‚µ‚¢Œ`Ž®
ƒAƒiƒŠƒVƒXƒpƒ^•[ƒ“‚Ì”-•sˆÈ—ˆŽ„‚ªŽÀŒ±‚µ‚Ä‚¢‚½•A•Å‚à‘å‚«‚È‚à‚Ì‚Ì‚¤‚¿‚Ì1‚‚͕Aƒpƒ^•[ƒ“‚ð•\Œ»‚·
‚éŒ`Ž®‚Å‚ ‚é•BƒAƒiƒŠƒVƒXƒpƒ^•[ƒ“‚Å‚Í—¦’¼‚È•¨Œê‚¾‚Á‚½•B‚±‚Ì‚±‚Æ‚ªƒŠƒtƒ@ƒŒƒ“ƒX‚Æ‚µ
‚ăpƒ^•[ƒ“‚ðŽg‚¤‚Ì‚ð‚æ‚è“‚-‚µ‚Ä‚¢‚é‚Æ•ª‚©‚Á‚½•B‚µ‚©‚µ•A‚»‚ê‚ƈø‚«Š·‚¦‚É•A•¨ŒêŒ`Ž®‚Æ‚·‚é
‚±‚Æ‚Å•A’†•S‚É‚ ‚éƒpƒ^•[ƒ“‚ÌŠÖŒW‚ɂ‚¢‚Ä—eˆÕ‚É‹c˜_‚Å‚«‚é‚悤‚É‚È‚é‚ÆŽv‚Á‚½•B

‚³‚µ‚ ‚½‚è‚Ì‰ðŒˆ•ô‚Æ‚µ‚Ä•A2‚‚̃ZƒNƒVƒ‡ƒ“‚É•ªŠ„‚µ‚Ä‹L•q‚·‚é‚悤‚É‚µ‚Ĉȗˆ•A•¨ŒêŒ`Ž®
‚ƃŠƒtƒ@ƒŒƒ“ƒXŒ`Ž®‚Å‚ÌŽæ‚è‘g‚Ý‚±‚»‚ªŽ„‚É‚Æ‚Á‚Ä‹¤’ʂ̃e•[ƒ}‚¾‚Á‚½•B‚»‚̃gƒŒ•[ƒhƒIƒt‚É
‚‚¢‚Ä‹c˜_‚·‚é•B‚æ‚è’·‚¢ƒJƒ^ƒ•ƒO•EƒZƒNƒVƒ‡ƒ“‚Í•A•‡”Ô‚ÉŠeƒpƒ^•[ƒ“‚̕ڕׂɂ‚¢‚Ä‚Æ‚è‚ ‚°‚é•B
‚±‚Ì•ª—£‚ª•AŽ„‚Ɉê•Î“ñ’¹‚ð‰Â”\‚É‚³‚¹‚Ä‚¢‚邾‚¯‚Å‚Í‚È‚-•A‚³‚ç‚É•A“ǂݎ肪ƒpƒ^•[ƒ“‚Ì‘¶•Ý‚⃉ƒt
‚ȈӖ¡‚ð—•‰ð‚·‚é‚½‚ß‚É’P‚Ȃ镨Œê‚ð“Ç‚Þ‚±‚Æ‚ð‰Â”\‚É‚µ‚Ä‚¢‚é•B‚»‚̂悤‚É•Aƒpƒ^•[ƒ“‚ªŠÖŒW
‚µ‚Ä‚¢‚é‚æ‚¢Ž‹“_‚𓾂邽‚ß‚É–{‚ð‘S•”“Ç‚Þ•K—v‚ª‚È‚-•A•¨Œê‚ð‚¿‚å‚Á‚Æ“Ç‚Þ‚±‚Æ‚à‚Å‚«‚é•B

ƒJƒ^ƒ•ƒO•–Ú‚ÍŽŸ‚ÌŒ`Ž®‚Ńpƒ^•[ƒ“‚ð•Ú•q‚·‚é•B

● –¼‘O
● –Ú“I
● ƒ_ƒCƒAƒOƒ‰ƒ
● ‚Ç‚¤‚»‚ê‚Í•ì“®‚·‚é‚©
● ‚»‚ê‚ðŽg—p‚·‚é‚ׂ«‚Æ‚«:
● ‚¢‚-‚‚©‚̃R•[ƒh•EƒTƒ“ƒvƒ‹‚Í—á‚Æ‚µ‚Ä‚ÌŽÀ‘•‚ðŽ¦‚µ‚Ä‚¢‚é•B

ƒpƒ^•[ƒ“‚Ì‚½‚ß‚É‚±‚̃tƒH•[ƒ}ƒbƒg‚Í‚©‚È‚èŠÉ‚¢‚¾‚낤•B‚µ‚©‚µ•AŽ„‚̓pƒ^•[ƒ“‚ÌŽå—v
‚ȃZƒNƒVƒ‡ƒ“‚ª–{Ž¿‚ð•\‚·‚±‚Æ‚ÉŠú‘Ò‚·‚é•B

‰½•l‚©‚Ì•l‚̓R•[ƒh•EƒTƒ“ƒvƒ‹‚ÌŽg—p‚ɂ‚¢‚ăRƒ•ƒ“ƒg‚µ‚½•B‚±‚ê‚ç‚̃Rƒ•ƒ“ƒg‚ÍŠì‚Ñ‚©‚ç‹°•|‚Ö
‚Æ•Ï‚í‚Á‚½•B‚»‚ê‚ç‚ðŽg‚¤Žå‚È—•—R‚̓vƒ•ƒOƒ‰ƒ}(”Þ‚ç‚ÍŒ‹‹Çƒvƒ•ƒOƒ‰ƒ‚ð—•‰ð‚·‚é)‚Æ‚æ
‚èˆÓŽu‚ª’Ê‚¶‚é‚©‚ç‚Å‚ ‚é•B‘½‚-‚̃vƒ•ƒOƒ‰ƒ}‚Í•A•}‚â–{•¶‚Ì‹L•q‚©‚çƒpƒ^•[ƒ“‚ª‚Ç‚¤“-‚-‚©—•‰ð‚·‚é‚Ì
‚É‹ê˜J‚µ‚Ä‚¢‚½•BƒTƒ“ƒvƒ‹‚ðƒR•[ƒh‰»‚·‚邱‚Æ‚Å•A‚»‚ÌŠT”O‚ð‚Í‚Á‚«‚肳‚¹‚é•B

–Y‚ê‚Ä‚Í‚È‚ç‚È‚¢‘厖‚È‚±‚Æ‚Í•A‚±‚ê‚炪—á‚Æ‚µ‚Ä‚ÌŽÀ‘•‚Å‚µ‚©‚È‚¢‚Æ‚¢‚¤‚±‚Æ‚Å‚ ‚é•B’N‚à•A‚»‚Ì
‚Ü‚ÜŽg‚¤‚±‚Æ‚Í‚Å‚«‚È‚¢‚¾‚낤•B‚»‚ê‚ç‚Í“K—p‚³‚ê‚é–â‘è‚ɉž‚¶‚Ä“K‰ž‚³‚¹‚é•K—v‚ª‚ ‚邾‚낤•B

http://www.tech-arts.co.jp/martinfowler/ap2/index.html (2 of 3)05/12/2003 15:39:04


Analysis Patterns 2 - Work in Progress

‚»‚ê‚ç‚Í•A‚»‚êˆÈ•ã•à–¾‚³‚ê‚È‚¢ŠT”O‚ð•â‚¤‚½‚ß‚É‘¶•Ý‚µ‚Ä‚¢‚é•B

‚³‚ç‚É•AƒR•[ƒh•EƒTƒ“ƒvƒ‹‚̓pƒ^•[ƒ“‚Ì—•‰ð‚É‚Æ‚Á‚Ä•K—v‚Å‚Í‚È‚¢•BŽ„‚Ì–Ú•W
‚Í•AUMLƒ_ƒCƒAƒOƒ‰ƒ‚𕇗•“I‚É“Ç‚Þ‚±‚Æ‚ª‚Å‚«‚ê‚ΕAƒR•[ƒh‚É‚æ‚炸‚É•Aƒpƒ^•[ƒ“‚𗕉ð‚Å
‚«‚邱‚Æ‚É‚ ‚é•B‚à‚µƒR•[ƒh‚ð“Ç‚Ý‚½‚-‚È‚¯‚ê‚ΕA–³Ž‹‚µ‚Ä‚¢‚¢‚¾‚낤•B‚»‚ê‚Å‚à•A‚¨‚»‚ç‚-‚̓pƒ^•
[ƒ“‚͈Ӗ¡‚ð‚È‚µ‚Ä‚¢‚é‚Í‚¸‚¾‚©‚ç•B

© Copyright Martin Fowler, all rights reserved

http://www.tech-arts.co.jp/martinfowler/ap2/index.html (3 of 3)05/12/2003 15:39:04


AgileAlliance

USER CONTACT
HOME ARTICLES NEWS MANIFESTO MEMBERSHIP PROGRAMS ROADMAP
GROUPS US
powered by objectmentor.com

The AgileAlliance
Who We Are - The AgileAlliance is a non-profit
Go to the
organization dedicated to promoting the concepts of
Agile
agile software development, and helping organizations
Manifesto adopt those concepts. Those concepts are outlined by
the Manifesto for Agile Software Development.

Become A Member - You can join the Agile Alliance!


Join in the programs, receive the famed Agile Times
newsletter, get discounts at conferences, and support
the agile movement through information dissemination in
our library, user groups, and news programs.

Check Out Our Library - All the information you


wanted about Agile processes. This is your research
base for learning about Agile development.

What's New - What's going on in the Agile community.

Volunteer For a Program - Once you've become a


member, check out the section on Programs. Already
operating programs are listed. If you want to volunteer to
work in any of these programs, contact the program
director. The program director is the person who thought
up the program and volunteered to make it happen. If
you have some ideas about ways to further agile
processes that aren't already encapsulated in a
program, any member can propose a new program and
be its director. If you think an existing program could use
another slant, either join it and change it, or propose a
parallel program. As a director of a company that
employs agile processes said, "Lead, follow, or get out
of the way." That is another way of saying that all
opportunities have been provided for anyone who wants
to move the agile movement forward to do so. So, do!

http://agilealliance.org/home (1 of 2)05/12/2003 15:39:09


AgileAlliance

How We're Organized - The AgileAlliance


germinated in the fertilizer of the original AgileAlliance, a
group of software professionals that had developed and
were practicing lightweight approaches to software
development. Responding to requests for a more open,
inclusive, and visible way for everyone to participate,
most of the founders of the AgileAlliance defined and
established the non-profit AgileAlliance. This
organization was designed to be lightweight, initially only
consisting of a board of directors, one administrator, and
a set of bylaws. Just like agile processes, all work and
operations within the AgileAlliance is intended to emerge
from subsets of members that self-organize into
programs. The board of directors had to resist impulses
to do top-down planning and is watching to see how
successfully the organization emerges and succeeds
following agile principles.

http://agilealliance.org/home (2 of 2)05/12/2003 15:39:09


XP$BJQAU6J(B(Variations on a Theme of XP)

XP $BJQAU6J (B
$B86Bj (B: Variations on a Theme of XP

Martin Fowler
Chief Scientist, ThoughtWorks

XP $B$NL%NO$N$R$H$D$O!" (BXP $B$r$N%i%$%H$JJ}K!O@$r;Y$($k86B'$K$O!V<+8JE,1~@-!


W$,$"$C$?$O$:$@!#$D$^$j!"%W%m%8%'%/%H$N?JE8$K=>$C$F%W%m%;%9<+BN$rJQ
$($F9T$/$Y$-$@!"$H$$$&$3$H$@!#$3$N9M$($H!" (BXP $B$N873J$J%W%i%/%F%#%9=8$H
$O!"2L$?$7$F$I$&@09g$9$k$N$@$m$&$+!# (B

● $B$J$s$GJ}K!O@$J$I:NMQ$7$h$&$H;W$&$N$@$m$&$+ (B
● $BJ}K!O@$N2~JQ2DG=@- (B
● $B2~JQ2DG=@-$HJ}K!O@ (B
● XP $B$H$O2?$+ (B
● XP $B$H<+8JE,1~@- (B
● $B6qBN2=$5$l$? (B XP $B$N%P%j%(!<%7%g%s$r:n$k (B
● XP $B$H$=$NE,MQHO0O (B

$B2>$K;d$,!"$"$k%=%U%H%&%'%"J}K!O@!J (Bmethodology $B!K$r:n$j=P$7$?$H$7$h$&!J

$B$3$l$O!"%=%U%H%&%'%"%W%m%;%9$K$D$-$b$N$NLdBj$G$"$k!#$=$7$F:#!"$3$NXP $B
$dB>$N (B $B%i%$%H$JJ}K!O@ (B $B$KBP$7$FLd$$$+$1$i$l$F$$$k!#FC$K (BXP $B
$N>l9g!"873J$Kr7o$H$r;}$C$F$$$k$N$G!"$3$l$O=EMW$J

$B$5$i$K8@$($P!"%i%$%H$JJ}K!O@$N3K$H$J$kItJ,$O!V<+8JE,1~@-!W$G$O$J$+$C$?$+!"$H$
$$&OC$b$"$k!#$D$^$j!"%W%m%;%9$NE,MQ$K9g$o$;$F!"J}K!$=$N$b$N$rJQ99$9$k$3$H$,4|BT
$5$l$F$$$k$N$@!#$7$+$7$3$N9M$($O!" (BXP $B$N873J$5$HAjMF$l$k$b$N$J$N$@$m$&$+!#
(B

$B$J$s$GJ}K!O@$J$I:NMQ$7$h$&$H;W$&$N$@$m$&$+ (B
$B$3$N5?Ld$KEz$($k$?$a$K!"$A$g$C$H8eB`$7$F$3$&Ld$$$+$1$?$[$&$,$h$$$@$m$&!'J}K!
O@$H$O!"$$$C$?$$2?$N$?$a$K$"$k$N$@$m$&$+!#$J$$C$F$$$l$P!"@.8y$K8~$+$&@5$7$$F;

http://objectclub.esm.co.jp/eXtremeProgramming/xpVariations-j.html (1 of 7)05/12/2003 15:39:10


XP$BJQAU6J(B(Variations on a Theme of XP)

$K$-$C$H$D$l$F$$$C$F$b$i$($k$O$:!"$H4|BT$7$F$$$k$N$@!# (B

$B$5$i$K$3$&$b8@$($k$@$m$&!#J}K!O@$K=>$&$3$H$G!"2?$+<:GT$,5/$-$?>l9g$K!"!V$$
$d!"$d$l$k$3$H$O$d$C$?$s$@$h (B -- $B$A$c$s$HM-L>$JJ}K!O@$K=>$C$F$$$?$s$@$7!W$H$
$$C$F<+J,$rJ[8n$7$h$&$H$7$F$$$k$N$@!"$H!#8e$&$3$H$O$h$/$d$j6L$K$"$2$i$l$k!#$7$+
$7!"$"$k;E;v$r9T$&$N$K=jDj$N%W%m%;%9$rF'$`$3$H$,4|BT$5$l$F$*$j!"$b$7$=$&$7$J$+$C$?
$i!">-Mh!"LdBj$KBP$7$F@UG$$rLd$o$l$k2DG=@-$,9b$^$k!"$H$$$&5,B'$d5,N'$,B?$/8+$i$l$k$H
$$$&$3$H$b;v

$B$I$A$i$N>l9g$K$;$h!"?M!9$O$"$k%9%F%C%W$rF'=1$9$k$3$H$G@.8y$N%A%c%s%9$rA}$d
$7$?$$$H9M$($F$$$k$3$H$K$OJQ$o$j$J$$!#$=$7$F$3$l$OEvA3$G$"$k!#$@$C$F!"%=%U%H%
&%'%"$N3+H/$NNr;K$O$b$&2?==G/$K$b$J$m$&$H$$$&$N$@!#B>?M$N7P83$+$i$$$m$$$m
$H3X$Y$F$$$$$O$:$G$O$J$$$+!# (B

$BJ}K!O@$N2~JQ2DG=@- (B
$BMpK=$K8@$($P!"B?$/$NJ}K!O@$O!"$=$N:nl9g$N$3$H$@ (B -- $B;d$O$[$H$s$I$NJ}K!O@
$O!"$3$&$G$-$?$iNI$+$C$?$N$K!"$H$$$&:n$K4p$E$$$?$b$N$G$O$J$$$+$H5?$C$F$$$k!#%"%
$%G%"$r;W$$$D$$$??M$O2??M$+$$$k$+$b$7$l$J$$!"$7$+$7!"C/$G$b$$$$$+$i$=$N7k2L$r

$B%=%U%H%&%'%"$O$^$?!"6KC<$KJQ$o$j$d$9$$$b$N$@!"$H$$$&FCD'$,$"$k!#$^$:!"%=%U
%H%&%'%"$N=EMW$JJQ?t$N0l$D$O!V?M4V!W$G$"$k!#0[$J$kJ}K!$O!"?M4V$,0c$($PF/$-J}
$b0c$C$F$/$k!#$=$N4k6H$N%+%k%A%c!<$b$^$?%=%U%H%&%'%"$KBg$-$J1F6A$r;}$D!#$5$i
$K!"%=%U%H%&%'%"$N%9%?%$%k$H$$$&LdBj$b$"$k!#EEOC5!4XO"$N3+H/$N$?$a$K:n$i$l
$?%W%m%;%9$,!">pJs%7%9%F%`$d%2!<%`$K$bE,$9$k$H$O$H$F$b;W$($J$$!# (B

$BJ}K!O@M@$N$?$a$K8@$C$F$*$1$P!"H`$i$NB?$/$,$3$N$3$H$rG'<1$7$F$$$k!#?M!9$rC1=c$J
%9%F%C%W$K=>$o$;$k$@$1$G40`z$J7k2L$,F@$i$l$k$J$s$F$3$H$O$J$$!"$H$$$&$3$H$OJ}K!
O@ $B$3$NLd$$$+$1$O (B $B%i%$%H$JJ}K!O@ (B $B$N $B<+8JE,1~E*!J (Bself-adaptive $B!K
(B $B$G$"$k$3$H!W$,$"$2$i$l$k$+$i$G$"$k!#<+8JE,1~E*$H$O!"J}K!O@$r;H$&$K$D$l$F!"$=
$NJ}K!O@<+BN$rJQ99$7$F$$$/$Y$-$@!"$H$$$&$3$H$r0UL#$7$F$$$k!#$3$&$J$k$H!"$I$3$^$G
$rJ}K!O@$N%P%j%(!<%7%g%s$HG'$a$k$+$H$$$&6-3&$O!"$5$i$K[#Kf$J$b$N$H$J$k$@$m$&!
#J}K!O@$r;H$&%W%m%8%'%/%H$4$H$N%P%j%(!<%7%g%s$@$1$G$O$J$/!"F1$8%W%m%
8%'%/%H$NCf$G$b!";~4V$K$h$C$F$"$kJ}K!O@$NJL8D$N%P%j%(!<%7%g%s$,N)$A8=$l$F$/$k
$+$i$G$"$k!# (B

$B$3$l$,!VJ}K!O@u67$K9g$o$;$FJ}K!O@$r2~JQ$G$-$k$h$&!"$I$3$+$KM>CO$b;D$5$J$/$F$O
$J$i$J$$$N$@!# (B

$B2~JQ2DG=@-$HJ}K!O@ (B

http://objectclub.esm.co.jp/eXtremeProgramming/xpVariations-j.html (2 of 7)05/12/2003 15:39:10


XP$BJQAU6J(B(Variations on a Theme of XP)

$BJ}K!O@$N!V%P%j%(!<%7%g%s$N:n$j0W$5!W$r9M$($k:]$K!"J}K!O@$K$bMM!9$J%?%$%W
$,$"$k$3$H$O5$$KN1$a$F$*$/$Y$-$@$m$&!#%P%j%(!<%7%g%s:n@.$N:]$K2]Bj$H$J$k$3$H
$O!"J}K!O@$N%?%$%W$4$H$K0c$&$+$i$@!#$H$$$&$o$1$G!"0J2<$KJ}K!O@$NJ,N`$r$^$H$a
$F$_$k!#$3$3$GMQ$$$kMQ8l$O!"$3$NO@J8$N$?$a$K:n$j=P$7$?$b$N$G$"$C$F!"J,N`$,I,$:$7
$b87L)$G$O$J$$$3$H$KCm0U$5$l$?$$!# (B

$B$^$:=i$a$Ke$2$k$N$O!"6qBN2=$5$l$?%W%m%;%9$@!# (B $B6qBN2=$5$l$?%W%m%;%9!
J (Bconcrete process $B!K (B $B$G$O!"/$7$@$1$G$"$k!#6qBN2=$5$l$?%W%m%;%9$ND9=j
$O!"%W%m%;%9$K=>$&$?$a$K$d$k$Y$-$3$H$r$+$J$jL@3N$K$7$F$$$k$3$H$@!#$7$+$7L@$i
$+$K!"2~JQ$,$G$-$J$$$H$$$&@)Ls$b$"$k!#$$$d!".$5$$$b$N$KN1$a$F$*$1$P!"%W%m%;%9$N;
Y;}

$B6qBN2=$5$l$?%W%m%;%9$@$H8GDjE*$9$.$k$N$G!"B?$/$N%W%m%;%9$O!"$I$&2~JQ$9
$Y$-$+$H$$$&E@$bL@3N$KDj$a$k$h$&$K$7$F$$$k!#$3$&$$$C$?%W%m%;%9$r!! (B
$BD4@02DG=$J%W%m%;%9!J (Btailorable process $B!K (B $B$H8F$V$3$H$K$7$h$&!
#D4@02DG=$J%W%m%;%9$O!"@5Ev$J%P%j%(!<%7%g%s$K$O$I$s$J$b$N$,$"$k$+!"$^$?$=$l
$i$N%P%j%(!<%7%g%s$O$$$D;H$&$Y$-$J$N$+!"$H$$$&$3$H$K%W%m%;%9$N@bL@$N>.$5
$/$J$$ItJ,$rHq$d$9$N$,IaDL$G$"$k!#%P%j%(!<%7%g%s$K4X$9$k%"%I%P%$%9$r<($7$F$$$k
$H$$$&E@$G$O!"6qBN2=$5$l$?%W%m%;%9$KBP$7$F:9$rIU$1$F$$$k$H8@$($h$&!#$7$+
$7!"$3$l$G$b40A4$H$O$$$($J$$!#$=$N2~JQ$r@5$7$/9T$&$K$O$I$&$9$Y$-$J$N$+M}2r$9$k$N
$O!"4JC1$K$O$$$+$J$$$3$H$,B?$$$+$i$@!#2?$+$d$m$&$H;W$C$?$i!"4pK\7A$N%W%m%;%9
$HA4$F$N%P%j%(!<%7%g%s$H$NN>J}$rM}2r$7$J$/$F$O$J$i$J$$!# (B

$B$3$3$G!"%W%m%;%9$N!V%5%$%:!W$KCeL\$7$F$_$h$&!#%W%m%;%9$N%5%$%:$H$O2?
$r0UL#$9$k$N$+$H$$$&$N$bFq$7$$LdBj$@$,!"0l$D$NJ}K!$H$7$F!"%W%m%;%9$r%^%9%?!<
$9$k$^$G$K$I$l$@$1$NNL$rFI$^$J$/$F$O$J$i$J$$$+!"$H$$$&4p=`$rMQ$$$F$_$k!#$9$k
$H!"D4@02DG=$J%W%m%;%9$N%5%$%:$OBg$-$/$J$k$O$:$G$"$k!#2?$r$7$J$/$F$O$$$1$J$/
$F!"2?$r>JN,$7$F$b9=$o$J$$$N$+!"A4$F$r=R$Y?T$/$9$N$,D4@02DG=$J%W%m%;%9$@$+$i
$@!#$7$+$7$3$l$@$H!"#S%5%$%:$N%W%m%;%9$r8+$$$@$9$?$a$K#L%5%$%:$N%W%m%;%
9$rM}2r$9$kI,MW$,=P$F$/$k!#>.$5$$%5%$%:$N%W%m%;%9$7$+I,MW$H$7$J$$$J$i!"$3$s$J$3
$H$O$7$?$/$J$$$@$m$&!# (B

$B>e5-$N$h$&$J0UL#$G!VD4@02DG=!W$J%W%m%;%9$O?tB?$/$"$k!#8=:_$b$C$H$bM-L>$J$b
$N$O (B $B%i%7%g%J%kE}0l%W%m%;%9!J (BRUP $B!K (B $B$G$"$k!#D4@0$NHO0O$,$3$l$h
$j9-$$$b$N$O$^$:8+$"$?$i$J$$!#$"$^$j$K$b9-$$$N$G!" (B $B%W%m%;%9!&%U%l!<%`%o!<
%/ (B $B$H$$$&L>A0$,IU$1$i$l$F$$$k!#@bL@$H$7$F$O!" (BRUP $B$r;H$&?M$O$N6qBN2=$5
$l$?%$%s%9%?%s%9$re$G$O!"=u$1$H$J$k$@$m$&!# (B

$B6qBNE*$J%9%F%C%W$K4X$9$k$3$H$O2?$R$H$D<($5$:!"$`$7$m%W%m%;%9$r2<;Y$($7$F
$$$k!"%=%U%H%&%'%"3+H/$K4X$9$k0l$D$N;WA[$r<($9$3$H$KFC2=$7$?%W%m%;%9$H$$
$&$b$N$bB8:_$9$k!#$3$&$$$C$? (B $B;WA[E*$J%W%m%;%9!J (Bphilosophical process $B!
K (B $B$,=@Fp$G$"$k$N$OEv$?$jA0$G!"$J$<$J$i!"F1$8;WA[$KBP$7$F!"$=$l$KB'$C$F%W%m

http://objectclub.esm.co.jp/eXtremeProgramming/xpVariations-j.html (3 of 7)05/12/2003 15:39:10


XP$BJQAU6J(B(Variations on a Theme of XP)

%8%'%/%H$r?J$a$k$?$a$NJ}K!$O$?$/$5$s$"$k$+$i$@!#:Y$+$$%9%F%C%W$d%P%j%(!<%7%g
%s$NOC$KF'$_9~$^$J$$J,!"D4@02DG=$J%W%m%;%9$d%W%m%;%9!&%U%l!<%`%o!<%/$N$h
$&$J%5%$%:$NBg$-$5$K4Y$i$:$K$9$`$@$m$&!#$7$+$7!";WA[E*$J%W%m%;%9$K6qBNE*$J
%9%F%C%W$,7g$1$F$$$k$H$$$&$3$H$O!"ASD $B$O$3$N;WA[E*$J%W%m%;%9$N9%Nc$@
$m$&!# (B

$B%W%m%;%9$H8F$P$l$F$$$J$$$+$b$7$l$J$$$,!"4X78$N?<$$$b$N$H$7$F%Y%9%H%W%i%/
%F%#%9=8$H$$$&9M$(J}$,$"$k!# (B $B%Y%9%H%W%i%/%F%#%9=8!J (Bbest practice
collection $B!K (B $B$NNc$H$7$FAj1~$7$$$N$O!" (BMcConnel $B$,$=$N$9$P$i$7$$Cx:n (B
Rapid Development $B$K<}$a$?%3%l%/%7%g%s$@$m$&!#$3$&$$$&%W%i%/%F%#%9=8$H$$
$&$b$N$O!"$=$l$>$l$,$"$kDxEYFHN)$7$?!"3+H/Cf$K9T$&$HNI$$$3$H$r0l%0%k!<%W$K$^$H
$a$?$b$N$"$k!#%W%i%/%F%#%9$N

$B%Y%9%H%W%i%/%F%#%9$ND9=j$O!"$3$s$,$i$,$C$?%9%F%C%W$NLV$NL\$r$?$0$k$h$&
$J$3$H$r$7$J$/$F$b!"$9$0MxMQ$G$-$k$H$$$&E@$K$"$k!#$3$l$O;H$($k!"$H;W$C$?$b$N$@
$1%T%C%/%"%C%W$9$l$P$h$$$N$@!#;d<+?H!"$$$o$f$k!VJ}K!O@!W$r?.MQ$7$F$3$J$+$C$??
M4V$J$N$G!"$3$N%Y%9%H%W%i%/%F%#%9!&%"%W%m!<%A$r5$$K$$$C$F$$$?!#$7$+
$7!" (BXP $B$,;d$NLX$r7<$$$F$/$l$?$N$O!"%W%i%/%F%#%9$O!VAj8_$KFHN)$7$?ItIJ!W$J$I
$G$O$J$$!"$H$$$&$3$H$@!# (BXP $B$N0RNO$O!"8DJL$N%W%i%/%F%#%9$+$i$b$?$i$5$l$k
$H$$$&$h$j$O!" (BKent $B$,A*$SH4$$$?%W%i%/%F%#%9=8$N!"Aj8_:nMQ$+$iM/$-=P$F$/$k
$b$N$J$N$@!# (BXP $B$N%W%i%/%F%#%9$r8DJL$K8+$F$$$k$@$1$@$H!"$=$N4N?4$J$H$3
$m$r

$B$D$^$k$H$3$m!"$I$N%"%W%m!<%A$K$b$"$k0UL#$GIT40A4$G$"$k!#6qBN2=$5$l$?%W%m
%;%9$O!"M}O@>e$O2~JQIT2DG=$@$7!"lLL$G$b!V2~JQ$N

XP $B$H$O2?$+ (B
XP $B$H2~JQ2DG=@-$r9M$($k$K$"$?$C$F!"$^$: (BXP $B$,!">e5-$NJ}K!O@J,N`$G$I$3$KF~$k
$+$r8+$kI,MW$,$"$k!#!V6qBN2=$5$l$?%W%m%;%9!W$KJ,N`$5$l$k$3$H$K0[O@$O$J$$$@$m
$&!# (BXP $B$K$O=>$&$Y$-%W%i%/%F%#%9$, (B12 $B8D$"$k$7!"$^$?!"$_$s$J$, (B12 $B8D
$N%W%i%/%F%#%9$NA4$F$r9T$&$h$&$K$H (BXP $B$NH=$,N)$C$F$7$^$C$?$/$i$$$@!# (B

$B$7$+$7 (BXP $B$NL%NO$O!" (BXP $B$N6qBNE*$J%W%i%/%F%#%9$Kl=j$G;H$C$F$_$h$&


$H9M$($F$$$k!# (B

XP $B$NIwJQ$o$j$JFCD'$G!";d$,$3$H$N$[$+5$$KF~$C$F$$$k$3$H$,$"$k!#$=$l$O!"<+J,$NE,
MQHO0O$N6-3&$r!"$-$C$A$j$HDj$a$F$$$k$3$H$@!#B?$/$F$b==?t?M$/$i$$$N!"F1$8>l=j$K$$
$k3+H/l9g$K$O!"$I$&$@$m$&$+!#!VE,1~2DG=@-!W$d!V?M4V;X8~!W$H$$$C$?86B'$O!"$3$3
$G$bI,MW$H$5$l$k$@$m$&!#$G$"$l$P!" (BXP $B$K$J$k$?$16a$E$1$kEXNO$r$7$F$b!"$h$$$N
$G$O$J$$$+!# (B

http://objectclub.esm.co.jp/eXtremeProgramming/xpVariations-j.html (4 of 7)05/12/2003 15:39:10


XP$BJQAU6J(B(Variations on a Theme of XP)

$B$+$/$7$FO@Ah$N2P38$,@Z$i$l$k!# (BXP $B$r69$/$H$i$($k$Y$-$@$$$&?MC#$H!"9-$/B*$($k


$Y$-$@$$$&?MC#$H$N4V$K5/$-$kO@Ah$@!# (BXP $B$O!V%V%i%s%I!W$K$J$C$F$7$^$C$?
$*$+$2$G!"O@Ah$O$5$i$K%R!<%H%"%C%W$9$k!#$_$s$J!"<+J,$?$A$, (B XP $B$r $B$I$3$^$G
$r (B XP $B$HG'$a$k$+$H!"$$$&8x<0@

XP $B$H<+8JE,1~@- (B
XP $B$r!"$+$C$A$j$H7h$a$i$l$?%W%m%;%9!"BgCO$K;I$5$C$?!V$/$$!W$HB*$($k$J$i$P!"$8$c
$"$3$l$H (BXP $B$,<+8JE,1~E*$G$J$/$F$O$J$i$J$$$H$$$&9M$($H!"$I$&$D$8$D$^$r$"$o$;$k
$N$@$m$&$+!# (B

$BEz$($N%+%.$O!" (BXP $B$N$?$a$K=,=OEY%l%Y%k$rDj5A$7$?$i$I$&$+!"$H$$$&

● $B%l%Y%k (B 1 $B$G$O!"K\$K=q$+$l$?$H$*$j$KA4$F$N%W%i%/%F%#%9$r $B%l%Y%k


(B 2 $B$G$O!" (BXP $B$r%m!<%+%k$J>r7o$KE,1~$5$;$k!# (B
● $B%l%Y%k (B 3 $B$G$O$b$&!" (BXP $B$r

$B$3$3$K!"<+8JE,1~@-$NK(2j$,8+$($k (B -- XP $B$r$d$jB3$1$k$?$a$K!" (BXP $B$rE,1~$5$;$kI,


MW$,$"$k!#;d$N8@MU$G8@$$BX$($F$_$h$&!'$b$7%$%F%l!<%7%g%s$NO;2sL\$K$J$C$F
$b!"0l2sL\$HF1$8$d$j$+$?$G (BXP $B$r$d$C$F$$$k$s$@$C$?$i!"$=$l$O (BXP $B$r

$B$7$+$7$3$3$G!"=,=O$K;j$kCJ3,$N$3$H$rK:$l$F$O$$$1$J$$!#>e5-$N!V%l%Y%kJ,$1!W$@
$H!"E,1~$r;O$a$kA0$K$O!"?M!9$,5,B'DL$j$K (BXP $B$rl$GBN83$9$k$3$H$NB-2<$K$b5Z$P$J$
$!#?.$8$FM_$7$$!# (BXP $B$O$3$&$J$k$@$m$&$H$$$&;d$NM=A[$H!"

$B$3$l$,!" (BXP $B$r2~A1$9$k$K$O$I$&$7$?$i$$$$$+$J$I$H$$$&;W:w$K$U$1$kA0$K!"$^$:


$O5,B'DL$j$K$d$C$F$_$m$h!"$H (BXP $B'?M$@$C$FM=A[$G$-$J$$$O$:$@!"$H9M$($k$N
$OEvA3$G$"$j!"$G$"$l$P!"$=$N!V7P83!W$r7P$F$$$J$$B>?M$N8@MU$J$IJ9$-$?$/$J$/$J$m$&
$H$$$&$b$N$@!# (B

$B6qBN2=$5$l$? (B XP $B$N%P%j%(!<%7%g%s$r:n$k (B
$B$3$N$3$H$O!"%W%m%;%9$r2~JQ2DG=$J$b$N$K$9$kJ}:v$K$D$$$FJL$J;kE@$rM?$($F$/$l
$k!#$3$NJ}:v$O!"$"$k6qBN2=$5$l$?%W%m%;%9$r4pAC$KCV$/!#$3$s$,$i$,$C$F$$$k$,
D4@02DG=$J%W%m%;%9$N;H$$J}$K$H$j$/$`Be$o$j$K!"$^$:$O!"L@$i$+$K<+J,$NMW5a$K:G
$b9gCW$9$k$b$N$G$O$J$$$H$7$F$b!"$"$k6qBN2=$5$l$?%W%m%;%9$rA*$V$H$3$m$+$i;O$a
$h$&!#$3$NHs:GE,2r$@$,6qBNE*$J%W%m%;%9$H$D$-$"$C$F$_$k!#$=$&$9$k$H!"%W%m%;
%9$K4X$7$FIaDL$J$i8+2a$4$7$F$7$^$&$h$&$J=EMW$J$3$H$r3X$Y$k$@$m$&!#$=$&$J$C$?
$i!"2~JQ$r3+;O$9$k!#B>$N%W%m%;%9$+$iCN8+$r

$B$3$3$K!" (BXP $B$K$*$1$k!V2~JQ!W$N%+%.$,$"$k!#J}K!O@$,$I$&5!G=$9$k$+K\Ev$KM}2r

http://objectclub.esm.co.jp/eXtremeProgramming/xpVariations-j.html (5 of 7)05/12/2003 15:39:10


XP$BJQAU6J(B(Variations on a Theme of XP)

$7$F=i$a$F!"$=$NJ}K!O@$r$I$&D4@0$9$l$P$h$$$N$+$bK\Ev$KM}2r$G$-$k$N$@!#J#;
($G=ENL5i$NJ}K!O@$J$i!"$3$l$@$1$GO+NO$rHq$d$7$F$7$^$&$@$m$&!#%i%$%H$JJ}K!O@
$O!"$o$:$+$J%W%i%/%F%#%9$H!"%$%s%/%j%a%s%?%k$J3+H/$d3X=,$r%5%$%/%k$H$7$F9T
$&$3$H$X$N6/$$;V8~$H$,$"$k$*$+$2$G!"$<$s$<$s.$5$J$b$N$K:Y$+$$DI2C$r9T$C$F2~JQ$9$k
$[$&$,!"Bg$-$J$b$N$r:Y$+$$:o=|$K$h$C$F2~JQ$9$k$h$j$b4pK\E*$K$:$C$H3Z$J$N$@$+$i!# (B

$B$7$+$7 (B XP $B8GM-$N;v>p$H$7$F!" (BXP $B$N;EAH$_$NM}2r$GBgJQ$J$3$H$,$"$k!#$=$l


$O!"$d$C$F$_$J$$$+$.$jK\Ev$KM}2r$9$k$N$O:$Fq$@$H$$$&$3$H$@!#$G$"$l$P!"$=$N!V46$8!
W$,=o$KCm0U$7$J$/$F$O$$$1$J$$!" (B

$B0lHV$h$$$N$O!"5,B'DL$j$K (BXP $B$r9T$&$3$H$G%W%m%8%'%/%H$r%9%?!<%H$5$;$k$3


$H$@!#$=$7$F!"Mn$A$D$/$^$GFs!";0$N%$%F%l!<%7%g%s$r9T$$!"$=$N>e$GD4@0$r9T$&!#
$G$b$[$H$s$I$N>l9g!"$=$l$r$_$s$J$G$-$F$J$$$h$&$@!#Be$o$j$K$_$s$J$O!"3Fl9g$O!" (BXP
$BA4BN$,5!G=$9$k$H$3$m$rL\7b$7$??M$K$D$$$F$b$i$C$F!"$=$NCN<1$K$h$j%,%$%I$7$FLc
$&$3$H$,$h$j=EMW$K$J$C$F$/$k$H;W$&!# (B

$B$+$/$7$F (BXP $B$K$*$$$F$b!"=i$a$K9T$&$Y$-%W%i%/%F%#%9$H@Q$`$Y$-7P83$,


$"$k!"$H$$$&$3$H$K$J$k!#$7$+$7$3$l$O$O$8$^$j$K2a$.$J$$!# (BXP $B$r<+J,$N>u67$KE,1~$5
$;$J$/$F$O$J$i$J$$$N$@$,!"$=$l$r!" (BXP $B$,$&$^$/5!G=$9$k$H$O$I$&$$$&$3$H$+M}2r$7$?
>e$G9T$&$3$H$,=EMW$@!#$7$P$i$/$N4V$O!"$3$3$rJQ$($?$[$&$,$&$^$/9T$/$N$K$H;W$C$?
$H$7$F$b2fK}$7$F!" (BXP $B$r$J$k$?$1K\$K=q$+$l$?7A<0$KCi

XP $B$H$=$NE,MQHO0O (B
$B>-Mh!" (BXP $B$H$=$NE,MQHO0O$O$I$&$J$k$N$@$m$&$+!#$3$3 (B ThoughtWorks $B?t$,3
+H/h$;$k$?$a!"%W%i%/%F%#%9$K

$B$K$b4X$o$i$:;d$O!" (BXP $B$,$=$NBgCO$K;I$5$C$?!V$/$$!W$r!"$-$A$s$HDj$a$i$l$?HO0O


$NOHFb$K<}$a$F$/$l$?$[$&$,$h$$$H;W$&!#;dC#$,$3$3$G9T$C$F$$$k$3$H$O!" (BXP $B
$N1F6A$rA0$OIU$1$J$$$@$m$&!#$H$$$&$N$b!"$b$&FCDj$N%W%m%8%'%/%H$KBP$7$F$+
$J$jE,1~$7$F$7$^$C$F$*$j!"$3$l$+$i$bE,1~$r7+$jJV$7$F$$$/$N$@$+$i!"$3$l$, (B XP $B$+$I$&$
+$J$I$H$$$&$3$H$O;dC#$O5$$K;_$a$F$$$J$$$N$@!#B>$N%W%m%;%9$b;w$?$h$&$JN)$A8=
$o$lJ}$r$9$k$@$m$&$7!"$=$&$J$k$Y$-$J$N$@!# (BXP $B$K1F6A$r

XP $B$r!VGc$&!W (B( $B$H$$$C$F$b9XF~Hq$O$+$+$i$J$$$N$@$, (B) $B$3$H$K$7$?$H$-


$K!";dC#$,.$5$/$F!"6qBNE*$G!"$=$l$f$($KD4@0$,I,MW$J2U=j$,$I$3$+GD0.$7$d$9$$!"$=$s$J%
W%m%;%9$H$D$-9g$C$F$-$? (BXP $B%3%_%e%K%F%#$+$i$N7P83$r$$$?$@$/$3$H$,=PMh
$k!#%$%F%l!<%7%g%s$r2?2s$+$3$J$9$^$G$O!"%3%_%e%K%F%#$+$i$N%"%I%P%$%9$K=>
$&!#$7$+$7u67$X$NE,1~$r9T$&I,MW$,$G$F$/$k!#$3$3$G$b7P83$rJX$j$K$9$k$7$+L5$$$,!"$@$
+$i$H$$$C$F!" (BXP $B$r;H$C$F$$$?$3$H$r!V<:GT$N;~$N$$$$$o$1 (B(cover your ass) $B!W
$KMQ$$$k$3$H$O$G$-$J$$!# (BXP $B$K8B$i$:B>$N%i%$%H$JJ}K!O@$G$"$C$F$b!"$3$N

http://objectclub.esm.co.jp/eXtremeProgramming/xpVariations-j.html (6 of 7)05/12/2003 15:39:10


XP$BJQAU6J(B(Variations on a Theme of XP)

© Copyright Martin Fowler, all rights reserved

$BK]Lu (B: $B>.Ln (B $B9d (B $Id: xpVariation-j.html,v 1.10 2001/01/19 06:16:16 ono Exp $

http://objectclub.esm.co.jp/eXtremeProgramming/xpVariations-j.html (7 of 7)05/12/2003 15:39:10


The Almighty Thud

$BJ,8|2a$.$k!V%I%-%e%a%s%H!W (B
( $B86Bj (B: The Almighty Thud)

by $B%^!<%A%s!&%U%!%&%i!< (B(Martin Fowler): November/December 1997


$B9f$X$N4s9F (B

$B0MMj$r@A$1$?%*%V%8%'%/%H%b%G%k$N%l%S%e!<$K$D$$$F!"$=$N8\5R$HOC$r$7$F
(B $B$$$k;~$@$C$?!#!V@h$K%I%-%e%a%s%H$@$1!"$*Aw$j$7$?J}$,JXMx$G$9$+$M!)!W (B
$B$3$&J9$+$l$F!"5$>h$j$O$7$J$+$C$?$,!"$($(!"$O$$!"$=$NJ}$,JXMx$G$9$M!" (B $B$HEz$($F
$*$$$?!#FsF|8e$K!"M9JX6I$NG[C#IW$,;d$N<+Bp$N%I%"$NA0$K>.Jq$rMn (B $B$7$F$$$C$?;~
$K$O%G%+%$2;$,$7$?!#M%$K (B 1.5 $B%$%s%A$NI}$,$"$k!V%I%-%e%a%s%H!W (B $B$G
$"$C$?!# (B

$B3+$$$F$_$?$i!"2?$+$N (B CASE $B%D!<%k$+$i$N%W%j%s%H=PNO$@$C$?!#3($,$$$/ (B $B


$D$+$"$C$F!"8e$O (B $BA4$F$N%/%i%9$NA4$F$NB0@-$HA4$F$N%*%Z%l!<%7%g%s$K4X$9
(B $B$kE0Dl$7$?@bL@=q$-!#$=$NA4It$K!VDj5A!W$,IU$1$i$l$F$$$k!#7@Ls (B(Contract) $B%/
%i%9$O!" (B" $BJ#?t$N;22C $B$3$N (B 1.5 $B%$%s%A$NI}$rFI$_@Z$C$?8e$b!"$5$7$F;d$NM}
2r$OA}$($J$+$C$?!#$= (B $B$N%*%V%8%'%/%H$,2?$G$"$k$+!"$H$$$&$3$H$O$?$/$5$s=q$+$l
$F$$$?$,!"2?$r (B $B!V$9$k!WL\E*$G$=$3$K$"$k$N$+!"$H$$$&$3$H$K$D$$$F$O!"$[$H$s
$I@bL@$,$J$+$C (B $B$?$+$i$@!# (B
$B$3$&$$$&L\$K9g$&$N$O=i$a$F$8$c$J$$$7!"$3$l$G:G8e$@$H$bE~Dl;W$($J$$!# (B

$B$J$<$\$/$i$O$o$6$o$6!"%b%G%j%s%0$H$+%I%-%e%a%s%H2=$H$+$9$k$N$@$m$& (B $B$
+!):n$C$?$H$3$m$Go$KB?$/!" (B $B;d$O%=%U%!!<$GFH$jG:$`$3$H$H$J$k!# (B

$BLdBj$N0lIt$O!"$_$s$J$,%I%-%e%a%s%H@8@.$K;H$C$F$$$k (B CASE $B%D!<%k$K$" (B $B


$k (B(CASE $B%D!<%k$K$O!"%I%-%e%a%s%H2=$H%3!<%I@8@.$H$NFs $B$7$+$7!"$3$NO2=
$9$k$3$H$,!"%I%-%e%a%s%H$G$NOS$N8+$;$I$3 (B $B$m$G$"$k!#$3$&$9$l$P=EMW$JNN0h
$,6/D4$5$l!">\:Y$O%3!<%I$K$^$+$;$F$7$^$( (B $B$k$N$@!# (B

$B7k6I!"%I%-%e%a%s%H$O4J7i$GL5$/$F$O$J$i$J$$!#%I%-%e%a%s%H$,4J7i$G$"$C (B $B$F
$O$8$a$F!"$_$s$J$bFI$s$GM}2r$7$F$/$l$k$@$m$&!#%I%-%e%a%s%H$,4J7i$G$"$C (B $B$F$O
$8$a$F!"$"$J$?$b99?7$7$h$&$H$$$&5$$K$J$k$@$m$&!#!VA4$F!W$K$D$$$F5- (B $B=R$9$k$3

http://objectclub.esm.co.jp/eXtremeProgramming/thud-j.html (1 of 3)05/12/2003 15:39:13


The Almighty Thud

$H$J$I=PMh$J$$$7!"$=$&$9$Y$-$G$b$J$$$N$@!#M'?M$N0l?M$,$"$k%W%m (B $B%8%'%/%H
$K$D$$$F8l$C$F$/$l$?!#$=$N%W%m%8%'%/%H$G$O!"%3!<%I$,D9$$$+$i$G (B $B$O$J$/%I%-
%e%a%s%H$,D9$$$+$i!"$_$s$J%/%i%9$NL>A0$rJQ$($?$,$i$J$$$H$$$&!# (B $BJ8>O2=$,LdBj$K
$J$C$?$i!"BP:v$r9V$8$k$Y$-$@!#%I%-%e%a%s%H$N$9$/$J$/$H$b (B $BH>J,$O!" $B2?$r=q$/$Y
$-$+!) (B $B=q$/$Y$-$3$H$r7h$a$k$K$O!"$I$&$7$?$i$h$$$N$@$m$&$+!#;DG0$J$,$i!"$"$J$? (B
$B<+?H$N%W%m%U%'%C%7%g%J%k$JH=CG$K$^$+$5$l$F$$$k$H$7$+8@$$$h$&$,$J$$!#$h
(B $B$j$I$3$m$H$J$k%k!<%k$O$J$$!#@_7WR2p$7$h$&!# (B

$B$b$7%7%9%F%`$,$=$l$[$IBg$-$/$J$$$J$i!"%7%9%F%`$r (B(UML $B$H$+ (B Java $B$H (B $B


$+$G (B) $B%Q%C%1!<%8$KJ,3d$9$k!#3F%Q%C%1!<%8$O!"0l$D$NFCDj$NL\E*$N$?$a$K6
(D4 (B $B$9$k%/%i%972$+$i9=@.$5$l$k!# (B $B%7%9%F%`$NA4BN9=B$$r!"%Q%C%1!<%8$H
%Q%C%1!<%84V$N0MB84X78$H$N?^$K$h$C$F (B $B%I%-%e%a%s%H2=$9$k!# (B( $B$3$l$O
(B UML $B$@$H!"%/%i%9?^$NFCA0$G8F$V$3$H (B $B$,B?$$!#>\$7$/$O;d$N (B UML $BK\$rFI
$s$GM_$7$$!# (B) $B@_7W$r8+D>$7$F!"$3$N0MB84X78$,:G>.$K$J$k$h$&$K$9$k!#$3$l$O!"%
7%9%F%`Fb (B $B$N%+%C%W%j%s%0$r>.$5$/$9$k$&$($G=EMW$G$"$k!# (B( $B$d$jJ}$K$D$
$$F=q$+$l$?K\ (B $B$O>/$J$$$,!";d$NCN<1$G$O%m%P!<%H!&%^!<%A%s (B "Designing Object-
Oriented C++ Applications Using the Booch Method" $B$,:G$bM%$l$F$$$k!# (B)

$B3F%Q%C%1!<%8$K$?$$$7$F4JC1$J%I%-%e%a%s%H$rIU5-$9$k!#$3$3$K$O4pK\E* (B $B
$K!"%Q%C%1!<%8$,9T$&$3$H$G%+%.$H$J$k$b$N$K$D$$$F!"$=$7$F$=$NO$r=q$/!#Jd=u$H$7
$F (B UML $B?^$rMQ$$$F$b$h$$!#%Q%C%1!<%8 (B $BFb$N=EMW$J%/%i%972$K4X$7$F%/%i
%9?^$r0lKg=q$/$,!"A4It$N%/%i%9$KIU$$$F=q (B $B$+$J$/$F$b$h$$!#3F%/%i%9$K$O=EMW
$JB0@-$HA`:n$N$_$r5-=R$7!"A4It=q$/$3$H (B $B$O$7$J$$!#$l%$%s%?%i%/%7%g (B $B%s?^
$rIA$/!#$b$7Cm0U$9$Y$-%i%$%U%5%$%/%k$r$?$I$k%/%i%9$,$"$l$P!">uBV?^ (B $B$rIA$/!#%
I%-%e%a%s%H$O$J$k$Y$/>.$5$/$^$H$a$F!":G?7>uBV$X$N99?7$,LLE]$G (B $B$J$$$h$&$K$9
$k!#;d$OIaDL!" (B12 $B%Z!<%8$r1[$($J$$$h$&$K5$$rIU$1$F$$$k!# (B

$B3F%Q%C%1!<%8$4$H$N%I%-%e%a%s%H$@$1$G$O$J$/!"%Q%C%1!<%84V$K$^$?$,$k (B
$B%3%i%\%l!<%7%g%s$K$D$$$F$b5-=R$,$"$k$HJXMx$G$"$k!#$3$N$?$a$K!"%+%.$H$J (B $B
$k%f!<%9%1!<%9$r%7%9%F%`$+$i8+$D$1$@$7!"$=$l$r%$%s%?%i%/%7%g%s?^$H@bL@ (B
$B$G%I%-%e%a%s%H2=$9$k!#4X78$9$k%/%i%9$N$J$+$G=EMW$J$b$N$ro$K99?7$9$k $B$J$s
$H$$$C$F$b%3%_%e%K%1!<%7%g%s$G$"$k!# (B $B$3$N5-;vA4BN$G;d$,6/D4$7$F$-$?$3$H
$O!"%3%_%e%K%1!<%7%g%s$G$"$k!# (BCASE $B%D!<%k72$K$OHcH=E*$J$3$H$r=R$Y$?
$,!"$3$l$b$D$^$j$O!"%D!<%k$r;H$C$F$$$k (B $B$+$i$H$$$C$F$=$N?M$,%3%_%e%K%1!<%7%
g%s$7$F$$$k$H$O8B$i$J$$$N$@!"$H8@$$ (B $B$?$+$C$?$o$1$@!#$I$s$J%D!<%k$G$"$l%3%_
%e%K%1!<%7%g%s$rB%?J$7$?$jAK32$7 (B $B$?$j$9$k2DG=@-$,$"$k!#MW$O;H$$J} $B;d$,CN
$C$F$$$k%W%m%8%'%/%H$G!"%^%k%A%f!<%6!< (B CASE $B%D!<%k$rGc$C$F!" (B $B$I
$N3+H//$J$+$C (B $B$?!#$3$N>u67$r;!CN$7$?%W%m%8%'%/%H$N%"!<%-%F%/%H$O!"%*%U
%#%9$NJI$r;H$C (B $B$F!"H>%@!<%9$K$b$J$k%7%9%F%`$N $B$H$3$m$G;d$O!"$3$N5-;v
$r=q$-;O$a$k$K:]$7$F!"<+J,$,8l$l$kFbMF$NB?$5 (B $B$K05E]$5$l$F$7$^$C$?!#$?$/$5$s$N0oOC
$d%"%I%P%$%9$,G>N"$KIb$+$s$G$-$?$N (B $B$@!#$7$+$7;d$O!"FI/$7$7$+?($l$k$3$H$,=PMh
$J$$$@$m$&$3$H$r$o$-$^$($F$$$?!#$I$&$7$F$b?( (B $B$l$J$/$F$O$J$i$J$$=EMW$J0lIt$rA*
$S=P$9I,MW$,$"$C$?!#$=$l$,%3%_%e%K%1!< (B $B%7%g%s$@!#$h$$%3%_%e%K%1!<%7%g

http://objectclub.esm.co.jp/eXtremeProgramming/thud-j.html (2 of 3)05/12/2003 15:39:13


The Almighty Thud

%s$N%+%.$O!"=EMW$JItJ,$r6/D4$9$k$3$H$@!#A4 (B $B$F$r=R$Y?T$/$9$N$O%3%_%e%K%1!
<%7%g%s$H$O8@$o$J$$!#$=$l$O5U$K!"FIpJs$NA*Br$3$=!"%3%_%e%K%1!<%7%g%s
$G=EMW$J$3$H$N (B $B0l$D$G$"$j!"$5$i$KA4$F$N@_7W

$BK]Lu (B: $B>.Ln (B $B9d (B

http://objectclub.esm.co.jp/eXtremeProgramming/thud-j.html (3 of 3)05/12/2003 15:39:13


Software

Last Updated: 20 November 2003

Our 20th Anniversary


Past editors in chief reflect on the state
of software engineering and the
magazine since its inception in 1983.

The Compleat
Requirements Analyste
Reading Dostoyevsky or joining a drama
group might just make you a better
requirements engineer.

The State of the Interested in


Practice reviewing for
Software?
A collection of articles previously
posted on the IEEE Software homepage, Visit
including a report on the US Software
industry and a look at Web application
design.

for more SE
resources

For those of you not yet subscribing, try


the May/June 2001 issue on
"Organizational Change" for free. This
issue covers licensing engineers,
groupware, invisible users, and more.
DOWNLOAD NOW! (zip file)

Want to submit a paper to IEEE Software?


Our new online manuscript submission service, including answers to any questions you
might have about the submission process, is now available.

The full text of IEEE Software is available to Computer Society members who have an online subscription
and a IEEE Web Account.

Send general comments and any questions about the IEEE Computer Society's Web site to help@computer.org.
Read our Privacy and Security guidelines.

This site and all contents (unless otherwise noted) are Copyright ©2003, IEEE, Inc. All rights reserved.

http://www.computer.org/software/05/12/2003 15:39:21

Das könnte Ihnen auch gefallen