In The Cult Of Abstraction I railed against the over-use of abstraction. Here, I want to talk about a particular source cause of over-abstraction I have seen (and been guilty of).
Recently, while working with another team here at Spotify, I was working through some of their test code using the Helios Testing Framework, and the harness used a surprisingly complicated tree of classes to set up the various containers it used.
When it came down to it, the impenetrable code was a result of taking DRY too far. While the DRY principle in itself is generally good, what I’ve never seen included with it is:
The replacement for repetitive code is, by necessity, a layer of abstraction; and layers of abstraction always come at a cost.
This is true if you’re just extracting a magic number to a constant, or placing repetative code into a separate function/method. The cost of reducing duplication is paid in increased conceptual load of the added abstraction. Often, this conceptual load is a cost well worth paying. But I’ve also seen a great many cases where the cost far exceeds the benefit it brings by taking an instrinsically simple procedure, and making it into an abstracted mess. While the code may check all the academic checkboxes, I wouldn’t wish it on anyone.
In short, there are two ditches:
- unmaintainable, duplication-infested code
- unmaintainable, over-abstracted code
Let’s keep it between the ditches.
Update: I found a post here: Small Functions Considered Harmful which addresses many of the same kinds of issues.