A deep teal background showing two states side by side — Day 1 with a green DONE checkmark and Day 3 Months Later with a coral question mark asking whether the next engineer can change it without asking the original author.
Engineering Practices, Software Design, Continuous Delivery

"Done" Doesn't Mean It Works. It Means Someone Else Can Change It.

By Shivani Sutreja10 min read

Done in software means the next engineer can change it safely without asking the person who wrote it. A feature that works but only its author understands isn't done — it's a liability with a time delay. The real cost surfaces months later when changes route back through one person and the codebase develops regions nobody will touch.

The feature ships on a Friday. Tests are green, the PR is approved, the ticket moves to Done.

Three months later, a new requirement touches the same code. The engineer who built it is on another team now. The engineer assigned to the change reads the code for forty minutes, writes a careful Slack message — "do you have time to walk me through this before I start?" — and waits two days for a response that arrives in fragments between meetings.

Nobody made a policy that said this was acceptable. This is just what done looks like when it only means works.

The Definition That Fails You

Most teams define done as: the feature works as specified, tests pass, it is deployed to production. That is a reasonable definition for the day of delivery. It says nothing about the day someone needs to extend it, fix it under pressure, or understand it six months from now when the context is gone.

This is not a universal law. An emergency hotfix that restores a downed service can be done without passing any handoff test — the priority was the incident, not future maintainability. A one-off migration script that runs once and is never touched again may not justify that investment. For those cases, working is enough.

But for production software expected to evolve — features, services, modules that other engineers will extend, fix, and build on — working is only the first milestone. A feature is truly done when another engineer can safely change it without asking the person who wrote it. Everything else is a prototype with good uptime.

The gap between those two definitions is where most technical debt actually lives — not in the code that obviously needs cleaning up, which engineers can see and put in the backlog. In the code that works perfectly, ships on schedule, passes all review criteria, and gradually becomes a no-go zone that routes every future change back to the person who originally wrote it.

What the Cost Looks Like

The cost of done-means-works does not surface at delivery. It surfaces in slices, long after the sprint is over.

The engineer who spends three days understanding code that should take three hours. The change that breaks something unexpected because the coupling was invisible to anyone who was not in the original design conversation. The feature that gets rewritten rather than modified because nobody trusts it enough to touch it. The senior engineer who becomes a bottleneck because they are the only person who understands the service that handles payments.

None of these appear on a velocity chart. They compound silently — each one a small tax on the team's ability to move — until the codebase has regions nobody goes near without a guided tour.

At that point the team has what looks like a knowledge distribution problem, a bus factor problem, an onboarding problem. Often the root is simpler: code was marked done before it was truly changeable.

What Changeability Actually Requires

A changeable codebase is not necessarily a perfectly clean codebase. It is a legible one.

Three things make code changeable:

Tests that describe intent, not implementation. A test that verifies the exact sequence of method calls does not protect the next engineer — it locks the implementation in place and prevents the refactoring they need to make. A test that says "given this input, this business outcome should hold" gives them room to move. Tests that assert on implementation details document the current shape of the code. They are not a safety net for future changes — they are a cage around the current ones.

Names that communicate purpose. processData() is a function that does something. calculateMonthlyInstalment() is a function someone can find, understand, and safely ignore or modify without tracing its call chain first. Naming is the cheapest form of documentation and the most durable. The next engineer reads names before they read anything else. What they find there either orients or disorients them for everything that follows.

Boundaries that can move independently. Code that mixes concerns — database calls inside business logic, presentation details leaking into domain models — cannot be changed in one place without rippling into another. The engineer who needs to change the interest calculation should not have to understand the email renderer to do it. Boundaries that can move independently are what make "I just need to change this one thing" actually true rather than a wish.

The Handoff Test

The practical test for done: hand this feature to a different engineer — someone who was not in the planning sessions, did not hear the original context, was not in the PR review — and ask them to make a substantive change. Not a trivial one. A change that requires understanding what the code is doing and why.

If the honest answer is "I would want to walk them through it first" — the feature is done-for-you. That is a different thing from done.

The handoff test exposes something code review alone cannot. Good reviewers absolutely evaluate coupling, naming, test quality, and boundaries — and often that is the main purpose of a review. The gap is not that reviewers miss things. It is that they still possess the context that future maintainers will not have. They were in the same sprint, heard the same requirements, followed the same architectural conversation. They can navigate code a fresh reader could not, because they are not actually reading it cold.

Code review is an incomplete proxy for changeability. The handoff test closes the gap by removing the context advantage entirely.

