Granularity Of Variation

GranularityOfVariation is the granularity of the pattern of difference between two or more things that are similar. For example, does the entire block (function, class, method, etc.) differ between the items being compared, or only part of the block?

I've learned to be hesitant to hard-wire or heavy-wire the granularity of variation into a design. Although there may be a general tendency to the pattern (at least up front), exceptions can and do often pop up (EightyTwentyRule). It is one of the things that bothers me about PolyMorphism. IF statements seem easier to adjust in this regard. They are like a caliper tool that can widen or narrow as needed. Polymorphism, on the other hand, often requires overhauling or splitting the polymorphic interface, requiring roughly 4 times as much code rework.

Of course, it can be partially solved by duplicating the portions that are similar rather than refactor to a smaller polymorphic granularity, but of course this is a violation of OnceAndOnlyOnce. A small amount may be acceptable, but this is hardly the ideal and the granularity lapses may continue into the future.

--top

'if' statements do provide you higher-precision control than parametric or inheritance-based polymorphism. It does come at a cost, of course. It leads to a rather 'organically grown' codebase (hard to verify with analysis or code review, but organically grown unit tests provide a solution there), a possibly extreme cost to add new objects or dispatch decisions ('extreme' if you don't own the module or library), and poor code mobility (extremely high unnecessary coupling; every dispatch-point needs the whole damn namespace of objects). I.e. it isn't very nice to use when writing libraries or components for use by other people. Other than that, if it works for you... then feel free to do it.

The 'overhaul cost' for polymorphism is high when you decide you need to modify the polymorphic interface (cost is linear with number of unique objects unless you can have a reasonable default behavior). The 'overhaul cost' for the if-statement mechanism is high if you have a lot of decision points where you need to inject code (but, again, is reduced if you have reasonable default behaviors) - and a great deal higher if you don't control the code in which the dispatch decision is made. You can just as easily end up violating OnceAndOnlyOnce with the 'if' based solution because, all too often, you'll find yourself duplicating the exact same conditions-checks to every decision point. In my own experience, the number of decision points and number of object-variants can vary quite a bit between projects. I'd not be comfortable saying that one is more or less expensive than the other. However, I do tend to combine the two techniques a great deal (e.g. have a few high-abstraction if/enum-based variants that are implemented with low-level polymorphism).

There are not a lot of reliable guidelines for when to use one or the other, other than "rely on experience". Paying attention to the patterns of GranularityOfVariation in general and in a domain is one way to learn.


SeptemberZeroSeven

CategoryConditionalsAndDispatching, CategoryPolymorphism


EditText of this page (last edited April 30, 2013) or FindPage with title or text search