My Rules of Abstraction

Monday, September 15th, 2025

Rethinking the DRY Principle in Programming

I think the term DRY (Don't Repeat Yourself), albeit useful, is often misused in programming. The DRY rule advocates for avoiding code duplication by abstracting common functionality into reusable components. Yes, I know that DRY has its benefits, but it's often overused among developers.

A tweet I often refer to is from @Dmitrii: "Code is often multidimensional. It may solve multiple problems, and often you don't even know the dimension limit. The more data points with non-overlapping use cases you obtain, the more confidence you'll have that your abstraction will actually solve the problem." Abstracting early is usually a mistake. Duplicate the code 2-3-4 times, and you'll start noticing patterns.

My Problem with Over-Abstraction

A while ago, as I set out to waste a huge chunk of "my 24 hours", I happened to find Uncle Bob's daily rant. This one was about the DRY principle and it made me understand how much developers have overused this methodology. Not a total waste of time, right?

My Rules for Good Abstraction

  • Wait until n=3 or 4: My general rule of abstraction is not until three or four instances. My advice is to copy and paste until you see a genuine need to abstract and reuse. When it's more than three instances, then we can start to think about abstraction. Less than that doesn't really make much sense.

  • Consider the code size: If you have 10 lines of code only used in two places, then you definitely don't need abstraction. It's not worth it.

  • Allow repetition for simple code: If the code is self-explanatory and short, you are allowed to repeat yourself probably more than three times. Think about it - imagine having to go 5 files deep to make a single line change. That's what DRY can do if you aren't careful.

  • Abstractions should be pure: If you abstract something and you have to change it later, then it isn't worth it. Abstractions should always be pure - like a + b = c. In the sense that every time this runs, it should always give us a consistent answer.

  • Different domains need different solutions: If we have to change something like a + b = c to become a + b - c (something of that sort), then you can just write separate code for that part because they are not of the same domain. It looks easy to do at first, but abstractions can get complex pretty easily.

Paraphrasing Uncle Bob: they are going to evolve in different directions, so let them be. Even though they might appear the same initially, it's definitely not worth forcing them into a single abstraction. Code that looks similar today may have completely different requirements tomorrow, and premature abstraction will only make future changes more painful.

In summary

The key is to resist the urge to abstract too early. Let patterns emerge naturally, and only create abstractions when you have clear evidence that the code will remain stable and truly reusable across multiple contexts. It is okay to repeat yourself.

Share this post