Delete your code
In the world of modern software, code has become a curious thing. As developers, we spend hours carefully crafting it (ok, nobody has ever accused me of writing carefully crafted code but YMMV and presumably you are a better person than me), but before we know it, those lines that seemed so perfect last month are marked for deletion. Code is–and should be–considered a transient artefact, one that’s often changed, rewritten, or preferably removed altogether. Rather than fighting this reality, we should embrace it. Instead of aiming to write perfect, immortal code, let’s focus on writing code that’s easy to delete. At the end of the day, nothing says “I’ve grown as a developer” like welcoming the opportunity to delete some of your old code with a big smile on your face. Don’t think of it as destroying something precious, think of it as clearing out the weeds while tending your garden.
So let’s dig into some basic principles for writing code that’s not only easy to use and understand but also easy to part with when the time inevitably comes.
Repeat Thyself
“Don’t Repeat Yourself” has been drilled into most developers as a golden rule. And while it’s usually sound advice, the goal isn’t to avoid repeating yourself at all costs. In fact, software development requires a more flexible approach—one where you can repeat a little to keep things decoupled. If a small piece of code is better off repeated to keep it independent from other parts, go for it. What you gain is simplicity, reduced dependencies, and less risk of accidentally unraveling a spider’s web of connections every time you change something.
But let me be very clear: this isn’t a green light to go duplication-happy[1]. It’s more about picking your battles with dependency management. Selective repetition–emphasis on SELECTIVE–is the key. Don’t repeat yourself just to dodge dependencies, but when repetition helps keep things decoupled and isolated, it’s worth it. And no, this doesn’t mean copy-pasting every line of code just because you can[2].
Cake-like Code
Good codebases have layers, and layering is an art. Think of your code as an onion: the outer layers are simple, user-friendly interfaces built on top of clunky, unrefined foundations. You start with the basics—those raw data processing functions, algorithms, or internal protocols that get the job done but aren’t exactly easy to work with directly.
Then, you wrap those basics in a clean, simple and (for the love of all that is unholy) versioned API that shields users from the ugliness below. This layering lets you contain complexity without exposing it to the world, like a nice jacket that hides your laundry-day shirt. The result is twofold: your core code remains robust and reusable, and any future tweaks or deletions can be handled at the API level, sparing the guts of the system from upheaval.
By layering this way, you’ve made deletion less of a heart-stopping affair, where you risk tearing down the whole system. Instead, each layer insulates the next, making it easier to adapt, evolve, or (yes) delete when the time comes.
Split And Isolate It
Some code is hard to write, while other parts are a ticking clock, waiting to be updated, altered, or swapped out. Mixing the two is like putting a sandcastle next to the waves. Instead, isolate the pieces that were a real bear to get right (and that you want to keep stable) from the parts that are bound to evolve over time. You’re effectively separating your “rock” code from your “sand” code[3].
Why does this help? For one, it makes deleting or replacing the likely-to-change pieces far simpler since they’re not tangled up with complex, mission-critical calculations or operations. Isolating the “hard” code also shields it from the constant churn of updates, meaning that when you’re inevitably tempted to delete the change-prone code, the foundational parts can stay intact.
Some Code Paths Are More Equal Than Others
Ah, flexibility—the temptation to make every single thing configurable. It’s nice in theory, but too much flexibility can be a recipe for chaos. Overly configurable code can be tough to follow, but overly rigid code locks you into one option, like a single road trip playlist with no skips. So aim for moderation: make a few key choices flexible, particularly the ones related to runtime decisions or configuration options, and hard code the rest.
A small amount of flexibility obviously goes a long way. For instance, instead of hardcoding the data source, make it an option that can be set at runtime–this should be obvious to everyone at this point. However you might want to allow for some runtime configuration of features that are likely to change, but don’t go crazy and leave every single possible configuration option wide open. Too much configurability can leave you with code that’s as tangled as a choose-your-own-adventure book[4].
Do Less - Write Less
Occasionally I feel like I may be kicking in open doors and but here I fear it can’t be helped: less is–more often than we might think–more. In our particular case: when writing code, it’s tempting to think, “I’ll just cover all the bases I can come up with right now and save time later5.” But complex solutions are much harder to delete, significantly harder to understand, and frankly, far harder to love. When we write more code than necessary, we’re setting ourselves up for systemic debt and future headaches.
Therefore, write with restraint. Solve today’s problems, and don’t worry too much about tomorrow’s hypotheticals and the paranoid corner cases invented by your most wild eyed colleagues[6]. If you’re building a system with deletion in mind, less IS genuinely more. Write only what you need to, and keep your focus on simplicity. In the end, code that’s essential is far easier to part with than code that was created “just in case.” And here’s the paradox: the less code you write, the less code you have to maintain. Less maintenance, fewer dependencies, and fewer worries about hitting delete down the line.
Write Delete-Friendly Code
The ultimate goal isn’t to write perfect, timeless code. Rather, it’s to write code that’s flexible, decoupled, and easy to let go of when it’s time. By repeating yourself where needed, layering your code, isolating parts that are bound to change, and avoiding excessive configurability, you create a system that’s adaptable and light on its feet. And if that means writing less code in the first place, all the better.
So next time you sit down to code, think of the delete option not as an enemy but as an essential ally, your best friend[7]. And remember, in a world where requirements shift and codebases evolve, the best code is often the kind that’s easy to say goodbye to when its job is done.
It’s more of a orangish yellow?
Tempting as it may be to copy-paste, remember, that way lies madness.
Castles made of sand can look great, but they fall into the sea. Eventually. See also the work of PhD J Hendrix on this particular subject.
Only real adventurers choose every option. And they’re usually dead before reaching the final boss.
Or as one of my former colleagues used to call it: “Jam tomorrow”.
You know the one, the person who invents their own conspiracy theories because the normal ones aren’t crazy enough.
Your… precious.