DEV Community

Cover image for I Deleted 200 Lines of Code I Didn't Write and Learned More Than When I Wrote It...
Gamya
Gamya

Posted on

I Deleted 200 Lines of Code I Didn't Write and Learned More Than When I Wrote It...

The illusion of speed in AI-assisted coding

Quick note before we dive in — I know I've been off track from the iOS/Swift series lately. I just have so many thoughts I need to get out of my head first. The series is coming back with the next article, I promise. Okay. Now. Story time.

I was thinking to tell you all about the afternoon I spent deleting code and accidentally learned more than I had in the entire month I spent generating it.

This is not the story I expected to be telling. I went in thinking I was doing a quick cleanup. I came out a different person. Slightly humbled, deeply caffeinated, and with 200 fewer lines of Swift in a file that somehow works better now. Let me explain.


The Part Where I Confess Something

A few weeks ago I was moving fast on a project. Like, embarrassingly fast. Generate, test, accept, move on. Generate, test, accept, move on. The AI was producing stuff that compiled and did the thing I asked and I was just... letting it. Not reading carefully. Not asking questions. Just vibing my way through feature after feature like someone who is definitely not going to regret this later.

Reader, I regretted it later.

Not because it broke. That's the genuinely annoying part — the code was fine. It ran. The features worked. Nobody was complaining. But every time I opened that file I got this low-level anxiety I couldn't quite name, like walking into a room you cleaned by shoving everything into the closet. Technically tidy. Spiritually wrong.

So one afternoon I just... started deleting things. No plan. Just me, a delete key, and a growing sense that I had accepted a lot of code I did not actually understand.


The First Thing That Happened Was I Got Scared

This surprised me. I'm not easily scared by code. But I kept hovering over things going "okay but what if this is the thing holding everything together and I just don't know it yet."

That feeling? That is the exact feeling I never have when I write code myself. When you write something, you carry the map in your head. You remember the night you added that defensive nil check because something exploded in testing. You remember why the function is structured the way it is because you restructured it twice. You have context.

With generated code, the code arrived and the context didn't come with it. The AI made decisions — some of them genuinely good decisions — and I accepted them without understanding why they were the decisions. So now I'm standing here six weeks later, looking at my own project like a stranger, trying to figure out which parts are load-bearing and which are just decoration.

This is exactly as uncomfortable as it sounds.


So I Started Making Predictions

Before I deleted anything, I started asking myself: okay, if I remove this, what do I think breaks? Not what could break in theory. What do I think will happen, specifically.

Some of my predictions were correct and deleting the thing confirmed it was redundant. Good. Simple.

Some of my predictions were wrong in interesting ways. There was a function I was absolutely certain was doing nothing useful — looked like a model just added it out of habit — and when I deleted it, a very specific edge case in a flow I'd half forgotten about quietly fell apart. Turns out the function was handling a nil that could only show up under a particular sequence of user actions I didn't immediately remember building.

That function taught me something I did not know I didn't know. Which is the most annoying kind of learning, but also the most useful.


The Final Score

200 lines gone. Some of it was genuinely redundant — duplicated logic, defensive checks for situations that couldn't actually happen, a helper function called exactly once that could have just been one line where it was used. The kind of thing that gets added by something being thorough, not by something that knows what your specific project actually needs.

Some of it I rewrote from scratch. Not because the original was wrong. Because rewriting it meant I finally owned it. There's a difference between code you're managing and code you understand, and I needed to close that gap before I could trust myself to work on it properly.

Some of it I kept exactly as it was. Because staring at the empty space after I tried to delete it made me realize it was doing something I actually needed, and I just hadn't been paying enough attention to appreciate it. Those were the most useful deletions of all, actually — the ones where I tried to get rid of something and the project said "no, you need that, let me show you why."


What I Learned That I Didn't Expect to Learn

Here's the thing nobody tells you about generating code quickly: the velocity is real but it has a price that doesn't show up on the day you shipped the feature. It shows up later. It shows up when you need to change something, or debug something weird, or explain the thing to someone else, or just open the file six weeks later and feel that closet-full-of-junk anxiety.

Every line you accept without understanding is a small loan. The interest compounds quietly until you need to touch the thing again.

