## Chapter 13: Object Oriented Design

## Chapter Goals

- To learn about the software life cycle
- To learn how to discover classes and member functions
- To learn the concepts of cohesion and couple
- To learn the CRC card method
- To gain an understanding of UML class diagrams
- To learn how to use object-oriented design to build complex programs
- To study examples of the object-oriented design process

## The Software Life Cycle

- The software life cycle is the activities that take place between the time the software program is first conceived and the time it is finally retired.
- Many software engineers break the development process down into the following phases:
  - Analysis
  - Design
  - Implementation
  - Testing
  - Deployment

## The Software Life Cycle

- Analysis
  - You decide what the project is supposed to accomplish; you do not think about how the program will accomplish its tasks.
  - The output of the analysis phase is a requirements document that
    - describes in complete detail what the program will be able to do.
    - provides a user manual that tells how the user will operate the program to derive the promised benefits.
    - sets performance criteria - how many inputs the program must be able to handle in what time, or what its maximum memory and disk storage requirements are.
- Design -
  - You develop a plan for how you will implement the system.
  - The output of this phase is a description of the classes and member functions, with diagrams that show relationships among the classes.

## The Software Life Cycle

- Implementation -
  - You write and compile the program code to implement the classes and member functions.
  - The output of this phase is the completed program.
- Testing -
  - You run tests to verify that the program works correctly.
  - The output of this phase it a report describing the tests that you carried out and their results.
- Deployment -
  - The users of the program install it and use it for its intended purpose.

## The Software Life Cycle

- Formal processes have been established to help in the management of software projects.
- A formal process identifies the activities and deliverables of different phases and gives guidelines on how to carry out the phases and when to move from one phase to the next.
- An early (1970) formal development process called the waterfall method postulated that one phase would run until complete, its output would spill over to the next phase, and the next phase would begin.

## The Software Life Cycle

- The waterfall model did not work.
  - It was difficult to come up with a perfect requirement specification.
  - It was common to discover in the design phase that the requirements were not consistent and needed changing.
  - When a design was implemented, the results program might not be fast as desired.
  - When the program was tested, many bugs were found that would best be fixed by reimplementing, or maybe even redesigning.
  - Customers might be unhappy with the finished product.
- A mechanism is needed to deal with the unresolved problems from the preceding phase.

## The Software Life Cycle

- The spiral model, proposed by Barry Boehm in 1988, breaks the development process into multiple phases.
- Early phases focus on the construction of prototypes - small systems that show some aspects of the final system.
- Because prototypes model only part of a system they can be implemented quickly.
- Lessons learned from the development of one prototype can be applied to the next iteration of the spiral.

## The Software Life Cycle

- By building repeated trials and feedback, a development process that follows the spiral model has a greater chance of delivering a satisfactory system.
- However, if engineers believe that they don't have to do a good job because they can always do another iteration, ther will be many iterations.

## The Software Life Cycle

- The "Rational Unified Process" is a common, yet complex, process involving multiple iterations.
- In a first programming course you will not develop systems that are so complex, but you should understand that that successful software development involves more than just coding.

## CRC Cards

- In the design phase of software development, your task is to discover structures that make it possible to implement a set of tasks on a computer.
  - Discover classes.
  - Determine the responsibilities of each class.
  - Describe the relationships between the classes.
- A simple rule for finding classes is to look for nouns in the task description.
- Example: suppose you job is to print an invoice. As you brainstorm, keep a list of candidate classes on a whiteboard or sheet of paper.
  - Invoice
  - Item
  - Customer

## CRC Cards

- Once a set of classes had been identified, you need to define the behavior (member functions) for each classes.
- A simple rule for finding member functions is to look for verbs in the task description, and then match the verbs to the appropriate objects.
- To create an invoice we need to compute the amount due.
  - Do customers compute the amount due?
  - Do invoices total up the amount due?
  - Do items total themselves up?

## CRC Cards

- In the CRC card method, you create an index card for each class.
- CRC stands for "classes", "responsibilities", "collaborators."
- As you think about the verbs in the task description, pick the card of the class that you think should be responsible, and write that responsibility on the left-hand side of the card.
- For each responsibility, you record on the right-hand side of the card which other classes (the collaborators) are needed to fulfill it.

## CRC Cards

- As you list responsibilities and collaborators, think about the member functions the collaborators might need to help with the task.
- Example: To computer the total, the invoice needs to ask each item about its total price.
  - Therefore the `Item` class is a collaborator.
  - Does the `Item` class have a "get total price" member function? If not, add one to its card.
