Previous Section Main Menu Next Section 
CHAPTER 5
Object-Oriented Design
Section III : CRC Cards Section I: The Object-Oriented Paradigm  Section II: Class Analysis and Design  Section IV: Classes in C++ 
Section V: Defining Classes  Section VI: Using Class Declarations in a Program  Section VII: Constructors 

A. The Idea of CRC Cards
The circled nouns and underlined verbs give us a starting point. What we need now is a systematic way of determining the objects/classes required of a program and what each object/class consists of. In this course we will use a team oriented approach called CRC - more on the meaning of these letters later.

In the CRC approach a design team gathers together with a stack of index cards. Using the underlined nouns in the problem narrative, the team comes up with the objects/classes required in the program. Someone writes down a name for each class in the upper left corner of a card - one card for each class. A line is then drawn down the middle of the card and on the left we begin to list the responsibilities of objects belonging to this class.

There are two kinds of responsibilities. First, an object is responsible for knowing or being able to determine certain things about itself. Some of the underlined nouns in the narrative represent such responsibilities. In the example above instances of the class 'Person' would be responsible for knowing their name and address. In many cases these knowledge responsibilities will become properties of the class but we will see exceptions to this.

The second type of responsibility involves the behaviors instances of the class will expected to perform. Such behavioral responsibilities can be as simple as reporting the value of some property or can involve complex calculations and manipulations of data. The circled verbs in the narrative act as clues in the discovery of these responsibilities.

On the right side of the CRC card we list other classes that this class must use in order to carry out its responsibilities. Such required classes are called collaborators. Thus we see where the name CRC comes from - Classes, Responsibilities, Collaborators.

Notice the words 'responsibilities and 'collaborators'. These have been chosen on purpose to emphasize that each object (instance of some class) is to be considered as an 'actor'. Objects manage their internal state and perform actions. They receive and respond to messages or requests sent to them by other objects or 'main' and its related non-member functions. This may seem a bit strange at first - as if we are anthropomorphizing our programs. For the fun and ease of it, you might want to imagine a program as some kind magical land where inanimate objects come to life.

Consider as an example, a race car game played on a computer. An object-oriented program for such a game would probably consist of a race track class with one or more object instances representing possible race tracks and a race car class with one or more instances representing the various cars involved in a race. We humans do actually use phrases like the 'response' of the car, and we can think of an instance of the class 'car' in this program as 'responding' to messages to accelerate or brake or turn. In other words, each instance of the class 'car' must be responsible for knowing its position, speed, and direction and for accelerating, braking, and turning itself. The responsibilities of an instance of race track might include displaying the race on the screen, keeping track of (knowing) such things as who is in the lead and the elapsed time of the race, and of informing a car when it has crashed into a wall of the track.