Deleting code — actually reading it carefully enough to have an opinion about whether it should exist — is one of the weirdest and most effective ways to pay that debt down. You can't delete something without understanding it well enough to argue for or against it. Which means by the time you're done, you've been forced to actually learn the codebase you thought you already knew.

I came in for a cleanup. I got an education. Slightly against my will, but still.


The Part Where I Tell You What I'm Actually Doing Differently Now

I haven't stopped using AI to generate code. That would be a dramatic overreaction and also I have deadlines. But I've started treating accepted suggestions like debt I'm choosing to take on, not like code I wrote. Because the moment I need to touch it again, I need to understand it — and if I never read it carefully, that understanding isn't there just because I was in the room when it was generated.

So now, every once in a while, I open a file I generated fast and haven't looked at closely since. I read it like it's someone else's code. I try to delete things. I make predictions about what I think will break, and then I see if I'm right.

Sometimes I am. Sometimes I'm wrong in exactly the ways that teach me something.

Either way, I come out knowing the codebase better than I did going in.

Which is, genuinely, more than I can say for the afternoon I generated it.


AI tools were used to help with grammar and structure.

Top comments (68)

Collapse
 
alexshev profile image
Alex Shev

Deleting unfamiliar code is one of the fastest ways to learn the real architecture. Writing code teaches the intended path; removing code tests whether the path was actually necessary. The scary part is that the best refactor often looks like doing less, which is harder to defend than adding another abstraction.

Collapse
 
gamya_m profile image
Gamya

"Harder to defend than adding another abstraction" is so true and I think it's why so much unnecessary complexity survives — adding something looks like work, removing something looks like you didn't do anything, even when the removal required more understanding than the addition ever did. The deleted code post literally involved an afternoon of careful reading and reasoning and the output was fewer lines, which is a very hard thing to point to in a standup as evidence of productivity. But the codebase is cleaner and I actually understand it now, which is worth more than whatever I would have shipped in the same afternoon by generating more.

Collapse
 
alexshev profile image
Alex Shev

Exactly. Removal is hard to defend because the visible artifact is absence. The work shows up later as fewer branches to reason about, fewer assumptions to preserve, and fewer places where a future change can break. But in the moment, it can look like negative productivity unless the team values understanding as an output.

Thread Thread
 
gamya_m profile image
Gamya

"Understanding as an output" is the framing that most teams don't have language for, which is why removal is so hard to defend in the moment — the usual outputs are features, fixes, or improvements you can point to, and understanding doesn't show up on any of those lists even though it's what makes all of them possible. The absence artifact problem is real too. Fewer lines, fewer branches, fewer assumptions to preserve — all of that is genuinely valuable and completely invisible until the moment someone needs to make a change and it goes smoothly instead of being a week-long archaeology project. The value is in what doesn't happen, which is the hardest thing to get credit for.

Thread Thread
 
alexshev profile image
Alex Shev

That is the missing vocabulary. Teams can celebrate output they can demo, but they rarely count understanding as something delivered. Yet a codebase with fewer branches, fewer rumors, and fewer forbidden zones is very real progress. It just needs a better artifact than a line-count delta.

Thread Thread
 
gamya_m profile image
Gamya

"Better artifact than a line-count delta" is the unsolved problem honestly — because the value is real but the representation is missing, and without a representation it doesn't show up in sprint reviews or retrospectives or anywhere decisions about how to spend time get made. A codebase with fewer forbidden zones and fewer rumors is genuinely more valuable than one that shipped two more features at the cost of two more load-bearing mysteries, but there's no metric that captures that and most teams don't have the language to even argue for it. The deletion afternoon produced understanding that I'll carry forward for as long as I work on that code, and there's no field in any tracking system where that goes.

Thread Thread
 
alexshev profile image
Alex Shev

That missing representation is the whole management problem. Teams often know deletion and understanding created value, but the value does not fit the usual artifact slots. Maybe the artifact is not a metric at all; maybe it is a short decision record: what uncertainty was removed, what future change is now safer, and which forbidden zone is no longer private knowledge.

Thread Thread
 
gamya_m profile image
Gamya

A decision record framing makes a lot of sense actually — because the value of that deletion afternoon wasn't a number, it was a set of things I now know that I didn't before, and a short record of what uncertainty got removed and what's now safer to change is actually a much more honest representation of that than any metric would be. It also doubles as the thing the next person needs when they open that file, which means the artifact of understanding the code becomes documentation for whoever inherits it. That's a much better output than a line-count delta and it actually persists in the codebase rather than disappearing into a sprint review.

Thread Thread
 
alexshev profile image
Alex Shev

Right, the value is often in future debugging. A decision record does not need to be heavy; it just needs to preserve what was known, what was assumed, and what would make the decision worth revisiting.

Thread Thread
 
alexshev profile image
Alex Shev

That artifact is the compounding part. A deletion session that only leaves a smaller diff is easy to undervalue. A deletion session that leaves a decision record gives the next maintainer a map of what became safer and what is still unknown.

Thread Thread
 
gamya_m profile image
Gamya

"What was known, what was assumed, and what would make the decision worth revisiting" — that's the minimal viable decision record right there, and it's so much lighter than what most people imagine when they hear "documentation." Three fields, none of them requiring prose or ceremony, but all of them answering the exact questions the next person debugging at 2am actually needs answered. The heavy version of documentation often gets skipped entirely; something that light might actually get written.

Thread Thread
 
gamya_m profile image
Gamya

The "what is still unknown" part is what makes the record genuinely useful rather than just retrospective — because a map that only shows what was resolved is half a map. Knowing what got cleaned up tells you what you can touch confidently. Knowing what's still uncertain tells you where to slow down, which is at least as valuable and much harder to reconstruct from a diff alone. A deletion session that leaves both is worth significantly more than one that just leaves fewer lines.

Thread Thread
 
alexshev profile image
Alex Shev

Exactly. The unresolved list is what keeps the cleanup honest. Without it, a deletion note can accidentally become a confidence story instead of a map for the next person who touches the code.

Thread Thread
 
gamya_m profile image
Gamya

"Confidence story instead of a map" is exactly the failure mode — because a deletion note that only records what got resolved reads like closure, which feels satisfying but leaves the next person with no signal about where the remaining uncertainty lives. The unresolved list is what makes it a working document rather than a retrospective, and a working document is actually useful when something breaks three months from now. 🌸

Thread Thread
 
alexshev profile image
Alex Shev

Yes. The unresolved list is what keeps the note operational. Without it, the cleanup record becomes a victory lap, and victory laps are not very useful when something breaks later.

The future reader needs to know where confidence ended. A short unresolved section says, "we made this call, but here are the edges we did not prove." That is honest engineering context.

Thread Thread
 
gamya_m profile image
Gamya

"Where confidence ended" is exactly the information that's missing from most documentation, because documentation tends to record what was decided and why, not where the decision ran out of certainty. The unresolved section is honest in a way that's actually rare, it's saying here is what we know, and here is where we stopped knowing, and that boundary is just as important as the decision itself. A future reader who knows where confidence ended can calibrate appropriately. A future reader who only sees the decision has no way of knowing how much weight to put on it.

Collapse
 
mnemehq profile image
Theo Valmis

Deleting it is usually the fastest way to actually understand a system, because you find out what depends on it in a way reading never surfaces. Curious whether any of those 200 lines turned out to be quietly load-bearing in a way the tests didn't catch.

Collapse
 
gamya_m profile image
Gamya

Yes, actually — and it was exactly the category that tests don't catch well. There was a defensive nil check that looked redundant on paper, handled a condition that seemed impossible given the current flow, and turned out to be protecting against a sequence of user actions that was technically reachable but only under a specific set of steps I'd half-forgotten I'd built. The tests didn't catch it because the tests were written for the happy path and the common edge cases, not for that particular sequence. Deleting the check and then tracing what actually broke was the only way to understand why it was there, which is a much more complete kind of understanding than reading the check and assuming it was probably defensive boilerplate. The ones that turn out to be load-bearing are genuinely the most valuable deletions, even if they end up getting put back.

Collapse
 
forwardava profile image
Oscar Garcia

Hi Gamya.
This really connected with me. I think many developers have experienced this feeling but don't always talk about it. The speed that AI gives us is amazing, but sometimes we forget that understanding the code is still our responsibility.

I especially liked the part about "code arriving without the context." That is so true. When we write code ourselves, every decision has a story behind it. We remember why we made a choice. But with generated code, we can easily become a stranger to our own project.

I also believe deleting code is one of the best ways to learn. It forces us to ask questions: Why does this exist? Do I really need this? What happens if I remove it? Those questions help us become better engineers, not just faster ones.

AI is a powerful tool, but it should help us think deeper, not make us stop thinking. The best developers in the AI era will not be the ones who generate the most code, but the ones who understand, improve, and take ownership of the code they create.

Thanks for sharing this experience. It is a good reminder that sometimes slowing down for a moment helps us move faster in the long run. 👏

Collapse
 
gamya_m profile image
Gamya

"We can easily become a stranger to our own project" is such an accurate way to put it — and the strange part is it happens gradually enough that you don't notice until you open a file and feel that low-level unease that's hard to name. You shipped it, you own it, and somehow it still feels like someone else's work.

The three questions you listed — why does this exist, do I really need this, what happens if I remove it — are exactly the ones that a read alone won't force you to answer, because reading lets you nod along without committing to a position. Deletion makes the question unavoidable in a way that's uncomfortable and useful at the same time.

"The best developers in the AI era will be the ones who understand, improve, and take ownership" — I think that's right, and I'd add that ownership is the part that's hardest to fake. You can generate code that looks owned, but the moment something breaks in an unexpected way, the difference between understanding and having been in the room when it was generated becomes very obvious very fast.

Collapse
 
technogamerz profile image
𝐓𝐡𝐞 𝐋𝐚𝐳𝐲 𝐆𝐢𝐫𝐥

Hey Gamya! Hope you are doing well

This was such a refreshing read. It's funny how we often measure progress by how many lines we write, but sometimes the biggest win is realizing that fewer lines can actually mean better code.

I really liked how you focused on understanding the why before making changes. Deleting code you didn't write takes confidence, but it also takes patience and respect for the person who wrote it. That balance is something many developers learn only after making a few painful mistakes.

It reminded me that good engineering isn't about adding more—it's about making things simpler, clearer, and easier for the next person (or future you) to understand. Thanks for sharing this lesson in such a relatable way. 💙

And one more thing... I have to say this 😄. You haven't been posting your Swift articles lately, and it honestly feels like eating food without salt. But no pressure at all—post whenever you get the time. I'll be looking forward to reading them whenever they arrive!

Collapse
 
gamya_m profile image
Gamya

Hey! Sorry for the late reply, got a bit caught up with things this week! 😊 And thank you so much for this — "making things simpler, clearer, and easier for the next person" is exactly the standard I was trying to hold myself to, and you put it better than I did in the post itself.

Also haha the Swift articles without salt comment 😄 You're absolutely right, I've been on a bit of a general writing detour but the Swift series is coming back very soon — actually already have the next one lined up. Don't worry, the salt is coming! 🌸🚀

Collapse
 
alexshev profile image
Alex Shev

Deleting unfamiliar code is one of the fastest ways to learn the real architecture. You discover which abstractions are load-bearing, which comments are decoration, and which complexity exists only because nobody wanted to touch it. AI-generated code makes that cleanup skill even more important.

Collapse
 
gamya_m profile image
Gamya

"Which complexity exists only because nobody wanted to touch it" is the category I found most interesting honestly — because it's not wrong exactly, it's just accumulated caution. Someone decided at some point that this thing was too risky to simplify, and then the decision got inherited by everyone who came after them without the original context for why it was scary. Deleting it forces you to either validate that the fear was justified or discover that it wasn't, and both outcomes are more useful than the inherited avoidance.

The AI-generated version of this is a bit different because the complexity doesn't come from accumulated caution, it comes from the model being thorough in ways that don't reflect the actual constraints of your specific system. Defensive checks for conditions that can't occur, helper abstractions that exist because they're good practice in general rather than necessary here. That kind of complexity is weirdly harder to delete because it looks responsible, and you have to understand the system well enough to know that the responsibility is misplaced.

Collapse
 
alexshev profile image
Alex Shev

That distinction between inherited caution and generated thoroughness is sharp.

Old complexity often has history behind it, even if the history is missing. AI-generated complexity can look equally responsible while having no local reason to exist. The review question changes from 'is this good practice?' to 'what specific failure in this system is this protecting us from?'

Thread Thread
 
gamya_m profile image
Gamya

"What specific failure in this system is this protecting us from" is the right question and also the harder one — because good practice in general is easy to verify, you just check it against a standard. But whether this defensive check is protecting against a real failure mode in this specific system requires you to actually understand the system, which is exactly the understanding that wasn't transferred when the code was generated.

The review surface looks the same either way. Inherited caution and generated thoroughness both produce code that looks responsible, handles edge cases, adds defensive checks. The difference is that one of them has a reason that lives somewhere in the history, even if you have to go find it, and the other has a reason that lives in the model's training data and may have no relationship to your actual situation at all. That's a genuinely different kind of thing to evaluate and I don't think most review processes are set up to catch it.

Thread Thread
 
alexshev profile image
Alex Shev

That is the review failure in a nutshell. A defensive check can look responsible whether it came from scar tissue or autocomplete. The only way to tell is to ask for the local failure story. If nobody can name the failure, the check may still be useful, but it should not get the same trust as code that was shaped by a real incident.

Thread Thread
 
gamya_m profile image
Gamya

"Ask for the local failure story" is the right test and also the one that most review processes don't have a step for — because the check looks responsible either way, so there's no obvious prompt to ask where it came from. Scar tissue and autocomplete produce code that's visually identical, and the only thing that distinguishes them is the story behind it, which you have to actively ask for rather than read off the diff. The trust differential makes sense too — a check that survived a real incident has been validated by something that actually happened, whereas a check that arrived from thoroughness is a hypothesis about what might happen, and those two things shouldn't carry the same weight even when the code looks the same.

Thread Thread
 
alexshev profile image
Alex Shev

That distinction between scar tissue and hypothesis is the key. Both can produce responsible-looking code, but they deserve different confidence. A real incident gives the check provenance. A generated or speculative check may still be useful, but it should carry a lower trust level until the team can tie it to a concrete failure mode.

Thread Thread
 
gamya_m profile image
Gamya

Provenance is exactly the right word for what the incident gives the check — it's not just that the check exists, it's that you can trace it back to a specific thing that happened, which means you can also reason about whether that thing can still happen, whether the check is still in the right place, and whether it needs to change if the system changes. A speculative check has none of that lineage, so you can't reason about it in the same way. You can only treat it as "probably useful" until something either validates or invalidates it, which is a much weaker foundation to build on even when the code looks identical. The trust differential isn't about the code, it's about what you can know about the code. 🌸

Thread Thread
 
alexshev profile image
Alex Shev

Yes. Provenance changes whether a check is knowledge or superstition. Two checks can look identical in code, but one has a failure story attached and the other is just a plausible fear. Without that lineage, future maintainers cannot know whether removing it is cleanup or amnesia.

Thread Thread
 
gamya_m profile image
Gamya

"Cleanup or amnesia" is such a precise way to describe the decision a future maintainer has to make without the lineage — and the problem is that both look identical from the outside. A check with no story could be defensive boilerplate that never needed to be there, or it could be the thing standing between you and a production incident that happened three years ago and nobody remembers. Without provenance you can't tell, which means you either leave everything in out of fear or delete things and find out the hard way. Neither is a good way to work with a codebase. The lineage is what makes that decision possible to make confidently rather than just hopefully. 🌸

Thread Thread
 
alexshev profile image
Alex Shev

That is the danger zone. Removing code is easy to celebrate, but the useful question is whether you removed accidental complexity or erased the map of why the system behaved that way. Cleanup needs memory too.

Thread Thread
 
alexshev profile image
Alex Shev

That uncertainty is what makes deletion work emotionally hard too. Without lineage, removing code feels like gambling against forgotten incidents. A small note that says why the check existed and why it is safe to remove changes the whole maintenance decision.

Thread Thread
 
gamya_m profile image
Gamya

"Cleanup needs memory too" is such a good way to put it — because the celebration of removing lines can quietly skip over the question of whether what got removed was complexity the system no longer needs or complexity that was load-bearing in ways that weren't obvious. The deletion afternoon worked because I forced myself to understand each thing before removing it, which meant the memory was being built at the same time as the code was being deleted. Removing without understanding first is just replacing one kind of debt with another.

Thread Thread
 
gamya_m profile image
Gamya

"Gambling against forgotten incidents" is exactly the feeling — and it's not irrational caution, it's the correct response to genuinely not knowing whether the thing you're about to remove was defensive boilerplate or the last line standing between you and a bug that happened three years ago. The note changes the decision from a gamble to an informed call, which is a completely different kind of confidence. It also means the next person who looks at the deletion in git history has something real to read instead of just "removed dead code" and a prayer.

