< Zurück | Inhalt | Weiter >

Chapter 12

Analysis and Design: Seeking the Objects


In this chapter, we will present the barest outline of a software development methodology. For some readers, this will be simplistic and unsuitable. In our experience, however, there are many businesses out there with very small devel- opment teams that have very little software engineering experience, even though they have considerable technical and programming skill. Our goal here is to present a bare minimum of analysis and design method, so that we can be sure we have a common basis for discussing the issues of object-oriented analysis and design.



In this chapter you will learn a very simple method for object discovery and a simple method of documenting this process.



So, you have some requirements. Maybe you even have some UI prototypes. How do you turn that into an object-oriented design for Java classes? How do you confront the paralyzing blank white of your whiteboard, terminal session, or easel?

The simplest way is to start with real-world objects. Stop thinking about everything you have read about object-oriented programming. Instead, ask yourself, “What are the real objects involved in this problem?”

In our case, the more you look at it, the simpler it gets. For the moment, the only real objects we have are people—the users—and accounts, that is, named pools of money. We know that users get accounts from “above,” and that they may break those pools down into subaccounts, which they may own or delegate to other users.

At the broadest level, then, we seem to have two “classes” or types of real-world objects: Accounts and Users.


So, we need two classes. But what goes into those classes? How do we go about putting the substance into this simplistic framework?

In their now (semi)famous paper presented at the object-oriented program- ming conference OOPSLA in 1989, Kent Beck and Ward Cunningham intro- duced a simple, practical design tool for object-oriented design based on a simple, practical 3x5 file card. The CRC cards for our classes are shown in Figures 12.1 and 12.2.

But we are getting a bit ahead of ourselves. These CRC cards are an end product of analysis. They are the starting point for coding. Let’s talk a little bit about what is on these cards and how we came to that content.


The basic technique for doing OOA1 with CRC cards is to start with a stack of blank cards. Assemble a design team (this may be one person, or this may


1. (object-oriented analysis)


a pool of dollars

members collaborations

* name - a String * persistence (CRUD)

* owner - a User * User

* amount - an SAMoney object

* children - an ArrayList (of Accounts)

* parent - an Account

12.4 Finding the Objects 281



a pool of dollars

members collaborations

* name - a String

* owner - a User

* amount - an SAMoney object

* children - an ArrayList (of Accounts)

* parent - an Account

* persistence (CRUD)

* User


Figure 12.1 Account CRC card


someone who manages budget dollars

members collaborations

* name - a String

* home - an Account

* persistence (CRUD)

* Account

Figure 12.2 User CRC card

be dozens).2 The first step should always be the nomination of the real-world objects. Don’t edit or critique at this point. If someone says “computer” as an object, write “Computer” on the top of a card and put it on the table. If someone says “Manager” write it on a card and put it on the table.


2. It is fun to gloss over such a complex topic with a single sentence! Obviously, the composi- tion of a design team is a complicated matter. At the very least, a design team must include a representative from the programming team and a future user of the system. On small, simple projects, that may be all you need. On more complex or mission-critical systems, there will have to be additional representatives, such as people from Operations, Support, Training, Quality Assurance, and so on.

To take our example, suppose we have the following list of CRC cards after such an open brainstorming session:

• Database

• Capital Account

• Current Account


• Computer


• Director

• Keyboard

• Manager

Where do you go from here? Let’s articulate a general principle.

The first principle. If we could teach a programmer only one thing about software design, it would be this idea: less is more. Or, to quote Antoine de Saint-Exupéry: “Perfection is achieved not when nothing can be added, but when nothing can be taken away.” Or, to put it yet another way, always use the KISS3 principle. The best object design is the smallest possible number of classes that model the real objects and meet all the requirements.

You are seeking simplifying abstractions.

First of all, all the objects that represent technologies or implementation details should be removed. In our list, this would include “Database,” “Com- puter,” and “Keyboard.” While it is likely that all three will be involved in the final product, they are not objects in the problem space. There is no theoretical reason why an OOA session cannot produce a manual, noncomputer solution. It is a common tendency to leap from problem analysis directly to technical solutions. “We can write that in Java,” “We can store those in Oracle,” “That could be an XML file.” Statements like these are to be avoided at this stage. Those are details about the implementation. You haven’t got a design to implement yet!

As we said, you are seeking simplifying abstractions. The next step, after culling cards that do not represent real objects in the problem space, is to group together the cards that have any attributes in common. If we look at our


3. An acronym for: Keep It Simple, Stupid!

12.5 Finding the Methods and Attributes 283


remaining cards, we can quickly see that we have two cards that are accounts: “Capital Account” and “Current Account.” These are both pools of money. Put them on top of one another on the table. Likewise, it is fairly obvious that “CEO,” “CFO,” “Director,” and “Manager” are all people. Put them together on the table.

Remember that we are looking for simplifying abstractions. The grouped cards should all be obviously variant types of a generic class of objects. In our example, the one is a stack of Accounts, and the other is a stack of People, or, as we will call them, Users. Create new cards for these generic classes. Make a card with “Account” at the top and put it above the first stack. Make another card with “User” at the top and put it above the second stack.

There are two ways that this might simplify your design. For now, all cards below the abstract cards are “on probation.” We are going to move on to define the attributes (data) and methods (behavior) of our abstract classes. If the ab- stract class can handle all use cases without having to treat any of the more specific classes differently, then the specific cards are discarded. If not, then all functionality that is common across the more specific types will be put on the abstract class card, and only those data and behaviors that are different will be put on the more detailed cards.

In the first case, the simplification is a reduction of several potential classes to a single class. This is always a good thing, when it is possible. In the second case, you are identifying potential inheritance relationships.4


The next step is to start identifying the data and behavior that characterize your classes. Always put such items on the most abstract class first. The only time to add an attribute or method to a more specific class is when it applies to that class and only that class—in other words, only when it represents a difference between the general case and the specific case.5


4. We’ll talk more about that later in the book. As it happens, all of our simplifications in this chapter are examples of the first case.

5. In complex cases, you may find an attribute or method that applies to several, but not all, of the specific cases. In such a case, a new abstract class below the main abstract class, but above all the specific classes that share that attribute or method, may be called for.


So far, we have walked you through a very simple example, and we have made sound choices at every step. In more complex cases, even the best of us will make mistakes. We will head down blind alleys. We will group things together that might belong in separate abstract categories, but should, perhaps, share an interface. These are not so much errors as judgment calls, and skill at recogniz- ing them and making the correct decisions comes only with experience.

For now, the most important questions to ask include:


• Do I need this class?

• Should I get functionality by inheritance or composition?

• Does this attribute or method belong here?