Where Should Details Go?
People unfamiliar with CRC cards sometimes worry about where should they put design details. My advice is to keep cards simple. There isn’t room for details. A responsibility statement should summarize what a design element knows or does. For example, a Repository, a design element found in domain-driven design, has these responsibilities: “maintain a collection of persistent domain objects”, “retrieve objects that match a specification”, and “reconstitute and store domain objects (which are usually located in a relational database)”. If you are familiar with repositories, you know that several methods are used to maintain objects in a repository: adding, saving, and deleting. And there are usually several different ways provided to select and retrieve objects. A responsibility statement shouldn’t just restate a method name or an attribute. If you were to write at that level of detail, you would quickly run out of room. The value in a CRC card is in its summary descriptions. So put the details where they belong—in your code and in your tests.
You can view the design of a class, component, or service at least these three different levels:
- At the conceptual level: as a set of responsibilities (hand written on a CRC card, typed into design documentation, or scrawled on a whiteboard);
- At the specification level: a set of methods and attributes (shown on a UML class diagrams); or
- At the implementation level: code, tests, and data declarations.
Most of the time agile developers are happy working at the implementation level. Yet from time to time I find it useful to pop up to the conceptual level to summarize a class’ design intent. CRC cards help me keep to the point. I even reverse engineer from code to cards. I often keep a stack of index cards handy when I wade through unfamiliar legacy code.