Friday, January 18, 2008

Object Thinking and Description Objects

I'm reading about Description Objects in "Object Thinking" by David West, and I'm having a hard time wrapping my mind around them. Their primary mentions are on pages 125 and 217. The index in the book is a bit thin. I've had to use O'Reilly's Safari book search feature to find things in the book.

At their simplest, an Object Description is a map from labels (strings? atoms? symbols?) to primitives (e.g. string, int, etc.).

Rather than fill up a CRC card with lots of attribute based responsibilities (e.g. know age, know first name, etc.), your object would have a responsibility called describe self. This responsibility is met by returning a Description Object that contains attributes (e.g. age, first name, etc.).

Description Objects create at least one benefit. Let's say that you have a customer class that has the following attributes: age, first name, and last name. Your domain analysis shows that some customers also have discount. In a non-Object Thinking world, you would have two classes: Customer and CustomerWithDiscount. The only need for the CustomerWithDiscount is the fact that it adds a single attribute. In an Object Thinking world however, you would have a single Customer class but some Customers would return a Description Object that had a Discount label in it and others would not.

This raises some questions:

How does one Customer object get a Discount label in its Description Object?

I see that we have two options:

The first is that if it's the Customer object that adds the Discount label that, taken to its somewhat logical conclusion, implies that a Customer object would have to know about all labels that a Customer could possibly have, when they should be added, and what values they should have.

The other option is that some other object adds the Discount label, and that sounds like a breach of encapsulation to me.

Of the two options, I dislike the first one the most (but the second option comes in close behind). The first option implies that potentially a lot of intelligence would be placed in one class (what labels to add in different circumstances). The second option might spread that intelligence all around the place.

Perhaps we can use factory methods to encapsulate the population of the Description object. For example:

Customer createCustomer(age, firstName, ...)
Customer createCustomerWithDiscount(age, firstName, ..., discount, ...)

In this case the intelligence is all in one place and all of the encapsulation violations are done in one place. Perhaps that's not too evil...

If the presence of a label in a Description Object or its value, influences the behavior of an object, how is difference of behavior implemented?

If the Customer has a responsibility to calculate cost and a Customer with a Discount label in their Description Object calculates a different amount that a Customer without the Discount label, where does that decision logic go?

You might say that this is a job for polymorphism but if that is the case, then we need two Customer objects: one with a discount and one without. Hmmm, we introduced the Description Object to reduce the number of classes in the system but now we're back to two classes.

So does this mean that if the presence of a label in a Description Object or its value can influence behavior of the object, that entry doesn't need to be in the Description Object (and probably should not be there)?

I'll have to read up on Rule Objects but perhaps the cost calculation is a job for one or more rule objects (if inheritance and polymorphism are not appropriate).

What happens when you need to change a value in the Object Description?

If the Object Description is implemented as a mutable map and another object just goes to the map and makes a change, this is a definite violation of encapsulation.

The author states that Description Objects might have their own behaviors. If the author considers setting values of entries in the Description Object as one of the Description Object's behaviors, then we have created a new problem. Now we need different kinds of Description Objects for different kinds of customers. One Customer Description Object knows how to set the discount, while others know how to set other attributes.

Perhaps rule objects would come to the rescue again. When you create a Customer with a discount, you attach different rules to the Description Object than when you create other kinds of Customers.

It seems that in Object Thinking rule objects might be used in many places where polymorphic methods would be used in non-Object Thinking.

All this to say, I think I'll reexamine my CRC cards...

No comments: