← Blog

The Right Amount of Abstraction

The Two Failure Modes

Under-abstraction is the one junior engineers mostly worry about. You copy-paste logic, functions grow to 300 lines, the same validation rule lives in four places, and changing one thing requires finding all four. This is the "don't repeat yourself" failure mode.

Over-abstraction is the one experienced engineers fall into. You build a general-purpose framework to solve a problem you have one instance of. You create a plugin system for a feature no one will ever plug into. You write a configurable abstraction where a simple function would have been cleaner. This is the "wrong abstraction" failure mode, and it's actually harder to fix than duplication.

The wrong abstraction is sticky. It gets built upon. Other code depends on its interface. Removing it later costs more than removing duplicated code.

The Rule of Three

A practical heuristic: don't abstract until you have three uses of a thing. One use is a specific case. Two uses might be coincidence. Three uses is a pattern.

This isn't a law — if the second instance is radically different from the first, don't abstract. If the pattern is obviously going to recur, don't wait. But as a default, it prevents premature abstraction.

What Good Abstractions Feel Like

A good abstraction:

When you're using a good abstraction, you don't need to look at its implementation to use it correctly. The interface tells the story.

A bad abstraction makes you read the implementation every time, because the name or interface doesn't match what it actually does.

The Leaky Abstraction Problem

All abstractions leak. At some level of usage, you'll hit a case the abstraction doesn't handle well, and you'll need to understand the thing underneath it. This is not a reason to avoid abstraction — it's a reason to keep abstractions thin and honest.

The worst abstractions are the ones that try to completely hide complexity that sometimes genuinely matters. They work until they don't, and when they break, they break in confusing ways.

Practical Advice

When you feel the urge to abstract, ask: am I doing this because it makes this code clearer, or because abstracting feels like progress? The second reason is not a good reason.

The simplest code that works is not a failure of imagination. It's often the right answer.

Stay in the loop

Get new posts delivered to your inbox.

Leave a comment