- Many people find it helpful to group cards on a table so that the collaborators are close to each other, and to simulate tasks by moving tokens (such as a coin) from one card to the next to indicate which object is currently active.
- Responsibilities that you list on the CRC card are on a high level, and may need two or more member functions for carrying out.
- The CRC method is an informal process:
  - Be creative and discover the classes and their responsibilities.
  - Cross out, move, or split responsibilities.
  - Rip cards up if they become too messy.

## Cohesion

- What makes a good class?
  - A class should represent a single concept.
    - Point
    - Circle
    - Time
    - Product
    - Employee
  - Class names should be nouns (function names should be verbs).
- What makes a bad class?

- If you can't tell from the class name what an object of the class is supposed to do, then you are probably not on the right track.
- Example: What does a instance of a `PaycheckProgram` class do?
- Do not turn an action into a class.
- Example: `ComputePaycheck` is a function, not a class.

- The member functions and constants that the public interface of a class expose should be cohesive - all interface features should be closely related to the single concept that the class represents.
- If a class interface refers to multiple concepts, then that is a good sign that it may be time to use separate classes instead.

## Coupling

- A class depends on another class if one of its member functions uses an object of the other class in some way.
- The "collaborators" column of the CRC cards tells you which classes depend on another.
- In a UML class diagram, you denote dependency by a dashed line with an open arrow tip that points to the dependent class.

- A `Purse` class depends on a `Coin` class, because a purse contains coins.
- The `Coin` class does not depend on the `Purse` class because the `Coin` class makes no use of the `Purse` class.

## Coupling

- When many classes of a program depend on each other, we say that the coupling between classes is high.

## Coupling

- When there are few dependencies, we say coupling is low.

## Coupling

- Coupling is important because if one class changes, all the classes that depend on it may be affected.
- Furthermore, if a class is used in another program, so must all the classes on which it depends.
- In general, you want to remove unnecessary coupling.

## Relationships between Classes

- When designing a program, it is useful to document the relationships between classes.
  - For classes with common behavior, you can save effort by placing the common behavior in a base class.
  - For classes that are not related to each other, you can assign different programers to implement each of them.
- The inheritance relationship is a very important relationship between classes.
- The relationship is often described as the is-a relationship.
  - Every truck is a vehicle.
  - Every savings account is a bank account.

## Relationships between Classes

- Inheritance, although useful, can be over-used.
- Should a class `Tire` be derived from a `Circle` class?
- Conceptually, the arrangement does not make sense.
- A tire has a circle as it's boundary.

  >     class Tire
  >     {
  >        ...
  >     private:
  >        string rating;
  >        Circle boundary;
  >     };

- The term for this relationship is association.

## Relationships between Classes

- Every car is a vehicle. Every car has a tire (several tires, actually).

  >     class Car : public Vehicle
  >     {
  >        ...
  >     private:
  >        vector<Tire> tires;
  >     };

- In UML notation, association is denoted by a solid line with an arrow at the tip.

## Relationships between Classes

- A class is associated with another if you can navigate from objects of one class to objects of the other class.
- Example: You can navigate from a `Car` object to the `Tire` object, so these classes are associated.
- The association relationship is related to the dependency relationship. Association is a stronger form of dependency.
- If a class is associated with another, it also depends on the other class.
- If a class depends on another, it comes in contact with objects of the other class in some way, not necessarily through navigation.

## Relationships between Classes

- The arrows in the UML notations can get confusing; the table shows the relationships symbols used in the book.

## Implementing Associations

- Associations between classes are usually implemented in data fields.
- You need to make two important choices:
  - Do you store a single object, or a vector of objects?
  - Should you store objects or pointers?
- First decide what the multiplicity of the association is:
  - 1 : many (ex. every company has many employees)
  - 1 : 1 (ex. every bank account has one owner)
  - 1 : 0 or 1 (every department has 0 or 1 receptionist)
- For a "1 : many" relationship, you need to use a vector (or some other data structure).

## Implementing Associations

- You use pointers in three circumstances.
  - For a "1 : 0 or 1" relationship
  - For object sharing
  - For polymorphism, to refer to an object that may belong to a base class or a derived class.
- Examples:
  - Since multiple bank accounts could share the same owner, it makes sense to use a pointer.

    >     class Bank Account
    >     {
    >        ...
    >     private:
    >        Person* owner;
    >     };

  - A vehicle has multiple tires, but a tire can only be part of a single vehicle.

    >     class Vehicle
    >     {
    >        ...
    >     private:
    >        vector<Tire> tires;
    >     };

