You Don't Hate Abstractions

Published: (December 7, 2025 at 08:08 PM EST)
6 min read
Source: Dev.to

Source: Dev.to

It’s an hour until you’re free for the weekend, and you’re trying to knock out one last ticket before you escape into whatever action‑packed plans await you.

You spot a seemingly harmless task: “Add Middle Initial to User Name Display.” You chuckle. Easy. A palate cleanser. A victory lap.

You assign the ticket, flip it from New to Active, and let your IDE warm up while you drift into a pleasant daydream about not being here.

But then the search results begin to appear, slowly, line by line, and your reverie begins to rot:

IUserNameStrategy
UserNameContext
UserNameDisplayStrategyFactory
StandardUserNameDisplayStrategy
FormalUserNameDisplayStrategy
InformalUserNameDisplayStrategy
UserNameDisplayModule

Your chuckle hardens into a throat‑scraping noise somewhere between a laugh and a cry.

“What in the Gang‑of‑Fuck is happening here?” you think, feeling your pulse tick up.
“Either someone read Refactoring.Guru like it was scripture and baptized the codebase in every pattern they learned, or a grizzled enterprise veteran escaped some Netflix‑adjacent monolith and is trying to upskill in TypeScript. Because surely no sane developer would build this much redirection for such a trivial feature… right?”

That tiny, spiraling task is a perfect microcosm of a continuous debate across engineering circles: when does abstraction help, and when does it become a hindrance?

I recently stumbled across the humorous article You’re Not Building Netflix: Stop Coding Like You Are by Adam — The Developer. While it resonates in many ways, its broader critique is ultimately misdirected.

Adam opens with a more complete version of the code mocked in my prologue and uses the verbosity and obscurity of that abstraction pile as the springboard for a rebuke of using enterprise patterns across the board. The problem isn’t that the complaint is wrong; it’s that it points the finger at the wrong culprit, literally missing the forest for the trees.

Why Abstractions Matter

Abstractions are fundamental and essential. They are the elementary particles of software, the quarks and leptons that bind into the subatomic structures that become the atoms our earliest techno‑wizards fused into molecules. Today we combine those same basic elements into the compounds and contraptions used by millions. Without abstractions, we are left helpless in the ever‑increasing parallel streams of pulsating electrical currents, rushing through specialized, intricately forged rocks that artisan wizards once trapped lightning inside and somehow convinced to think.

But even with all that power at our disposal, the way we use these building blocks matters. Chemistry offers a fitting parallel. Food chemists have spent decades learning how to repurpose industrial by‑products into stabilizers, textures, preservatives, and anything else that can be quietly slipped into a recipe. Much of this work is impressive and innovative, but some of it is little more than creative waste disposal disguised as convenience: a brilliant hack in the short term and a lingering problem in the long one.

Developers can fall into the same pattern. We learn a new technique or pattern or clever trick and then spend the next year pouring it into every beaker we can find. We are not always discovering better processes; sometimes we are just repackaging the same product and calling it progress. When that happens, we are not solving problems—we are manufacturing new ones that future maintainers will curse our names over.

A developer must be architect, engineer, mechanic, and driver all at once. It is fine to know how to fix a specific issue, but once that problem is solved, that knowledge should become a building block for solving the next one. If we keep returning to maintain the same solution day after day, then what we built was never a solution at all. It was a slow‑burning maintenance burden misfiled as “done.”

Abstractions exist to reduce complexity, not to multiply it. Their purpose is to lighten the cognitive load, to lift the details off your desk so you can see the shape of the problem in front of you. Terse, repetitive, wire‑on‑the‑floor code that looks like it tumbled out of a flickering green CRT from 1999 may impress the authors who have stared at machine code long enough to discern hair color from a data stream, but it does not serve the broader team or the system that outlives them. Abstractions only do their job when they are aligned with the actual problem being solved, and that brings us to the part many developers skip entirely: modeling your software after the problem you are solving.

Seeing the Problem Before Solving It

When you build a system—any system, even a disposable script—the first responsibility is understanding why it exists. What problem does it address? Has that problem been solved before? If so, what makes the existing solution insufficient for you now? Understanding that difference is the foundation that everything else must sit on.

I learned this the hard way as a homeowner. My house is old enough to have grounded me if I talked back to it as a teenager. A couple of years ago we went through a near‑total remodel. After some work and the birth of our daughter, new problems started surfacing. We brought in a structural engineer. The slab foundation was heaving. Exploration revealed the culprit: the original cast‑iron sewage line had split along both the top and bottom, creating pressure changes and settling issues throughout the house.

The fix was not small. We pulled up every inch of flooring, replaced baseboards, repaired drywall, fixed the broken line, repainted entire sections, redid trim, installed piers, pumped in foundation foam, cashed in favors, and lost many weekends. Yet, even with all that, it still cost far less than buying an equivalent house on the current market.

Lesson: Things are rarely a total loss. Even when a structure looks hopeless, there are almost always assets worth salvaging inside the wreckage. You should not bulldoze unless you know you have truly exhausted the alternatives.

Before throwing away any system and starting another from scratch, assess what you already have. Understand what is broken, what is sound, and what simply needs reinforcement. Software, like houses, tends to rot in specific places for specific reasons. Understanding those reasons separates renovation from reinvention.

The Nightstand Problem

The same principle applies at a smaller scale. You may already own a perfectly functional house with perfectly functional furniture, yet still want a nightstand you do not currently possess. Your choices are straightforward:

  1. Find an existing nightstand – the open‑source gamble.
  2. Buy one – constrained only by budget and the manufacturer’s definition of quality.
  3. Build one yourself – limited only by your skills, imagination, and tolerance for sawdust.

If your goal is personal satisfaction or experimentation, then by all means build the nightstand. But if your goal is to sell or support a product that makes money, you are no longer just hobby‑carpentry; you are operating in the domain of enterprise software.

When building enterprise software, you must view the system from the top down while designing from the bottom up. This holistic perspective helps you decide when an abstraction is a helpful lens and when it is an unnecessary layer of indirection.

Back to Blog

Related posts

Read more »

Show HN: Detail, a Bug Finder

'Hi HN, tl;dr we built a bug finder that's working really well, especially for app backends. Try it out and send us your thoughts! Long story below.

Design System: Governance and Adoption

Introduction Building a design system is only half of the work. Yes, it's challenging to evaluate multiple options, gather feedback from stakeholders, and impl...