From: johnson@m.cs.uiuc.edu (Ralph Johnson)
Subject: Re: Object-Oriented Methodologies - Class Specifications
Organization: University of Illinois, Dept. of Comp. Sci., Urbana, IL
Date: Wed, 9 Sep 1992 10:53:20 GMT

Claiming that inheritance is not useful because it won't handle a
particular problem is like saying that chain-saws are not useful
because they are not good for cutting food at the table.

I think that inheritance is great, and I don't want to use a language
without it.  Nevertheless, when I teach object-oriented programming
and design I am constantly emphasizing that inheritance shouldn't
be overused, because beginners are always misusing it.  Inheritance
has several legitimate uses, but it is only one relationship among
many.  It is a relationship between classes, not objects, and
that is an important distinction.

The most recent edition of CACM has a paper by Ken Rubin and Adele
Goldberg on "Object Behavior Analysis" that is pretty good.  One of
the side comments that they made is that at one time they tried to
enumerate all the different kinds of relationships that can exist
between objects, and they eventually gave it up.  They decided that
there are an infinite number of relationships between objects, and
that it isn't possible to make a nice little table of them.  Each
project will want to define its own relationships.  That is my
experience, too.  There are a few relationships that are quite common
and that are used over and over again, but there are other relationships
that are rarely used, but that are essential when you need them.

sally@projtech.com (Sally Shlaer) writes:

>I would suggest instead that we need to look carefully at *additional
>techniques* for modeling relationships.  In my experience, entities in 
>the world are related in very interesting and complex ways -- and to
>capture these relationships accurately requires a much richer topology
>than can be attained with hierarchies alone.  For example:

>     Dog Owner owns Dog

>     Veterinarian provides medical services for Dog
>     Dog Owner pays Veterinarian
>     Veterinarian recommends Dog Food for Dog

>     Pet Store stocks Dog Food
>     Pet Store offers Dog Toy as a promotion for selling Dog Food

>     Dog Owner buys Dog Food from Pet Store
>     Dog prefers Dog Food

>So here we have just 6 objects and at least 8 relationships -- none
>of which have the generalization/specialization concept (i.e., inheritance).

We have people, dogs, food, toys, and stores.  People and stores can
own things.  Dogs, food, and toys are things that can be owned, i.e.
they are property.

In addition, we have some events.  (Event objects are a bit wierd
at first, but are absolutely essential for accurate modeling).
In particular, we have a "purchase".  First, the Dog Owner purchases
veterinary service from the Veterinarian, then purchases Dog Food
from the Pet Store.  (Why all these capital letters?  I don't know!)
So, there are two "purchase" events.

The Dog  Owner and Veterinarian are both People.  People and Stores
are both Owners.  The Dog, Dog Food, and Dog Toy are both Property,
which means that they have an Owner.  

>     Dog Owner owns Dog
Standard relationship between Owner and Property.

>     Veterinarian provides medical services for Dog
>     Dog Owner pays Veterinarian
There is Purchase event with Dog Owner as buyer, Veterinarian
as seller, and medical services for Dog as item or service.

>     Pet Store stocks Dog Food
Standard relationsip between Owner and Property.
>     Pet Store offers Dog Toy as a promotion for selling Dog Food

>     Dog Owner buys Dog Food from Pet Store
Purchase event with Dog Owner as buyer, Pet Store as seller,
and Dog Food (and Dog Toy) as property purchased.  Note that
we might have two different kinds of Purchases, a Service Purchase
and a Property Purchase.  The difference is that a Property Purchase
causes the Owner of Property to change, while a Service Purchase
doesn't.

I think all those relationships are pretty standard ones.  There
are two fairly odd relationships that I haven't looked at yet.
These are:
>     Veterinarian recommends Dog Food for Dog
>     Dog prefers Dog Food
Note that it isn't really the Dog that knows about the Dog Food
that is recommended, but the Dog Owner.  So, to model this correctly
we might have to keep a list of plans with the Dog Owner, i.e. say
that the Dog Owner now is planning to try the Dog Food. (I hate
these capital letters.  The Dog Owner is not planning to try any
old Dog Food, but some particular Dog Food, we just don't know what
it is.  The Vet. didn't say "You should give your Dog some Dog Food",
but he said "You should give Fido Alpo", or some such thing.  I
guess it is probably not a big deal.) In the same way, a Dog must
have a ranking of various food items, and the last statment is
saying that Dog Food now has the highest ranking.  In other words,
for all Food in Foods, preference(Dog, Dog Food) >= preference(Dog, Food).
Of course, that is just for this Dog.  The Dog that I had as a child 
prefered bananas, which probably isn't considered a Dog Food!

In summary, I see inheritance all over the place.  Just because
inheritance doesn't handle every relationship (or even the majority
of them) doesn't mean that it isn't useful.  Inheritance lets us
define a relationship like Owner/Property once and reuse that
relationship over and over again.  It also lets us reuse objects
that we create to represent relationships, like the Purchase event object.

Inheritance is a relationship between *kinds of objects*, not between
objects.  We need to make abstract *kinds of objects* like Owners
and Property to make the best use of inheritance.  These abstract kinds
of objects are our way of reusing the definition of a relationship.

In answer to the question of when we should represent a relationship
by simple pointers from one object to another, or when we should
have a separate object, the answer is "it depends".  In general, simple
relationships are best handled simply, i.e. by making one object an
attribute of the other.  If a relationship becomes complex then it
is best to make an object to represent it.  However, most relationships
are pretty complex if you just look closely enough.  For example, we
can have co-owners of property.  They can be joint owners, or each can
own part of it.  Their rights depend on which state they live in.  We can
keep track of when the owners gained the property, and who the previous
owners were.  If we want to keep track of all this then Ownership should
be an object.  I bet that much information is rarely needed, so most of
the time the simplest representation is best.

As far as I am concerned, there are only two ways to represent 
relationships, either by having one object directly refer to another
or by having them refer to an intermediary object that represents
the relationship.  Whether one object refers to another with a pointer
or with some other name is just implementation detail, and certainly
not part of the analysis.  Once a relationship is represented by an
object then you can start to make class hierarchies of the relationship.
On the other hand, as the Owner/Property example shows, you can reuse
a relationship definition by inheritance even when you don't make a
relationship an object.

Hey, Sally! You can use any of this in your next book if you want to,
as long as you reference me!