|
|
|
|
Phase 2: How will we build it?
In this phase you must come up with a
design that describes what the classes look like and how they will interact. An
excellent technique in determining classes and interactions is the
Class-Responsibility-Collaboration
(CRC) card. Part of the value of this tool is that it’s so low-tech: you
start out with a set of blank 3” by 5” cards, and you write on them.
Each card represents a single class, and on the card you write:
- The name of the class.
It’s important that this name capture the essence of what the class does,
so that it makes sense at a
glance.
- The
“responsibilities” of the class: what it should do. This can
typically be summarized by just stating the names of the member functions (since
those names should be descriptive in a good design), but it does not preclude
other notes. If you need to seed the process, look at the problem from a lazy
programmer’s standpoint: What objects would you like to magically appear
to solve your
problem?
- The
“collaborations” of the class: what other classes does it interact
with? “Interact” is an intentionally broad term; it could mean
aggregation or simply that some other object exists that will perform services
for an object of the class. Collaborations should also consider the audience for
this class. For example, if you create a class Firecracker, who is going
to observe it, a Chemist or a Spectator? The former will want to
know what chemicals go into the construction, and the latter will respond to the
colors and shapes released when it
explodes.
You may feel like
the cards should be bigger because of all the information you’d like to
get on them, but they are intentionally small, not only to keep your classes
small but also to keep you from getting into too much detail too early. If you
can’t fit all you need to know about a class on a small card, the class is
too complex (either you’re getting too detailed, or you should create more
than one class). The ideal class should be understood at a glance. The idea of
CRC cards is to assist you in coming up with a first cut of the design so that
you can get the big picture and then refine your design.
One of the great benefits of CRC cards is
in communication. It’s best done real-time, in a group, without computers.
Each person takes responsibility for several classes (which at first have no
names or other information). You run a live simulation by solving one scenario
at a time, deciding which messages are sent to the various objects to satisfy
each scenario. As you go through this process, you discover the classes that you
need along with their responsibilities and collaborations, and you fill out the
cards as you do this. When you’ve moved through all the use cases, you
should have a fairly complete first cut of your design.
Before I began using CRC cards, the most
successful consulting experiences I had when coming up with an initial design
involved standing in front of a team, who hadn’t built an OOP project
before, and drawing objects on a whiteboard. We talked about how the objects
should communicate with each other, and erased some of them and replaced them
with other objects. Effectively, I was managing all the “CRC cards”
on the whiteboard. The team (who knew what the project was supposed to do)
actually created the design; they “owned” the design rather than
having it given to them. All I was doing was guiding the process by asking the
right questions, trying out the assumptions, and taking the feedback from the
team to modify those assumptions. The true beauty of the process was that the
team learned how to do object-oriented design not by reviewing abstract
examples, but by working on the one design that was most interesting to them at
that moment: theirs.
Once you’ve come up with a set of
CRC cards, you may want to create a more formal description of your design using
UML[14]. You
don’t need to use UML, but it can be helpful,
especially if you want to put up a diagram on the wall for everyone to ponder,
which is a good idea. An alternative to UML is a textual description of the
objects and their interfaces, or, depending on your programming language, the
code
itself[15].
UML also provides an additional
diagramming notation for describing the dynamic model of your system. This is
helpful in situations in which the state transitions of a system or subsystem
are dominant enough that they need their own diagrams (such as in a control
system). You may also need to describe the data structures, for systems or
subsystems in which data is a dominant factor (such as a
database).
You’ll know you’re done with
phase 2 when you have described the objects and their interfaces. Well, most of
them – there are usually a few that slip through the cracks and
don’t make themselves known until phase 3. But that’s OK. All you
are concerned with is that you eventually discover all of your objects.
It’s nice to discover them early in the process but OOP provides enough
structure so that it’s not so bad if you discover them later. In fact, the
design of an object tends to happen in five stages, throughout the process of
program
development.
|
|
|