Yueseryueser.com

← All workflows

Taking over an unmaintained legacy project: where do I start?

The risk in legacy code is not that it is ugly. It is that you don't know what you just changed. Read first, assess second, change last.

How to do it

  1. Understand one unfamiliar module through its data flow

    Paste one module at a time into 'Understand unfamiliar code'. Have it state in one sentence what the module does, then follow the data: where input comes from, what transforms it, where output goes. Ask for the two or three places that are easiest to misread. Do not ask for a line-by-line translation; draw your own call graph as you go, because you will reuse it.

  2. Map the boundaries and the single points of failure

    Give the system name, how it is deployed, and its main external dependencies to 'Breaking Down a Complex System'. Draw what is inside and outside, list inputs, outputs, and goals, split it into three to six subsystems with their interfaces, and mark bottlenecks and single points of failure. Then walk one real scenario through it and note the steps you would have missed.

  3. Find the most dangerous code first

    Take the riskiest module from step 2 and paste it into 'Code review'. Ask only for bugs, security issues, and performance problems, ordered by severity, each with a trigger condition and a concrete fix. This list decides which part gets tests next, instead of spreading effort evenly.

  4. Check what the tests actually cover

    For the dangerous module identified in step 3, give the implementation and existing tests to 'Find the gaps in your tests'. Legacy projects often have tests that assert implementation details rather than behavior. List uncovered branches, pick the top five cases by production impact, and delete duplicate or internals-coupled tests. The tests should protect the part you are about to change.

  5. Assess whether a dependency upgrade will bite

    Give the dependency name, current and target versions, and how many call sites you have to 'Dependency upgrade risk assessment'. Keep only the breaking changes that your code actually calls, split them into must change, should change, and can wait, and ask for an upgrade order plus a way to verify locally. Upgrade one dependency at a time.

Prompts used

FAQ

Should I rewrite the legacy project or add tests first?

Neither, not yet. Read the boundaries and data flow, find the genuinely dangerous parts, then add tests around those. A scattershot rewrite and evenly spread tests both spend time on low-risk code while the parts that actually fail stay unprotected.

The old code has no docs. Can AI write them?

Partly, but what you get is behavior inferred from code, not the original design intent. Mark those inferences as unconfirmed and check them against former maintainers or the commit history. Treating them as fact sets up the next person to repeat the same mistakes.

The dependencies are years old. Should I upgrade everything at once?

No. Upgrade in batches by how much you call, one dependency at a time, with tests passing in between. When you cross several major versions, check which breaking changes your code actually hits; the rest can wait. Upgrading everything at once makes it impossible to tell which change broke what.