views:

67

answers:

3

I know there are LOTS of reasons why you would compose a certain object inside another one. Some schools of thought have made explicit the reasons for architecting a program a certain way e.g. 'data-driven design' or 'domain-driven design'. I'm still a beginner to OOP, and it's often hard for me to understand why one object should be contained by another. Sometimes, I find myself with an object that seems awesome, and then I get to the point where I realize, "Okay, now I have to put this somewhere?" Is the reasoning behind this similar to where I'd decide put a file on my hard disk?

I have a couple guiding principles for this:

  • If it models a relationship in the physical world.
  • If the composer has data needed to construct the object.
  • If the composed object will be listening to the composer.

What do you look for when you make this decision?

+3  A: 

Well, one very simple concept that helped me with this is simply the concept of "has a" versus "is a". Ask yourself, is the contained object something the containing object has, or is it something the containing object is? If it's something the containing object has, then containment is appropriate. Otherwise maybe you should be looking at inheritance.

A dog IS an animal, and has a nose, so it's:

class Animal { }

class Dog : Animal { Nose n; }

Now this works fine. One "problem" with this approach is that you tightly couple noses and dogs, so sometimes you'll see things like containing an interface pointer rather than an object, or you might Google "Dependency Injection". But as the saying goes, "has a" and "is a" is often close enough for government work.

Early on, just try lots of examples and over time it will become natural. If you end up with spaghetti, throw some meatballs at it and try again! :)

John Lockwood
A: 

What alternatives are you considering? Are you talking about Containment versus Inheritance, John Lockwood's comments about hasA and isA help with that issue.

Or are your perhaps talking about, Containment versus Association? There are various flavours of hasA. For example a Person may haveA Spouse, but clearly does not containA Spouse. There's a difference between changing a Spouse and changing a Nose.

The kinds of relationship that you consider:

  • Lifetime: Does it make sense to create a Person without a Nose? Can Noses exist without a Person? Can a Person exist without a Spouse? The answers to these questions drive the kind of operation you choose to have on Person. Probably don't need a setNose() method, though maybe we do need a wipeNose() method, and we probably do need a marry(Person) method.

  • Cardinality: How many Noses for a Person? How many Wheels and Seats does a Vehicle have? Answers to this determine the kinds of data structures? Just a reference? A list? An hash table?

I found it helpful to read about UML modeling, especially class diagrams. This reflects much experience of how to usefully capture various kinds of relationships.

djna
A: 

Sometimes, I find myself with an object that seems awesome, and then I get to the point where I realize, "Okay, now I have to put this somewhere?"

From the above sentence, it sounds like you're trying to design from the bottom up. One of the thing's I've learned over the years is that top down design is the way to go. You should only write the class after you know where it needs to be used. Otherwise you just end up writing classes that "seem awesome" and contain code that might not be useful at all.

Tom Dalling
Yeah! That sounds accurate; thanks. But, I know that design is an interplay of top-down to bottom-up and back again repeat ad nauseum. There never seems to be a clear-cut 'way to go' :/
Pup