Friday, August 04, 2006

Containment Strategies

You may be familiar with the concept of the "Matryoshka doll" or Russian nested/stacking dolls.  These dolls come in the form of a set of decreasing sized dolls placed one inside another. If we decide that we have a need for multiple classes of varying degrees of “looseness” or “tightness”, we might want to solve the problem of presenting a single unified view to the client software by nesting the classes within each other.  I can think of two ways to do this nesting: containment and inheritance.

Let’s take a look at containment first.  We could create a “tight” class and then wrap it with a “loose” class.  The “loose” class would hold (contain) a reference to an instance of the “tight” class.  The loose class would provide the laissez-faire string methods that allow the client software to store and retrieve the properties of the class in a string format.  An individual property within the “loose” class would always store the incoming data within the “loose” class.  It might also attempt to validate the data and attempt to store (a converted form of) the data into the corresponding inner “tight” class property.  A variation on this might be to defer the validation and conversion effort until an explicit request to change the stage of the data occurred.  Another variation would be to implement some kind of a latch concept where the “loose” property kept track of whether or not to draw the data from its own internal string representation or from a “ToString” conversion of the data contained within the inner “tight” class.  One advantage of this approach is that the “tight” class is pretty much ignorant of all of the fun and games that go on during the flaky data entry.  That is all handled by the “loose” class.  Once constructed and completed, the “tight” class can be handed off to the part of the application that assumes that all of the data is in good shape.

A variation on the containment process would be to invert the relationship of the “loose” and “tight” classes.  In this approach, the “tight” class would contain the “loose” class.  I have never done this and can’t really think of a reason why I would want to.  It seems to muddy the waters especially with respect to the concept of separation of responsibilities.  It’s probably not a very good idea.

In the description above, we have sort of assumed that we only have two classes, one “tight” and a second, ”loose”.  The Russian dolls that I mentioned above typically have six to eight dolls nested within each other.  The containment process would work quite nicely with any number of classes.  Each class would know about the class nested within it.  It would not have to know that it was, in turn, nested within another class.  This seems like a fairly clean way of doing things.

Now let’s take a look at inheritance.  We still have our “loose” and “tight” classes.  If there are just these two classes, it might make sense to have one of them inherit or derive from the other.  Given our analysis above, it is most likely that we would inherit or derive the “loose” class from the “tight” class.  The “tight” class would provide all of the strongly typed property access methods.  The “loose” class would provide the same type of functionality of validation, conversion and transmission to the inner class as above.  With inheritance I would assume that it is unlikely that we would defer the validation, conversion and storage processing until some change of stage event.  I think it is much more likely that we would try to keep the parent and child classes in sync with each other.  If the client software used one of the “loose” property access methods to store a legitimate value whose underlying datatype was other than string, I think it is reasonable to expect that retrieving the strongly typed version of the property would give me the value that I just stored.  Again, the parent “tight” class can be used independently of the derived “loose” class. 

With two classes, I don’t know that there’s a whole lot of advantage in using one of these approaches versus the other.  I think they’re both fairly straightforward and easy to use.  If the number of distinct classes increases, I think that inheritance will become more complex and fragile, while the containment approach seems to be quite simple.  With inheritance, the most derived child class has to be aware of all of its ancestral classes.  In software design, too much knowledge is almost always not a good thing.  With containment, as noted above, each class only needs to know about the immediate nested class.



Post a Comment

Links to this post:

Create a Link

<< Home