Next / Previous / Contents / Shipman's homepage

3.2. Design factoring and separation of concerns

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.

  1. The TicketAgency class's concern is matching up patrons with seats.

  2. 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 forth.

  3. Another class called PatronData is 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 the 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 the 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 Seat class, each of which describes just one seat. This process of dividing separate concerns into smaller sub-concerns is sometimes called factoring. The Venue class's proper concern is storing, searching and retrieving Seat instances.

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 patrons.

For example, suppose that one specific seat is damaged by a falling meteor. To insure that that seat does not get sold, the 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.