What the handoff test is actually checking:

  • Can the engineer locate where the change needs to happen in under 15 minutes, without asking anyone?
  • Can they make the change without touching code they were not expecting to touch?
  • Do the tests tell them whether they broke something — or do they have to run the whole application to find out?
  • Would they feel confident deploying, or does the change feel risky enough to warrant the original author's sign-off?

The more of those that are no, the further you are from a feature that can be safely owned by the team.

Done Is a Team Property, Not a Code Property

This reframe matters because it shifts where the responsibility sits.

A definition of done that covers whether the code works puts responsibility on the author: did they implement the spec correctly? A definition that includes changeability puts responsibility on the author, the reviewer, and the team's shared standards: did we produce something the team can work with going forward?

Code that works but cannot be changed is not usually a personal failure. It is a systematic one — of the review process, of what the team considers acceptable, of what good enough means under sprint pressure. The engineer who wrote untouchable code in a hurry did not fail alone. They operated inside a system that said working was enough.

The fix is also systematic. Standards that enforce changeability, not just correctness.

"Tests must pass" is a correctness standard. "Tests must describe business outcomes, not implementation steps" is a changeability standard. "Names must be meaningful" is a correctness standard. "A new engineer should be able to identify the business domain this function belongs to from its name alone" is a changeability standard.

The gap between those pairs is exactly the gap between code that works and code that can be worked on.

Why Good Engineers Create Unchangeable Code

This is worth naming, because the article can otherwise read as: hard-to-change code is written by careless engineers.

That is not what happens.

Most unchangeable code was written by capable people under real pressure. The structural reason it accumulates is simpler: delivery is measured immediately, changeability is measured months later. The incentives are asymmetric.

Teams celebrate shipping. Velocity charts reward points closed. Nobody runs a metric for "how long did it take the next engineer to understand and modify this feature." Nobody gets recognised at a retro for code that a different engineer changed in thirty minutes rather than three days.

The engineer who writes legible code under pressure is doing invisible work. The cost of not doing it is equally invisible — until it surfaces as a bottleneck, a prolonged incident, a feature that needs the original author to change even a small thing.

This is why unchangeable systems are not primarily a skill problem. They are a measurement problem. What gets measured shapes what gets done, and changeability is structurally harder to measure than delivery. The fix has to be structural too — standards and gates that enforce changeability at the point of review, not retrospective cleanup months later.

What This Means at the Margin

None of this requires perfection. Code does not need to be textbook-clean to be changeable. It needs to pass a simpler bar.

Named well enough that the next reader knows what they are looking at. Tested in a way that tells them what should remain true when they are done. Bounded in a way that isolates the change they need to make from the changes they do not.

A feature that meets those criteria can be handed off. One that does not will find its way back to you — during an incident, six months after you have forgotten the context, when the engineer who needed to change it could not afford to wait for a walkthrough.

Done is the word teams use to stop thinking about a piece of work. The question is whether you have earned the right to stop thinking about it — or whether you have deferred that thinking to the next person who needs to change it.

Before marking a feature done, ask:

  • Could a different engineer locate where the next change needs to happen without asking anyone?
  • Do the tests describe business behaviour rather than implementation steps?
  • Can a change be made in one area without unexpectedly touching several others?
  • If you left the team tomorrow, would this feature still be maintainable by whoever takes it on?
  • If the answer to "can someone else change this?" is "let me walk them through it first" — is that a helpful onboarding, or a dependency you have built into the codebase?

These are not boxes to tick. They are questions that surface whether the code is done or done-for-now.

Track how often changes require the original author. If certain engineers get consistently pulled back into work they marked done weeks ago, that is not a communication problem. It is a changeability problem wearing a collaboration hat.

Frequently Asked Questions

What is the real definition of "done" in software engineering?

Done means the next engineer can safely modify the feature without asking the person who wrote it. Not just that it works as specified, but that it can be changed by someone who was not there for the original design conversation. A feature that works but only its author understands is not done — it is a prototype with good uptime.

Collapse

How do you know if code is changeable enough to be considered done?

Expand

Does prioritising changeability slow down delivery?

Expand

What makes tests support changeability rather than prevent it?

Expand

See where your codebase fails the handoff test

Prevention surfaces the patterns that make code hard to change — untestable design, implementation-coupled tests, missing boundaries — at PR time, before they compound into regions nobody will touch.

Get Your Free Diagnosis

Share this article

Help others discover this content

TwitterLinkedIn
Categories:Engineering PracticesSoftware DesignContinuous Delivery