## Example: Printing an Invoice

- Recall the five part development process that is recommended for you to follow:
  - Gather requirements.
  - Use CRC cards to find classes, responsibilities, and collaborators.
  - Use UML diagrams to record class relationships.
  - Document classes and member functions.
  - Implement your program.
- For this example, the methodology will feel overblown, but it will introduce you to the mechanics of each step.

## Example: Printing an Invoice (Requirements)

- This program prints the billing address, all line items, and the amount due.
- Each line item contains the description and unit price of a product, the quantity ordered, and the total price.

  >     Sam's Small Appliances
  >     100 Main Street
  >     Anytown, CA 98765

  >     Description                        Price  Qty  Total
  >     Toaster                            29.95   3   89.95
  >     Hair dryer                         24.95   1   24.95
  >     Car vacuum                         19.99   2   39.98

  >     AMOUNT DUE: $154.78

- In the interest of simplicity, no user interface is required.

## Example: Printing an Invoice (CRC Cards)

- To discover classes, list the nouns:

  > Invoice | Address | Item | Product | Description
  > Price | Quantity | Total | Amount Due |

- Note that Toaster is a data value for an Item object, not a class.
- Product description and price are fields of the Produce class.
- Quantity is not an attribute of a Product.
- We will create an Item class that records the product and the quantity ("3 toasters").
- Our four candidates for classes are:

  > Invoice | Address | Item | Product

## Example: Printing an Invoice (CRC Cards)

- The purpose of the program is to print an invoice. Record that responsibility on a CRC card.

  > Invoice
  > print the invoice

- The invoice does not print the address. That responsibility belongs to the `Address` class.

  > Address
  > print the address

- Similarly, printing an item is the responsibility of the `Item` class (no card shown).

## Example: Printing an Invoice (CRC Cards)

- The print member function of the `Invoice` class calls the print member functions of the `Address` and `Item` classes.

  > Invoice
  > print the invoice | `Address`
  > | `Item`

## Example: Printing an Invoice (CRC Cards)

- The invoice also needs to compute the total amount due.
- To obtain that amount, it must ask each item about the total price.
- Each item must ask the product for the unit price and multiply it by the quantity.

  > Product
  > get description |
  > get unit price |

  > Item
  > print the item | `Product`
  > get total price |

## Example: Printing an Invoice (CRC Cards)

- The invoice must be populated with products an quantities so that is can print the result.

  > Invoice
  > print the invoice | `Address`
  > add a product and quantity | `Item`
  > | `Product`

- We now have a complete set of CRC cards.

## Example: Printing an Invoice (UML Diagrams)

- Use the collaboration column in the CRC cards to get the dependency relationships.
- An invoice object must hold the address and the items when it prints the invoice.
- An invoice object need not hold a product object when adding a product.
- It's the item's responsibility to hold the product.
- There is no inheritance in this example.
- The relationships between the invoice classes can be expressed in the following diagram.

## Example: Printing an Invoice (Class and Function Comments)

- Now design class headers and supply documentation for member functions.
- For member functions you will have to come up with reasonable parameters and return types.

  >     /**
  >        Describes an invoice for a set of purchased products.
  >     */
  >     class Invoice
  >     {
  >     public:
  >        /**
  >           Adds a charge for a product to this invoice.
  >           @param aProduct the product that the customer ordered
  >           @param quantity the quantity of the product
  >        */
  >        void add(Product p, int qunatity);
  >        /**
  >           Prints the invoice.
  >        */
  >        void print() const;
  >     };

  >     /**
  >        Describes a quantity to an article to purchase and its price
  >     */
  >     class Item
  >     {

  >     public:
  >        /**
  >           Computes the total cost of this item
  >           @return the total price
  >        */
  >        double get_total_price() const;

  >        /**
  >           Prints this item
  >        */
  >        void print() const;
  >      };

  >     // etc.

## Example: Printing an Invoice (Implementation)

By documenting first, you can share the documentation with others if you work in a team.

## Example: Printing an Invoice (`invoice.cpp`)

## Example: An Educational Game (Requirements)

- You task is to write a game program that teaches your baby sister how to read the clock.
- The game must:
  - Randomly generate a time.
  - Draw a clock face with that time.
  - Ask the player to type in the time.
