What is Object-Oriented Design (OOD)?

Here are some ways that various authors have described Object-Oriented Design:

Key Concerns of an Object-Oriented Design

Here are some key concerns that a developer must have when preparing an object-oriented design:

Principle of Modularity

A complex software system should consist of a set of modules that are highly cohesive, but loosely coupled.

When you actually begin to think seriously about the classes you are going to need for a software development project, you need to keep this Principle in mind. A good rule of thumb to remember is that a good design should attempt to maximize cohesion and minimize coupling.

You should think of this Principle as applying at all levels and stages of development, whether at the highest level of class relationships or the lowest level of method implementation.

Static Structure and the Domain Model

Use cases can help us to capture the system vocabulary for a problem we are trying to solve. This system vocabulary will contain the terms which characterize the problem domain, and will help us build a domain model, i.e., a list of all objects we need to model in order to properly model the complete system. When we understand how these objects relate to one another we shall have some kind of sense of the static structure of the system. We need to have this before we can begin to ask how the system behaves dynamically, i.e., how the various objects interact at run-time.

Here are some high level descriptions of some of the key activities we need to perform when applying OOD:

Note that CRC cards can be a big help with the first three of the activities in the above list.

As we think more and more about the model, we may find that a design language like the UML (Unified Modeling Language) will be helpful in describing the various parts of the model and their interactions to others, as well as to ourselves.

We must also be continually on the lookout for situations in which we might be able to make use of a design pattern, i.e., a previously-existing solution to a problem that has already been solved. Recognizing and using design patterns is one way of tring to avoid having to "re-invent the wheel".

Possible Relationships between Classes

It is a good idea to construct a UML class diagram to show the class relationships in any software development project you are working on. The most frequently encountered relationships are discussed below. It may be worth noting that some authors seem to suggest that the only relationships that are really clear-cut, useful, and occur frequently, are inheritance and composition, and that composition is to be favored over inheritance if there's a choice. Those authors also suggest that the problems with the other relationships stem from the fact that it's often very difficult to know exactly what a particular developer means by his/her interpretation of that relationship.

inheritance, generalization, specialization
The terms generalization and specialization are both used to refer to inheritance, which in turn refers to the "is-a" relationship. A better conceptual model may be to think of a "may be substituted for" relationship, or an "is-a-kind-of" relationship, rather than a strict "is-a" relationship.

Example:
A Student is-a-kind-of Person. Or, a Person may be considered a generalization of a Student. That is, a Student may be considered a specialization of a Person. Or, a Student "may be substituted for" a Person because a Student is-a-kind-of Person.

association
The term association refers to a relationship that is a little "deeper" than than dependency (see below), in that it's a structural relationship in which one object is "connected" to another object. This usually means that an object of one class will contain a reference to an object of another class as one of its member variables.

Example:
A Person borrows-from a Bank.

dependency
The term dependency, refers to the relationship in which one object depends on another object's specification. This typically occurs when an object of one class "uses" an object of another class, and a change in the specification of the class being used will typically require an update to the dependent object's class.

Examples:

  1. A Purse class may depend on (i.e., "use") a Coin class in order to compute the total amount of money contained in a Purse object. If the interface to the Coin class is changed in some way, then one or more methods in the Purse class interface that take a Coin object as a parameter and perhaps call one or more of its methods may have to be changed as well.
  2. If a Psychiatrist object's examine(...) method takes a Patient object as an argument and calls the Patient object's queryMood() method, then if the name or argument list of the queryMood() method changes you will have to update how the Psychiatrist object calls this method.

CRC Cards (for discovering classes, responsibilities and collaborators)

CRC cards were first introduced by Kent Beck and Ward Cunningham in 1989 at a conference on "Object-Oriented Systems, Languages and Applications".

Question:
How might you use CRC cards to help in your development of a program to play the game of Mastermind?