Before we dive into the details of the Cleanroom process, here is an example of two important software design concepts: separation of concerns and factoring.
A designer knows he has achieved perfection not when there is nothing left to add, but when there is nothing left to take away.
|-- Antoine de Saint Exupéry|
I conclude that there are two ways of constructing a software design: One is to make it so simple that there are obviously no deficiencies and the other way is to make it so complicated that there are no obvious deficiencies.
|-- C. A. R. Hoare, Comm. ACM 24(2), Feb. 1981: p. 81|
The idea behind separation of concerns is that each piece of a program has certain functional requirements to worry about, and those worries should be localized to that particular piece.
Let's consider a specific application: a ticketing agency. The purpose is to connect patrons with tickets to some performance.
When a promoter books an event in a hall, the ticketing agency must know exactly how many seats are available at each price level. It is the ticket agency's job to keep track of which seats have been sold, and to whom.
We might write a Python class called
TicketAgency to implement this functionality.
When we start designing the class, we can specify three
different areas of concern in the implementation.
TicketAgency class's concern is
matching up patrons with seats.
We might design another class called
Venue whose concern it is to keep track of
the number and arrangement of seats: how many in each
price class, which ones are on the aisle, and so
Another class called
concerned with patrons: how to contact them, and the
specific needs of each patron.
The way that separation of concerns works in this
application is that information about seats resides in
Venue class; information about patrons
resides in the
PatronData class; and the
TicketAgency class is concerned only about
the connections between seats and patrons.
The concept of separation of concerns is related to the concept of single-sourcing: there must be exactly one definition of each entity, and others use that single definition. Having two different lists of the seats in a venue inside your application is a sign of trouble: if the lists disagree, how do we know which one is right?
In practice, when we apply the idea of separation of
concerns, it becomes clear where in our design each
functional piece should live. In the example,
information about a seat's price and location is local to
Venue class; information about a
patron's phone number is local to the
PatronData class; and only the
TicketAgency class cares which patron is
associated with which seat.
As we push this design farther down into the details, we
may find that the
Venue class is a
container for instances of a
each of which describes just one seat. This process of
dividing separate concerns into smaller sub-concerns is
sometimes called factoring. The
class's proper concern is storing, searching and
Similarly, when we start writing the
PatronData class, we might factor it so that a
PatronData instance is a container for
Patron instances. The proper concern of a
Patron instance is information about one
ticket buyer; the proper concern of the
PatronData class is organizing all its contained
For example, suppose that one specific seat is damaged by a
falling meteor. To insure that that seat does not get sold,
Venue class must have a way to find and
delete that seat from its set of available candidates; that is
in its proper area of concern.