June 15, 2006

...Learn TDD with Codemanship

The Reused Abstractions Principle

I'm a fan of test-driven development, as you may already know. I believe that abstractions are discovered, not invented. When I see copy-and-paste programming or switch statements, I immediately think there's a supertype missing somewhere - and then I create it using simple refactorings like Extract Superclass or Extract Interface.

I'm not so keen on creating abstractions up-front. There's a tendency among Java programmers, following the example of many Java books and Java APIs, to habitually create interfaces for everything. They tend to end up with a clutch of abstractions that are implemented only once. In my opinion, these are not abstractions at all - they're indirections. I would like to make a clear distinction between the two. Creating an abstraction in order to avoid having clients bind to a concrete class is indirection - in my opinion, anyway. Extracting duplicate code into its own abstract class or interface is bone fide abstraction.

The problem with the indirection approach is that you muddy the waters as far as design quality is concerned. You finish up with a lot more types than are actually necessary to achieve exactly the same quality of design, and the abstract types you create have the effect of making not-very-abstract code look far more abstract than it really is. In other words, it can fool you into believing your design is better than it really is.

Robert Martin's distance from the main sequence metric relies on a measure of the abstractness of packages, to assess conformance to the stable abstractions package design principle. Abstractness is given as:

A = abstract types / all types in a package

If some of your abstract types are actually indirections, and not true abstractions, then the value of A will be skewed and you'll get a rosier picture of package design quality than is perhaps warranted. True abstractions - because they're more general - are less likely to want to change. Indirections are every bit as likely to change as the classes that implement them. If you depend upon a lot of indirections, you are potentially making a rod for your back.

I find Martin's metrics jolly useful in guiding me to OO design problem areas, and when the values are skewed by indirections my bad packaging radar goes on the blink and I can't tell which are the genuinely bad packages anymore.

To counter this, I propose a complementary OO design principle: the Reused Abstractions principle. Simply it states that any abstraction should be implemented/extended more than once. If it was discovered, and not invented, then this must surely be true. In that respect, it is also another possible indicator of how test-driven you are.
Posted 15 years, 2 months ago on June 15, 2006