Easy Is a Trap. Here’s Why Your Codebase Is Dying.

You know that feeling when you open a file you wrote six months ago and genuinely can’t remember what it does? When every new feature feels like defusing a bomb with oven mitts on? When a simple bug fix takes three days because touching one thing breaks seven others?

That’s not because you’re bad at your job. It’s because you’ve been lied to.

The industry sold you on easy. Easy frameworks. Easy languages. Easy abstractions that promise you can build anything in a weekend. And every time you reached for easy, you accidentally built something that’s now strangling your team.

Here’s the truth nobody puts on a conference slide: Easy and simple are not the same thing. Easy is how you got here. Simple is how you get out.

Rich Hickey figured this out in 2011, and the fact that most developers still haven’t internalized it explains almost every nightmare codebase on Earth.

Let’s break it down.

Simple means untangled. It comes from the Latin simplus — one fold, one braid, one thing. A simple component does one thing. It’s not intertwined with fifty other things. You can reason about it in isolation. You can change it without detonating the system.

Easy means familiar. It’s near at hand. It’s the tool you already know, the framework that has a tutorial, the library with the most GitHub stars. Easy is a psychological judgment — it’s about you and your comfort. Simple is an objective one — it’s about the thing itself.

And this is where the trap snaps shut. Because the easiest path is almost never the simplest one.

Think about it. You need to add a feature. The easy move is to grab that ORM you’ve used a hundred times, chain together some callbacks, stuff logic into a model that’s already doing fourteen other things, and ship it by Friday. Done. Easy.

But what did you actually build? You just braided five concerns into one object. You created a tangle. Next month, someone else adds a sixth concern. Then a seventh. Six months later, that model is a 2,000-line god object that nobody wants to touch. It was easy every step of the way. It was never simple.

Every time you chose easy over simple, you took out a loan against your future self. The interest rate is brutal, and the bill always comes due.

This is why your codebase feels like a haunted house. Not because the problems are hard. Because the solutions were easy.

Consider the tools we celebrate. Frameworks that do everything for you. ORMs that hide SQL behind magical method chains. Meta-programming that lets you write five lines instead of fifty. They’re all easy. And they all create the same problem: complexity you can’t see.

When something is simple, you can see all of it. You can hold it in your head. When something is easy but complex, the complexity is hidden behind a friendly interface — until it isn’t. Until production goes down at 3 AM and you’re reading through seventeen layers of middleware trying to figure out why a null pointer appeared in a place that, according to the API, should be impossible.

Easy hides complexity. Simple removes it. One is a mask. The other is a cure.

And here’s the twist that makes this painful: making something simple is hard. It requires discipline. It requires saying no. It requires decomposing problems into their actual parts instead of grabbing the nearest hammer and smashing everything into one shape. Simplicity is an engineering decision. Ease is a convenience.

Most teams don’t have the discipline. They have standups and sprints and velocity points, but they don’t have the one practice that actually matters: asking is this simple? before asking is this done?

So they accumulate. Every easy choice adds a thread to the tangle. Every familiar shortcut adds a dependency. Every quick fix adds a special case. And one day, the team is spending 80% of its time maintaining the tangle and 20% building anything new, and everyone wonders why velocity dropped to zero.

It dropped because you paid for easy with simplicity. And simplicity is the only currency that compounds.

The hardest thing in software isn’t learning a new framework. It’s having the discipline to build something that doesn’t need one.

So what do you do? You start by asking different questions. Not what’s the fastest way to build this? but what are the actual pieces here, and can each one stand alone? Not what am I familiar with? but is this tangled? Not can I ship this by Friday? but will someone be able to change this next year without crying?

Untangle your components. Separate your concerns. Make each piece do one thing — actually one thing, not one thing plus a few helpers plus some convenience methods plus a callback for that one weird edge case. Compose simple pieces instead of building complex ones. It feels slower. It’s not. It’s the only thing that’s actually fast, because fast is what happens when nothing is in your way.

The next time someone on your team says let’s just use X, it’s easy, stop. Ask: is it simple? Because easy is how you got into this mess. Simple is the only way out.

Easy is what feels good today. Simple is what still works in five years. Choose accordingly.

FAQ

Q: But doesn't using familiar tools make teams faster?

A: In the first sprint, yes. By sprint twelve, you're spending more time fighting the framework's hidden complexity than building features. Familiarity is a short-term speed boost with a long-term tax. Simple systems stay fast forever because nothing is in your way.

Q: How do I actually make something simple instead of easy?

A: Decompose the problem into independent pieces. Each piece does one thing — not one thing plus helpers plus edge cases. Ask 'can I change this without touching anything else?' If the answer is no, it's tangled, no matter how easy it was to write.

Q: Isn't this just over-engineering?

A: No. Over-engineering is adding complexity you don't need yet. Simplicity is removing complexity you don't need, period. The opposite of simple isn't over-engineered — it's tangled. Most codebases aren't over-engineered. They're under-simplified.

📎 Source: View Source