Thread Thread
 
alexshev profile image
Alex Shev

Right. The useful outcome is not just a cleaner codebase, it is a safer future decision. A short note can turn the next cleanup from archaeology into a bounded engineering call.

Thread Thread
 
gamya_m profile image
Gamya

"Bounded engineering call" vs archaeology is the right contrast — because archaeology requires reconstructing the whole context from scratch every time, while a bounded call just needs you to read the note and decide within a known set of constraints. The difference in cognitive load is enormous, and it compounds every time someone touches that part of the code. A short note written once pays out on every future decision that references it.

Thread Thread
 
alexshev profile image
Alex Shev

Yes, that compounding effect is the reason I care about small notes so much. The note does not need to capture the whole history. It just needs to keep the next decision from starting at zero.

A bounded call is much easier to revisit than a mystery. Even if the future engineer disagrees, they have something concrete to push against instead of rebuilding the entire context from scattered clues.

Thread Thread
 
gamya_m profile image
Gamya

"Something concrete to push against instead of rebuilding the entire context from scattered clues" is the key thing a small note provides, and you're right that disagreement is actually fine, maybe even good. A future engineer who reads the note and decides the reasoning no longer holds is in a much better position than one who deletes something without knowing there was reasoning at all. The note doesn't have to be right forever, it just has to give the next decision a starting point that isn't zero. That's a low bar to clear and a high return on the effort.

Collapse
 
embernoglow profile image
EmberNoGlow

AI is just a tool; you shouldn't use it as a replacement for yourself. I know that feeling all too well. AI only creates the illusion of fast coding, but it's not. Coding isn't just lines of text. It's the logic of a program. A workflow. If you don't understand how a program works, you're not the author of that code. You're just accepting the role of a copy-paste agent asking an AI to do everything for you (I didn't mean to offend anyone, btw). True programming is converting your thoughts into code. You should control the agent, not let it make decisions for you. Otherwise, how is your code different from something on a GitHub repo from someone else? You'll still have to understand it.

I'm not saying stop using AI. I'm just saying that you should know how a program's main loop works and be able to explain it to an AI. Knowing the syntax isn't as important as design. Decision making is your responsibility. Blindly trusting AI can lead to poor architectural decisions.

Collapse
 
gamya_m profile image
Gamya

"You're not the author of that code, you're just accepting the role of a copy-paste agent" — that line is uncomfortably accurate for what I was doing during that fast-moving stretch, and I think the discomfort I felt opening the file weeks later was exactly that: the gap between being the person who shipped it and being the person who understood it had gotten wider than I'd admitted to myself.

The distinction you're drawing between syntax and design is the one I keep coming back to. Syntax is the part that's most obviously replaceable — the AI is genuinely better at remembering the exact API call than I am, and I'm fine outsourcing that. But design is the part where the decisions compound. A bad architectural call made in minute two of a feature is still there in month six, except now it's load-bearing and surrounded by other things that assumed it was correct. That's not something the AI can take responsibility for because it doesn't live with the consequences the way the codebase does.

"You should control the agent, not let it make decisions for you" is probably the clearest version of the principle I've seen written down. The deletion exercise was basically me discovering, after the fact, which decisions I'd silently let the agent make. Would have been better to catch them in the moment. 🌸

Collapse
 
espoirsamah profile image
HopeGeek

Exactly.

Collapse
 
itskondrat profile image
Mykola Kondratiuk

deletion is actually the best code review. you can't skim what you're removing

Collapse
 
gamya_m profile image
Gamya

That's exactly it — reading lets you skim because your brain fills in what it expects to see, but deletion forces a verdict. You can't half-delete something, you either remove it or you don't, and making that call requires actually understanding what it does. The delete key is the strictest reviewer on the team.

Collapse
 
itskondrat profile image
Mykola Kondratiuk

the "verdict" framing is the right one. most review feedback hedges — "consider extracting," "might be cleaner as" — but delete forces binary commitment. that binary is where understanding actually happens.

Thread Thread
 
gamya_m profile image
Gamya

The hedging in review feedback is so real — and I think it's partly because suggesting a change is low stakes, you're not committing to anything, you're just raising a possibility. Delete is the opposite of that, it's a committed position that you then have to live with. There's no "consider removing" version of the delete key, you either did it or you didn't, and that irreversibility is exactly what forces the understanding that softer feedback lets you skip.