This last may also seem strange but again, remember the magic land we are in. Perhaps one should actually have a class 'wall', where some set of instances of wall form part of an instance of track, and instances of wall inform instances of car when a car has crashed into a wall. Walls would be collaborators of track because a track would not know if there was a crash (something it needs to find out about if it is to accurately display the race) unless it gets the information from the walls of a track. (If this seems a bit complex and far-fetched, don't worry much about it yet. The details will come later.)

Back to our CRC cards, note that this approach does not directly determine the properties of a class. However, some of the knowledge responsibilities of a class will be implemented as properties and some collaborators (such as walls in relation to tracks) will also become data members (for example, tracks have walls as properties). Other properties may become clear as we consider which underlined words in the problem narrative are useful to the behaviors/responsibilities of the class.

B. Introducing Olympia and the CRC Process
What with walls sending messages and all, it's probably time for a concrete example before we really get crazy. The race car game we just talked about is too complex for the moment so let's look at a more boring but simpler problem:

This problem description has been kept vague on purpose. Users rarely can describe their own problems in a way useful to the programmer. It is our job to tease out the information we need and hand it back to the user to make sure our analysis is correct. As a first step then, here is a problem narrative for this problem This description is the same but more detailed than the original. Hopefully, enough detail has been provided to help us discover the classes involved as well as their properties, behaviors, and relationships. This is a simple problem so it is likely that we will succeed. Be aware that a more complex problem will require both a more detailed problem narrative and a more complex analysis of that narrative.

C. What the Underlined Nouns Tell Us
You are urged to do the interface analysis for this problem on your own. Here we will proceed to the process of discovering the objects and classes. To accomplish that, we need to underline the nouns and circle the verbs. Since it is not easy to show 'circled' verbs, we will use italics:

In this example all nouns and verbs have been underlined or italicized the first time they appear. Since the underlined and italicized words are to be used as clues in discovering the necessary classes etc., it is not necessary to 'mark' clues that have already been discovered. Likewise, words that really refer to the same thing, as in "office complex" and "office" are not both 'marked'.

Many of the words here really are irrelevant to the process and can be weeded out immediately. Our goal is to create a 'model' of the contract world of Olympia. Since concepts such as 'program' and 'user' (of the program) are not part of that world, they are not part of the model and can be ignored.

Perhaps not as obvious, 'Olympia' and 'business' can also be ignored. The task here is to discover those objects that are part of Olympia's business world. Olympia herself owns that world. She is not contained in that world. Likewise, the business world is what is being modeled - it is not part of itself. Any words in a problem narrative that name the world being modeled or the 'owner' of that world can be ignored. It is not that these words could be left out of the problem narrative. They are necessary to describe the problem but they are not useful as clues in finding the classes and class responsibilities.

The nouns that are left include:

contract square footage          number of desks 
number of days          information  per week charge 
formula  office complex  week
Now we need to determine which of these represent classes, which represent objects, which represent properties of objects, which represent other elements of the program, and which can be ignored. Let's start with contract. It certainly is a thing, an object and it doesn't sound like a property or a description of some other object. Contracts seem to 'exist' by themselves in the little world we are modeling. As a matter of fact, there are five of them which means that there are five instances of contract. This is a sign that we might have a class. Further, each individual contract is unique but it is likely that they all have characteristics in common - another sign that we have a likely candidate for a class. Let's consider it a class for the moment.

How about 'square footage'. By the way it is written, it is clear that it is meant to describe a characteristic of a contract - contracts have a square footage associated with them. Therefore 'square footage' is a knowledge responsibility and probably a property of the contract class. This gives us more confidence that 'contract' is a likely class - we have found a responsibility for it. Classes without responsibilities are of little use in a program.

Next comes 'number of desks'. Here, perhaps, we cheated in our initial underlining. 'Number of desks' is most likely a property of contract just as 'square footage' was. If we had just underlined the word desk, we would have had to have been a bit more careful. Desks certainly are objects and therefore the concept of desk certainly could represent a class in our program. However, in this program do we care about desks in any other way other than the number of them. For example, do we care about any of the possible characteristics of desks? None of the rest of the underlined nouns refer to desks so the answer seems to be no. When we get to the italicized verbs we will also see that none of them describe behaviors of desks so nothing about desks seems to concern us or Olympia except their number in a contract. Therefore in this program desks are not objects.

Note that in other programs desks could play a significant role and could need to be modeled as objects. Consider a program which acts as a tool for doing office designs. In such a program users would be creating office spaces and placing desks as well as chairs, tables, portable walls, etc. in those spaces as part of the design process. Such a program would need to keep track of the location of each desk, its style, size etc. Desks could be moved around, deleted, and otherwise modified. Now desks have properties (characteristics) and behaviors, making them very likely candidates for class status.

Back to our problem: 'number of days' fits in the same category as 'square footage' and 'number of desks'. Knowing or being able to determine the 'Per week charge' is also a knowledge responsibility of the contract although we will see later that there is some discussion about how to represent it. That leaves four nouns to analyze. 'Information' is really just a collective word for the various properties we have been discussing. It was useful in the problem narrative but adds no detail here so can be ignored. ' Formula' is tricky. Yes, one can say that contracts have a formula but we will see that the formula here will be represented as a piece of code that calculates the 'per week charge'. In a programming context the word formula hints at an action ( a piece of code) more often than at a property.

The word 'week' also requires a bit of analysis. The problem narrative needs to include information about the time frame of a contract, but does the idea of time have a place in the program? A week is certainly a thing, but there is nothing the program does with 'weeks' so it is unlikely to become a class. Could it be a property? Since 'contract' is our only class, 'week' would have to be a property of 'class'. By itself, however, week is not a descriptive term like "hair color" or "number of days". It, therefore, does not seem to make a good property.

The problem narrative includes the phrase "per week" and we could imagine a property that referred to the length of time of a contract, as in "by the week" or "by the day" or "by the month". In this sense, the charge for a contract or the billing period might depend on this length of time. Note, however, that, under this interpretation, 'week' is not the name for a property but a possible value of a "time period" property. All this is unimportant in the context of this specific problem because all contracts are described in terms of a week and a property with only one possible value isn't worth noting.

Finally, we have 'office complex'. There are a number of office complexes involved in this program - one for each contract probably. Yet, as with desks, there do not seem to be any properties (or behaviors as we will see in a moment) associated with this potential class. If you think about it, we really aren't interested in office complexes in this program except that contracts are associated with them. Thus, this noun seems to be another one that was useful in the problem narrative but not useful in the program itself.

We wind up with one class (Contract) and a small set of knowledge responsibilities for that class. At this point you may be thinking, "You (the authors) wound up with that, but not me. I could never repeat this process on my own." You may well be correct. Indeed, it would be possible and quite easy to come up with a different and probably invalid set of candidate classes. The class discovery process is an art form and there is no clear set of criteria for determining when one has come up with the best set of classes. Object-oriented analysis and design is not easy. There is no simple algorithm for it. (If so, we could probably turn the process over to a computer and forget about it.) The "underline the noun and circle the verb" approach used here is only to get you started. You will need to use all your common sense and analytic skills to arrive at a complete analysis.

That is where the team approach comes in. A team is more likely to discover all the necessary classes, their responsibilities, and their collaborators. Object-oriented analysis and design is so hard that, in practice, even experts often work in teams. In fact the CRC approach is specifically meant to be executed in teams. Well managed teams allow the best ideas of each individual to come through while filtering out the mistakes. Students often resist working in teams for any number of reasons (grades, schedules....) but if you want to be trained for the real world, you need to get used to team work.

Part of the team approach used with CRC cards includes role playing. Team members decide on a few basic classes and then role play various scenarios a program would be expected to handle. The goal is to discover if these indeed are the correct classes, what other classes might be required, what are the responsibilities of the required classes, and how the classes collaborate.

What you also need to do at this point is carefully study the designs and resulting programs of others who are more experienced. Then, practice on your own or in groups. That is what much of learning to program is about.

D. What the Verbs Tell Us
If we accept the conclusion that we only need one class in our program, we know that we need only one CRC card. (The reader is again reminded that we are starting with a simple example, one that probably could be done without the use of a tool such as CRC cards, but that such a simple example will hopefully make the process clear.) What then are the responsibilities of this class?

We have already discovered at least some of the knowledge responsibilities: Know the square footage Know the number of desks Know the number of days Know the per week charge.

Now we proceed to determine the behavioral responsibilities. To accomplish this we work with the italicized verbs. As with the nouns, we first need to consider if there are any verbs that can be easily ignored. Remember that we are looking for behaviors that instances of the class should be expected to perform. Therefore, what we are looking for here are behaviors that contracts will be expected to perform. (Again, it might help if you think of a contract as an actor.)

Problem narratives often include verbs that refer to the person or organization for whom the program is being written. In this example, we have "Olympia owns" , "Olympia wishes", and "she has". These are not actions of a contract and can be ignored. The remaining verbs include:

keep track of    involves  to be cleaned 
get  change is calculated

It turns out that many verbs provide very strong hints about the knowledge and behavioral responsibilities of classes. For example, whenever you see verbs such as "keep track of", "saves", "stores", or "holds", whose subject noun is a candidate class (such as Contract in this example), the words after those verbs are likely to be knowledge responsibilities of the class. In the program narrative the first use of 'keeps track of' refers to the program itself and can be ignored on the same basis that 'owns', wishes' and 'has' were ignored. However, the second usage has 'contract' as its subject and refers to 'square footage', number of desks' and 'number of days'. We can interpret this to mean that instances of class 'contract' have the responsibility of keeping track of their 'square footage', number of desks' and 'number of days'. Here is corroborative evidence that we are on the right track with our analysis.

Such verbs hint at the characteristics (what we are calling the properties) of a class, but they do not indicate any behavior required of the class. On the other hand, verbs such as change, update, set, or modify indicate both possible properties and the action of changing, updating, setting or modifying the values of those properties. (They indicate properties because something can't be changed or modified or set unless it exists and it is not the object that changes - objects of one type (class) do not become objects of another type). Therefore, in our example, we can conclude that instances of class contract must be able capable of (responsible for) changing the 'information' they hold concerning the 'square footage', number of desks' and 'number of days' of the instance.

At this point we have the following responsibilities for the 'contract' class:

Another verb that often provides a useful hint is 'get'. When used in a form such as "the user should be able to get….", this word strongly implies that the class must be capable of reporting the values of the properties it is responsible for knowing. This does not mean that the values are output but rather that they can be retrieved from an instance and used by some other part of the program. In concrete terms what this means is that for each property there is a function (after all, functions implement behaviors) that returns the value of the property. It is usually considered wise to not have the function output the value itself because the object does not know how the value is to be used. Maybe it is not going to be output at all. Or, maybe it is to be used in a calculation or in a test condition.

In our example then we need at least three such 'get' functions, one for 'square footage', number of desks' and 'number of days'. In this material we will use the word 'provide' instead of 'get' to avoid some confusions students sometimes have. Thus, the contract class has the following additional behavioral responsibilities:

The idea is that an instance of the class 'Contract' will, upon request, provide the value of the desired property. We probably also need a 'get' or 'provide' function for the "per week charge" but this is a special kind of knowledge responsibility since it is a calculated value. In other words, the Contract class has the responsibility of knowing the "per week charge" more in the sense of knowing how to calculate it than in immediately knowing its value.

When we look at the verb 'calculate', the question arises: should there be a memory location set aside to hold the 'per week charge' or should it be calculated every time it is needed? If it is calculated every time it is requested then the program must do the math over and over even if none of the values upon which it depends have changed. Why do that work over and over? But, suppose we do set aside a memory location to hold the 'per week charge' and do the calculation once. Now, suppose that later the number of desks in the office changes. Since this is one of the properties upon which the 'per week charge' depends, any change in it forces a change in the per week charge. How do we make sure that the 'per week charge' is again calculated? It turns out that although one can write code to accomplish this, it is often easier to simply have an instance redo the calculation whenever the value is asked for. For us then, the conclusion will be that the contract class will have a 'Provide Per Week Charge' function, but there will not be a 'weekly charge' property. Each time it is called, the 'Provide Per Week Charge' function will perform the calculation and immediately return the result.

The reader should pay careful attention to what is happening here. The "per week charge" knowledge responsibility is being handled via a calculation BUT users of the class (users here means programmers who include the class in their code) will have no idea how the "per week charge" is generated. Outside the Contract class there is no visible difference between 'ProvideSquareFootage' and 'ProvidePerWeekCharge'. Indeed, if later we decided that the internal structure of the 'Contract' class should change to explicitly include a "per week charge" property, any program using this class would not need to change. This is one of the more powerful advantages of encapsulation.

Note also that the discussion here has slipped a bit into issues of 'how' not just 'what' the Contract class will do. Analysts and Designers should do all they can to keep these separate but it is not always possible to do so. That is part of the complexity of the real world and real world programming.

There are two verbs left:

involves  to be cleaned 

Neither of them really involve behaviors of contracts. The verb 'to be cleaned' certainly is not a behavior of a contract, while 'involves' implies a relationship - perhaps between instances of Contract and instances of some other class.

Is it possible that we have skipped a class or classes - classes that would be responsible for 'cleaning' or that would be 'involved' with the contract class? This possibility should not be overlooked - one part of the design process can often help in some other aspect of design. However, in this case there is nothing to worry about. First, the problem narrative says that "contracts involve office complexes" but we have already carefully analyzed the noun office complex and decided that it did not represent a class that would be useful in this program. Second, the other verb really refers to the user of the program - the user or an associate who would be doing the 'cleaning'. In our earlier analysis we decided that 'user' was not a useful class concept in our program.

To summarize: Our analysis shows that we need one class, call it Contract, which has four knowledge responsibilities and seven behavioral responsibilities:

Three of the four knowledge resupplies will become properties - square footage, number of desks, and number of days.

Since there is only one class, we do not need to worry about collaborators. Here then is the CRC card for the class 'Contract'

E. Some Additional Ideas on Discovering the Responsibilities of a Class
Our analysis has discovered two basic types of member functions that implement the behavioral responsibilities of a class

These functions are often referred to as interface functions because they allow a program's code to access (interface with) the encapsulated parts of an instance. That part of a program's code that does not belong to a class does not have direct access to the encapsulated properties of the class. However, through the interface functions, the code can retrieve and change the property values of an instance.

Such interface functions are often not 'discovered' until one actually begins coding. That is perfectly OK - a good design is meant to give the programmer a plan to follow and plans can be modified along the way. However, it is best to determine as much as you can at design time so you should ask the following questions of each class:

  1. Are there properties whose values will be needed outside the class? If so, for each such data member a 'get' or 'provide' function is needed since the data member values are encapsulated inside the instances.
  2. Are there properties whose values will be changed, set or modified by functions that are not members of the same class? If so, for each such property, a 'change' function is needed - since, again, the properties are encapsulated inside the instances. (See above and below for a discussion of encapsulation.)
 
Top of Section Main Menu Next Section