< Day Day Up > |
The rest of this chapter is dedicated to a case study pertaining to the design process covered in the previous sections. Walking through a case study seems to be a standard exercise in many object-oriented books that deal with OO design. My first recollection of such an exercise was a graduate course that I took in which we followed an example in the book Designing Object-Oriented Software by Wrifs-Brock, Wilkerson, and Weiner. The modeling technique was called CRC modeling, which will be described later in this section. The case study was that of an automated teller machine (ATM) system. The iterative process of identifying the classes and responsibilities using CRC modeling was an eye-opening experience. The books The Object Primer by Scott Ambler and Object-Oriented Design in Java by Gilbert and McCarty both go through similar exercises using CRC modeling and use cases. Let's start an example that we will expand on throughout this chapter. Because we want to have some fun, instead of creating a payroll system or an ATM system, let's create a program that simulates a game of blackjack. We will assume that the statement of work has already been completed. In fact, let's say that a customer has come to you with a proposal that includes a very well-written statement of work and a rule book about how to play blackjack. According to the statement of work, the basic goal is to design a software system that will simulate the game of blackjack (see Figure 6.3). Remember, we will not describe how to implement this game ”we are only going to design the system. Ultimately, this will culminate in the discovery of the classes, along with their responsibilities and collaborations. After some intense analysis, we have determined the requirements of the system. In this case, we will use a requirements summary statement; however, we could have presented the requirements as bullets. Because this is a small system, a requirements summary statement might make more sense. However, in most large systems, a database of the requirements (in bulleted list format) would be more appropriate. Here is the requirements summary statement:
Figure 6.3. A winning blackjack hand.
As already mentioned, you could also have presented the requirements in bullet form, as we did for the DataBaseReader class in Chapter 2, "How to Think in Terms of Objects." We want to take the perspective of the user . Because we are not interested in the implementation, we'll concentrate on the interface. Think back to the black-box example from Chapter 1, "What an Object Really Is." We only care about what the system does, not how it does it. The next step is to study the requirements summary statement and start identifying the classes. Before we actually start this process, let's define how we are going to model and track the classes that we ultimately identify. Using CRC CardsDiscovering classes is not a trivial process. In the blackjack example we are working on, there will be relatively few classes, because this is intended as an example. However, in most business systems, there could be dozens of classes ”perhaps 100 or more. There must be a way to keep track of the classes as well as their interactions. One of the most popular methods for identifying and categorizing classes is to use class-responsibility-collaboration cards ( CRC ) . Each CRC card represents a single class's data attributes, responsibilities, and collaborations. One of the more endearing qualities of CRC cards is that they are non-electronic (although I'm sure that there are computer applications around that simulate CRC cards). CRC cards are, quite literally, a collection of standard index cards. You need to create three sections on each card:
The use of CRC cards conjures up scenes of dimly lit rooms, partially filled boxes of pizza, pop cans, and multitudes of index cards strewn around the room. Although this might be partially true, using CRC cards is a good technique because many of the people involved with the design will not be developers. They might not even have much computer experience. Thus, using the index cards to discover classes is a technique that everyone can understand. Figure 6.4 shows the format of a CRC card. Figure 6.4. The format of a CRC card.
Identifying the Blackjack ClassesRemember that, in general, classes correspond to nouns, which are objects ”people, places, and things. If you go through the requirements summary statement and highlight all the nouns, you have a good list from which you can start gleaning your objects. Nouns Although it is true that nouns generally indicate classes, nouns are not the only places where classes are found. As stated earlier, you shouldn't get too hung up in getting things right the first time. Not all the classes that you identify from the list of nouns, or elsewhere, will make it through to the final cut. On the other hand, some classes might make the final cut that were not in your original list. Start feeling comfortable with the iterative process throughout the design. And as always, make sure that you realize that there are always many ways to skin a cat. We have already stated that if you put 10 people in different rooms, they will come up with 10 different designs, and they might all be equally good. In most cases, although the designs might be different, ideally there will be significant overlap. Of course, when working with a team, the final design will have to be a consensus, iterating and evolving to a common solution. Let's identify some nouns from our blackjack example:
Now let's make a list of the possible objects(classes):
Can you find any other possible classes that were missed? There might well be some classes that you feel should be in the list but are not. There might also be classes that you feel should not have made the list. In any event, we now have a starting point, and we can begin the process of fine-tuning the list of classes. This is an iterative process, and although we have 19 potential classes, our final class list might be a lot shorter. Again, remember that this is just the initial pass. You will want to iterate through this a number of times and make changes. You might even find that you left an important object out, or that you need to split one object into two objects. Now let's explore each of the possible classes:
We are left with six classes, as shown in Figure 6.5. Figure 6.5. The initial blackjack classes.
Design Decisions The dealer could be a specific type of player, and perhaps inherit from a player class. However, this would be a design decision. Identifying the Classes' ResponsibilitiesResponsibilities relate to actions. You can generally identify responsibilities by selecting the verbs from the summary of the requirements. From this list you can glean your responsibilities. However, keep in mind the following: Verbs Although it is true that verbs generally correlate with responsibilities, verbs are not the only places where responsibilities are found.
Let's take an initial stab at identifying the verbs, which will lead us down the path toward uncovering the responsibilities of our classes:
Now let's make a list of the possible responsibilities for our classes:
Remember that this is just the initial pass. You will want to iterate through this a number of times and make changes. You might even find that you've left an important responsibility out, or that you need to split one responsibility into two responsibilities. Now let's explore the possible responsibilities. We are left with the following classes and responsibilities: Card
Class Design What to do with the jokers presents an interesting OO design issue. Should there be two separate classes ”a superclass representing a regular deck of cards (sans jokers) and a subclass representing a deck of cards with the addition of the jokers? From an OO purist's perspective, having two classes might be the right approach. However, having a single class with two separate constructors might also be a valid approach. What happens if you have decks of cards that use other configurations (such as no aces or no jacks )? Do we create a separate class for each, or do we handle them in the main class? This is another design issue that has no right or wrong answer. Deck
Hand
Dealer
Player
Bet
As we iterate through the design process, we decide that we really do not want to have a separate bet class. If we need to, we can add it later. The decision needs to be based on two issues:
After careful consideration, we decide that the class is not needed, and most probably will not be needed later. We make an assumption that the payment method for all future bets will be money. This is not necessarily a proper design decision. I can think of many reasons that we might want to have a bet object. There might be some behavior that should be encapsulated in a bet object. However, for now, we will scrap the bet object and make the dealer and players handle their own bets. UML Use Cases: Identifying the CollaborationsTo identify the collaborations, we need to study the responsibilities and determine what other classes the object interacts with. In short, what other classes does this object need to fulfill all its required responsibilities and complete its job? As you examine the collaborations, you might find that you have missed some necessary classes, or that some classes you initially identified are not needed:
You might want to create collaboration diagrams to document this step. Obviously, there can be an infinite number of scenarios. The purpose of this part of the process is not to document all possible scenarios, which is an impossible task. The real purpose of creating use-case scenarios is to help you refine the choice of your classes and their responsibilities. By examining the collaborations, you might identify an important class that you missed. If this is the case, you can simply add another CRC card. You might also discover that one of the classes you originally chose is not as important as you once thought, so you can strike it and remove the CRC card from consideration. CRC cards help you discover classes, whereas use-case scenarios help you discover collaborations. For example, let's consider a single possible scenario. In this case, we have a dealer and a single player.
Let's determine some of the collaborations. Assume that we have a main application that contains all the objects (that is, we do not have a Game class). As part of our design, we have the dealer start the game. Figures 6.6 through 6.15 present some collaboration diagrams pertaining to this initial design. Figure 6.6. Start the game.
Figure 6.15. Do either the dealer or the player stand?
Figure 6.7. Shuffle and initially deal.
Figure 6.8. Get the hand value.
Figure 6.9. Get a card.
Figure 6.10. Deal a card and check to see whether the player busts.
Figure 6.11. Return the value of the hand.
Figure 6.12. Does the dealer want more cards?
Intangibles Be aware that there are more issues than the value of a player's hand involved in deciding whether to take another card. A player at a real blackjack table might go with a gut feel or how the dealer's hand looks. Although we might not be able to take gut feelings into consideration, we can attend to the issue of what the dealer's hand currently shows. Figure 6.13. If requested , give the dealer a card.
Figure 6.14. Does the dealer bust?
First Pass at CRC CardsNow that we have identified the initial classes and the initial collaborations, we can complete the CRC cards for each class. It is important to note that these cards represent the initial pass only. In fact, although it is likely that many of the classes will survive the subsequent passes , the final list of classes and their corresponding collaborations might look nothing like what was gleaned from the initial pass. This exercise is meant to explain the process and create an initial pass, not to come up with a final design. Completing the design is a good exercise for you to undertake at the end of this chapter. Figures 6.16 through 6.20 present some CRC cards pertaining to this initial design. Figure 6.16. A CRC card for the Card class.
Figure 6.20. A CRC card for the Hand class.
UML Class Diagrams: The Object ModelAfter you have completed the initial design using CRC cards, transfer the information contained on the CRC cards to class diagrams (see Figure 6.21). Note that this class diagram represents one possible design ”it does not represent the initial pass of classes created during the previous exercise. The class diagrams go beyond the information on the CRC cards and might include such information as method parameters and return types. (Note that the UML diagrams in this book do not include method parameters.) Check out the options for the modeling tool that you have to see how information is presented. You can use the detailed form of the class diagram to document the implementation. Figure 6.21. A UML diagram for the blackjack program.
Figure 6.17. A CRC card for the Deck class.
Figure 6.18. A CRC card for the Dealer class.
Figure 6.19. A CRC card for the Player class.
Remember that the purpose of this exercise is to identify the classes and their interfaces. All the methods listed are public. Now a light bulb should be going off in your head. Even though the search for the interfaces does not lead directly to private attributes and even private methods, the process is helpful in determining these as well. As you iterate through the CRC process, note what attributes and private methods each class will require. Prototyping the User InterfaceAs our final step in the OO design process, we must create a prototype of our user interface. This prototype will provide invaluable information to help navigate through the iterations of the design process. As Gilbert and McCarty in Object-Oriented Design in Java aptly point out, "to a system user, the user interface is the system." There are several ways to create a user interface prototype. You can sketch the user interface simply drawing it on paper or a whiteboard. You can use a special prototyping tool, or even a language environment like Visual Basic, which is often used for rapid prototyping. Or you can use the IDE from your favorite development tool to create the prototype. However you develop the user interface prototype, make sure that the users have the final say on the look and feel. |
< Day Day Up > |