Thread Thread
 
itskondrat profile image
Mykola Kondratiuk

Irreversibility is the mechanism. A suggestion is deniable after the fact — you only raised it as an option. Delete leaves a diff with your name on it. That accountability is what makes it uncomfortable, and also what separates a real review from a consultation.

Thread Thread
 
gamya_m profile image
Gamya

"A suggestion is deniable after the fact, delete leaves a diff with your name on it" — that's the exact distinction between a review and a consultation, and I think a lot of what passes for code review is actually consultation dressed up as review. You raised concerns, you noted possibilities, technically you did the review. But nobody committed to anything, nobody's name is on a position, and the ambiguity stays in the code because the review never forced anyone out of it. Delete can't do that. The diff is the receipt.

Collapse
 
eduzsh profile image
Edu Peralta

This matches something I see constantly running a few coding agents at once. I had an agent clean up what looked like a dead validation branch last month, and that branch was quietly catching a timezone edge case from an old support ticket nobody remembered. The diff summary called it dead code. It wasn't. Your loan metaphor is right, and the interest rate climbs the more agents you run in parallel, because each one hands you a summary of what it did instead of proof of what it touched.

Collapse
 
gamya_m profile image
Gamya

The timezone edge case one is exactly the kind of thing that keeps me up at night honestly — because dead code is such a reasonable thing to clean up, the agent's reasoning was completely sound, and the summary probably looked totally fine. There was no obvious signal that anything was wrong until the specific condition that branch was quietly handling showed up again. That's the worst category of miss because it passes every sanity check you'd normally run.

The parallel agents point is something I hadn't thought about directly but it makes total sense — the interest compounds because each agent's summary is one more layer of abstraction between you and what actually happened. With one agent you're already trusting a diff over a read. With several running at once you're trusting summaries of diffs, and the gap between what got touched and what you understand got touched keeps widening with every layer. The loan metaphor breaks down a little there actually, because at least with a loan you know how much you borrowed. With parallel agents you might not even know what decisions got made on your behalf until something surfaces that doesn't behave the way you expected.

Collapse
 
raffy_d profile image
Raffy

I think we are all guilty of just vibing away at one point or another. That's why it's also important to also zoom out at times and make attempts to re-evaluate your understanding of the code when doing AI assisted coding. Not even the actual code, but just how everything works under the hood.

Plus, don't do AI assisted coding when you're tired lol! Learned that the hard way. Seems you need a break too!

Collapse
 
gamya_m profile image
Gamya

"Don't do AI assisted coding when you're tired" is genuinely underrated advice that nobody puts in the tutorials 😂 Tired-me has a much lower bar for "this looks right" and a much higher tolerance for accepting things without reading them, which is exactly the wrong combination when the tool is producing confident-looking output that might be quietly wrong. The acceptance rate goes up and the scrutiny goes down at exactly the same time. Bad deal.

The "zoom out and re-evaluate how everything works under the hood" point is the one I keep coming back to too — it's easy to stay at the surface level of "does the feature work" and never check whether the way it works makes sense for the system around it. The deletion exercise basically forced me to zoom out because I couldn't delete things confidently without understanding the bigger picture first. Accidental architecture review. 😄🌸

Collapse
 
alexshev profile image
Alex Shev

Deleting generated code is one of the best learning loops because it forces you to identify the actual boundary. Writing can hide uncertainty; deletion exposes it. If you can remove 200 lines and explain why the system got clearer, you probably learned more than if you had accepted another generated patch.

Collapse
 
gamya_m profile image
Gamya

"Writing can hide uncertainty, deletion exposes it" is such a clean way to put the difference — when you're writing or accepting code you can stay in the comfortable zone of "this seems right" without ever having to commit to why. Deletion won't let you do that. Every line you remove is a position you're taking, and every line you decide to keep is also a position, and both require you to actually know what you're talking about in a way that passive acceptance never does.

The "explain why the system got clearer" bar is a good one to hold yourself to as well — if you can't articulate what got better and why, you might have just made it smaller rather than actually cleaner, which are not the same thing. The 200 lines I removed made sense to me precisely because I could say what each category of deletion was doing, and having to find that explanation was most of the learning.

Some comments may only be visible to logged-in visitors. Sign in to view all comments.