Software architecture finds some odd mirrors in life. I found an amusing example at the grocery store. The bananas. The great elegance of the banana is the simple fact that nature has endowed it with its very own container. It's thick, it's tough, and if you've got yourself an opposable thumb, it's easy to open. To add to all of that, it's 100% biodegradable! But as I sauntered down the produce aisle, I was aghast to discover that the bananas were wrapped in plastic!
Why would anyone shrink-wrap a bunch of bananas?
Of course, there's an answer. Grocers don't really like people breaking up those bunches. Bio-degradation and ease of use be damned. We don't want stray bananas in the bin!
But the plastic wrap solution is just so inelegant.
In our world of functions, variables, and objects, we are sometimes prone to shrink-wrap bananas. We sometimes even create design patterns that encourage us to do this. Just like Dole's packaging gurus, we are often unaware of our misstep.
The primary mistake that leads to shrink-wrapped bananas isn't laziness or zeal or naivety. It's metaphysics. Or, to use a less loaded term, it's the fact that we have certain (often unstated) commitments to organize our world in a certain way. In the Dole world, metaphysics manifested this way:
We want the bananas to stay together. To get things to stay together, we put them inside of plastic. Ergo, let's shrink wrap the bananas.
It's easy to lapse from here into platitudes about "thinking outside the box" or "applying Occam's razor", but to do so is to ignore the real origin of the misstep. I have a hard time believing that a group of packaging scientists were locked in the lab with no food or drink until they innovated their way out of the "stray bananas" problem. More likely, it was a common-sense move. It was the simple application of a tested principle: If you want it to stay together, put it in plastic.
The Parsimony of Structure
We are builders. We transform ideas into programs. We design things that have never existed before. We don't make houses. We make lexers and tree-walkers and daemons and message queues.
But in our zeal to create, we sometimes over-create. We clutter. And sometimes instead of creating our blueprints from scratch, we re-use each others' blueprints. "Design patterns," we call them.
When we let metaphysics get the better of us, though, we lapse from elegance (simplicity, as Rich Hickey termed it) into complexity. We add layers and wrappers and factories and containers that, simply stated, don't need to be there. And we do this in the name of Platonic eidetic (eye-DET-ic) purity: "This class really is a..." We refactor ourselves from a cottage to a sky rise, and then insist that we've just built a single-family residence.
To fight this tendency, we need to invoke the rule of parsimony of structure. Like YAGNI (You Aint Gonna Need It), parsimony of structure is a rule intended to keep us from extra work. And the rule goes something like this:
Introduce only the structures that are necessary to the accomplishing of the goal at hand.
Moreover, the parsimony of structure should be extended to suggest that...
Introducing a structure purely on the grounds of eidetic purity is bad practice.
Eidetic purity just means "for purely idealist or theoretical reasons". Whenever your arguments lapse from matters of practicality into debates as to whether something "really is an instance of a...", or "in an ideal world functions as a..." or is "ideally a..." you are now debating eidetic purity. (And when you get into debates that "several years from now, we may wish that...", you are also bordering on the eidetic purity argument.)
Don't Hate The Banana Hater
Before anyone's blood pressure spikes, allow me to make one more loop around the path just taken. I am not saying that design patterns are bad or should be avoided. I am not suggesting that all your code should live in one giant
main() function, either. We build better software today because we have studied the software of yesterday. And design patterns are often the best way of accomplishing a common task. But when we use design patterns because we are supposed to use design patterns, we're back to arguments from eidetic purity.
Instead, I am pleading with developers to stop building Plato's cathedral. Software development is really not about populating an unseen world with ideally perfect widgets. It is about building the appropriate metaphysical structures such that both you (and other programmers) and the computer can agree about what happens when you execute the program.
No computer cares that you built it a cathedral of bytes. And no programmers appreciate gratuitous BananaFactoryFactorySingleton classes.
Dole Gets Elegant
If you visit your grocery store now, you probably won't find any shrink-wrapped bananas. Dole has invented a better solution: a slim green band of tape that both colorfully displays their log and keeps a bunch of bananas together.
Honestly, I love this solution. It's simple and elegant. There are no stray bananas left in the bin. But it ain't just an empty implementation of a design pattern. And rest assured that you won't see oranges bundled together with a band of green tape.