Repeat Yourself

Photo by Jørgen Håland on Unsplash

I agree with Sandi Metz: duplication is far cheaper than the wrong abstraction.

A while back I had written a proof-of-concept: in Go, create a simple SFTP client, using only standard library packages, that retries a download or upload a configurable number of times before giving up. I encapsulated as much code as possible inside a package, and I was pretty satisfied with its “clean” and simple exported (public) API.

After a few months, I dug back into it to adapt it for new requirements. With fresh eyes, I immediately found that the abstractions I’d created were incompatible with the new requirements. I now needed configurability where I had inadvertently thwarted it in service of “simplicity.”

After a frustrating attempt to refactor to unwind the too-restrictive abstractions, I decided to rewrite it. It wasn’t a huge rewrite, but this was only because the original scope had been so constrained. I was lucky that I hadn’t built anything else on top of these misguided abstractions. Ultimately, I’d failed to inject some of my dependencies, and I should’ve known better.

I’ve been an obsessive DRYer in the past – i.e., make it work, make it small, make it fast, in that order – but I’ve come around to a different approach after having encountered this situation a few times:

Make it work, make it clear (simple, comprehensible at a glance), then maybe make it fast.

The conditional on “make it fast” depends on whether absolute performance improvements are currently more important than the next MVF, and they almost never are. Most operations in the systems I work on are bottlenecked by network or disk I/O, not CPU or memory. I don’t assume otherwise without measurements taken as it interacts with its environment at runtime.

DRY purism is an old habit that I’ve had to work to unlearn. It’s been easy to justify, having proven repeatedly that I tend to overestimate my ability to predict the abstractions that will be useful and permanent. I want the reader to be able to understand my code as quickly as possible.

For me, clarity is more important than brevity.

comments powered by Disqus