- The player gets two tries to guess the time before the game displays the answer.
- The score increases by one point each time the player guess the time correctly.

## Example: An Educational Game (Requirements)

- The game has four difficulty levels:
  - Level 1: full hours.
  - Level 2: 15 minutes intervals
  - Level 3: 5 minute intervals
  - Level 4: all possible times (1 minute intervals)
- When the player scores 5 points the game automatically advances to the next level.
- The game begins by asking for player's name and starting level.
- After every round the player is asked whether she wants to play more.

## Example: An Educational Game (CRC Cards)

- First we list the nouns:

  > Player | Clock | Time
  > Level | Game | Round

- Level is just an integer between 1 and 4; it doesn't need a class.
- Start with a simple class: the `Clock` class.
- When a clock draws itself, it must draw the hands to show the current time.
- To get the current time, it must collaborate with the `Time` class.
- How does the clock know what time it is? You need to tell it:

  > Clock
  > draw | `Time`
  > set time |
  > | ``

## Example: An Educational Game (CRC Cards)

- The `Time` class must be able to get the hours and minutes of a given time and check when two times are the same.

  > Time
  > get hours and minutes |
  > check if equal to another `Time` object |
  > | ``

## Example: An Educational Game (CRC Cards)

- A player has a name, a level, and a score.
- When the player gets a correct answer, the score must be incremented.
- After five score increments, the level is incremented - we will let the increment score function take care of that, but we must be able to find out what the level is.

  > Player
  > increment score |
  > get level |

## Example: An Educational Game (CRC Cards)

- A good plan is to introduce a class that represents the entire program:

> Game
> play |

## Example: An Educational Game (CRC Cards)

- What does it mean to play a game?

  >     read player information
  >     do
  >     {
  >        play a round
  >        ask whether player wants to play again
  >     }
  >     while (player wants to play again);

- New actions are added to the game class based on this pseudocode.

  > Game
  > play |
  > read player information |

## Example: An Educational Game (CRC Cards)

- Whose responsibility is it to play a round?
  - The `Game` class
  - The `Player` class
- It probably doesn't matter, so we will choose the Game class.
- What happens in a round?
  - Make a time (uses Time class).
  - Draw a clock (uses Clock class).
  - Ask for input (uses Player class).
  - Check input (uses Clock class)
  - Ask again or increment score (uses Player class).

> Game
> play | `Player`
> read player information | `Clock`
> play round | `Time`

- There is no need for Round and Level classes, so do not implement them.

## Example: An Educational Game (UML Diagram)

- The collaborator columns of the CRC cards indicate part of the relationship between class, but which are dependencies and which are associations?
- Since the same player must be manipulated for several rounds, you can't just construct local player objects.
- The `Game` object must have a data field of type Player and a have the play round function modify its state.
- The `Clock` and `Time` classes to not need to be associated with the `Game` class.
- The set time functions from the `Clock` class suggests that the `Time` class is associated with the `Clock` class.

## Example: An Educational Game (Class and Function Comments)

- The `Clock` class:

  >     class Clock
  >     {
  >     public:
  >        /**
  >           Sets current time.
  >           @param t the time to set
  >        */
  >        void set_time(Time t);

  >        /**
  >           Draws the lock face, with tick marks and hands.
  >        */
  >        void draw() const;
  >     };

## Example: An Educational Game (Class and Function Comments)

- The `Player` class:

  >     class Player
  >     {
  >     public:
  >        /**
  >           Increments the score. Moves to next level if
  >           current level complete.
  >        */
  >        void increment_score();

  >        /**
  >           Gets the current level.
  >           @return the level
  >        */
  >        int get_level() const;
  >     };

## Example: An Educational Game (Class and Function Comments)

- The `Game` class:

  >     class Game
  >     {
  >     public:
  >        /**
  >           Plays the game while the player wants to continue
  >        */
  >        void play();

  >        /**
  >           Reads player name and level.
  >        */
  >        void read_player_information();

  >        /**
  >           Plays a round, with up to two guesses.
  >        */
  >        void play_round();
  >     };

## Example: An Educational Game (Class and Function Comments)

- Before reinventing the wheel, determine if you can use the `Time` class that is part of the book before designing a new class.
- To use the `Time` class from the book, you must set seconds to zero. (Seconds has no use in our game).
- To see whether two times are identical, check whether there are zero seconds from the first time to the second time.

  >     time1.seconds_from(time2) == 0

## Example: An Educational Game (`clock.cpp`)

##