These notes are based, in part, on material from chapters 3, 4, 5. and 6 of The CRC Card Book by David Bellin and Susan Suchman Simone (Addison Wesley, 1997). These notes discuss principles and techniques for design using CRC cards using a bank's Automated Teller Machine (ATM) as its example.
Groups work by collecting a diverse set of ideas, comparing the ideas, and synthesizing unanticipated solutions.
A "brainstorming" session is a good way to collect the ideas quickly and creatively.
Brainstorming principles [Bellin and Simone]:
Don't censure yourself or others -- all ideas are equal
A fast-paced discussion encourages individual creativity
Include everyone in the group. Don't let the loudmouths dominate.
Humor can help break down barriers, relieve tension, and build trust needed for a cohesive and effective group.
Before the brainstorming session, assign each team member an investigative task [Bellin and Simone]:
A good analyst is a good detective!
University Bank will be opening in Oxford, Mississippi, in January, 2000. We plan to use a full service automated teller machine (ATM) system.
The ATM system will interact with the customer through a display screen, numeric and special input keys, a bankcard reader, a deposit slot, and a receipt printer.
Customers may make deposits, withdrawals, and balance inquires using the ATM machine, but the update to accounts will be handled through an interface to the Accounts system.
Customers will be assigned a Personal Identification Number (PIN) and clearance level by the Security system. The PIN can be verified prior to any transaction.
In the future, we would also like to support routine operations such as a change of address or phone number using the ATM
Each session should have a precise objective--clear to all and narrow enough to accomplish in the session.
Avoid digression from the objective.
Go around the group from individual to individual.
Individuals may "pass" if they have nothing to contribute.
Stop when no one has anything to contribute.
Restate the objective, then identify those items that everyone agrees are "winners"
Then select those items that everyone agrees are "losers"
Then discuss the items remaining--the "maybes". Set a fixed time limit on discussion. Then, for each item, either decide its status or postpone explicitly until more information is available.
By brainstorming, we might identify the following candidate classes for University Bank's ATM system [Bellin and Simone]:
ATM | FinancialTransaction | BankCard |
BankCustomer | PIN | Account |
SavingsAccount | CheckingAccount | Transfer |
Withdrawal | Deposit | BalanceInquiry |
Receipt | ReceiptPrinter | Keypad |
Screen | CashDispenser | ScreenMessage |
Display | FundsAvailable | DepositEnvelopeFailure |
Balance | TimeOutKey | TransactionLog |
Key | AccountHolder | Printer |
ScreenSaver | Prompt | NumericKey |
Moving from brainstorming to analysis, divide the candidate classes into categories in the following order:
Items that directly relate to the main entities of the application
In the ATM example: Account, Deposit, Withdrawal, BalanceInquiry
Items that are clearly outside the system scope
In the ATM example: Printer, ScreenSave, and Prompt -- related to the user interface subsystem to be done later, but not to the core banking application
Items that we may not be able to categorize without first clarifying the system boundaries and definition
In the ATM example: What is an "ATM"?
To continue design, we must determine what is and what is not part of the system.
What is the scope of the ATM system in the example?
Possible questions:
The system boundary should be the product of definite decision making.
It is often useful to draw a diagram to record system boundaries.
ATM example: limit its scope to the banking information capture -- leaving the user interface and actual account update to other systems
A hot spot is a portion of the system that is likely to change from one system variant to another.
Encapsulate the variable aspects within components. Design the interfaces of and the relationships among components so that change is seldom necessary.
Enables convenient reuse of the overall system architecture and common code. Makes change easier to implement at hot spots.
ATM example: withdrawal handling is a hot spot. Initially supports the dispensing of cash; future may require update of cash cards. The classes that touch this hot spot include Account, Withdrawal, FundsAvailable, and BankCard.
A design pattern is a design structure that has been successfully used in a similar context--a reusable design.
Design patterns may be distillations of development organization experience -- or may be well-known general patterns selected from a book such as Design Patterns: Elements of Reusable Object-Oriented Software by the Gang of Four (Gamma, Helm, Johnson, and Vlissides) (Addison-Wesley, 1995).
The use of the design pattern may require the addition of new classes to the design.
ATM example: The interactions of the ATM with outside entities might be modeled using a "system interaction pattern". This would result in a new core class AuthorizeSystemInteraction.
A framework is a collection of classes--some abstract, some concrete--that captures the architecture and basic operation of an application system. Systems are created by extending the given classes to add the specialized behaviors.
Frameworks are "upside down libraries" -- system control resides in framework code that calls "down" to user-supplied code.
Example: Graphical user interface toolkits like the Java AWT.
To fit an application into a framework may require addition or modification of core classes.
Look for classes that are related entities but are outside the system. We may need to interface to these entities, but do not need to model them within the system.
ATM example: BankCustomer, Printer, and Keypad are relevant but outside the application being developed. For example, the system only needs to know about BankCustomer indirectly through the BankCard information such as the PIN.
This situation may arise when different groups within an organization use different names to refer to the same thing.
ATM example: BankCustomer and AccountHolder are probably synonyms. Adopt one of them or create a new name.
ATM example: Balance and FundsAvailable may be different concepts. The Balance of some Account and the FundsAvailable for withdrawal may not be the same because of a policy of disallowing withdrawals for some period after deposit of a check.
Be careful when the same word actually refers to different things! New core classes may be needed.
Some candidate classes may turn out to represent information held by other objects instead of being classes themselves.
A candidate class may be an attribute rather than a class if:
ATM example: Balance and FundsAvailable (mentioned above) have few meaningful operations and both are closely associated with Account.
ATM example: Consider a PIN. If a PIN is viewed as being immutable, not changing state, then it probably should be an attribute of Account. However, if a PIN can change state--say from among valid, invalid, and suspended--then it should be a class.
These are outside the scope of the system. Many are candidates for classes in the user interface system.
Grady Booch: "When considering the semantics of classes and objects, there is the tendency to explain how things work; the proper response is 'I don't care.'"
False semantic distinction among responsibilities may rob us of the ability to use inheritance and polymorphism to advantage.
Use brainstorming to identify a set of candidate responsibilities for the core classes. Strive for inclusion of relevant responsibilities rather than exclusion. Don't worry about duplication.
Later refine the lists of responsibilities. Name each carefully.
If most the responsibilities fall to one or two classes, then the system is probably biased toward a procedural perspective -- does not take advantage of polymorphism and encapsulation. Many of the classes are reduced to "records" -- simply knowing about the information they hold.
ATM example: A tendency might be to give most of the responsibility to the Account class, which becomes a strong, busy "manager" procedure giving commands to relatively weak, ill-defined "worker" classes. Account is probably too inflexible to be directly reused; the other classes are probably too insignificant to be reused.
Give each class a distinct role in the system. Strive to make each class a well-defined, complete, cohesive abstraction. Such a class has higher probability of being reused.
ATM example: Give class Withdrawal the responsibility "Withdraw Funds", making it potentially useful to any other class needing to do a withdrawal. Give class Account the responsibility "Accept Withdrawal", which will, of course, be carried out by collaborating with Withdrawal.
Factoring out complexity also involves identifying specialized behaviors that occurs repeatedly and, as appropriate, spinning off new classes.
ATM example: The capturing and responding to user requests might be factored out into a new class Form with a responsibility "ask user for information".
Build hierarchies of classes. Abstract the essence of related classes by identifying where they have common responsibilities -- where they do the same thing, but do it differently -- same "what", different "how".
That is, look for opportunities for the classes to use polymorphism to implement the same responsibility differently.
The new parent classes may be abstract classes. That is, no actual objects may ever exist of that type. The abstract class exists to link together similar concrete types of objects.
ATM example: Create an abstract class Transaction that is a superclass for Withdrawal, Deposit, etc. It can have an abstract responsibility "execute a financial transaction", that is implemented differently for each subclass.
Remember that CRC cards are inexpensive and erasable!!
Do not hesitate to experiment with different configurations of classes or assignments of responsibilities. Changing the CRC cards is easy in the early stages of a project; changing the code later in the project is not easy.
Server is collaborator of client, not vice versa
ATM example: In a withdrawal operation, Account is a client of the Withdrawal class
ATM example: Transaction as superclass of Withdrawal, Deposit, etc.
ATM example: Withdrawal is a (kind of) Transaction. Withdrawal is not "part of" Transaction.
Use brainstorming
ATM example: customer withdraws cash
Each member has one or more classes
Execute the scenario with team members announcing what affected classes are doing
Core behaviors of the system, touch central features of system
ATM example: customer withdraws cash
Routine tasks to be carried out under certain conditions
Tasks to avoid exceptional situations
Careful about crossing out of system scope
Exceptions -- unusual, complex, difficult to handle cases
Help uncover poor collaborations and clarify system scope (a stress test)
ATM example: withdrawal with insufficient funds
Break up if larger
Especially important when team just formed or new member added
"must do" first, then "can do if"
ATM example: Start with Customer or BankCard
Hold up active card or toss "in play" on the table
Especially after considerable role play, avoid creating more problems
UP to CSCI 581 Lecture Notes root document?