Make code changes reviewable and recoverableLESSON 3.01 · 1 OF 14 IN CHAPTER
PART A / AI-assisted code changes
Step 71 of 252
LESSON 3.01 · 1 OF 14 IN CHAPTERGUIDED READING

Make code changes reviewable and recoverable

A shop stores prices in cents. A developer needs to fix a discount so an item priced at 1999 cents with a 200-cent discount costs 1799 cents. The same patch also renames files and removes a database column. If checkout breaks after release, those unrelated changes make the cause and recovery path harder to identify.

You will separate a coherent behavior change from unrelated work, write the reason beside the patch, and distinguish reverting source code from recovering data or external effects.

Project connection · feeds Reading-list stage 1: build the reading-list application

Compare the patch with the behavior being requested

- return price_cents - discount_percent
+ return price_cents - discount_cents

This illustrative patch changes one unit mismatch. It is not sufficient by itself: the caller must actually pass a discount in cents, and invalid or excessive discounts need a defined policy. A useful review description says: “The caller provides a 200-cent discount. The handler treated that value as a percentage field. This change uses the agreed cents value and preserves the existing total representation.”

Proposed work Include with this repair? Reason
Correct discount calculation and its caller Yes Implements the named behavior
Demonstrate 1999 minus 200 returns 1799 Yes Shows the observable result
Rename unrelated logging modules Separate change Does not explain or repair the discount
Delete a column still used by old code Separate staged migration Requires its own compatibility and recovery plan

A Git commit records a source change. A database commit records a transaction's stored changes. A successful Git revert does not undo database writes already performed by the released code.

Reason through the changed situation

“A checkout fix also renames thirty files and removes a database column. Ten percent of checkouts now fail. Make the next change easy to review, diagnose, and recover from.”

Start with one observable behavior: 1999 - 200 = 1799 cents. Keep an unrelated rename separate. Record the reason for each change, not just what the diff contains.

Diagram: Reason through the changed situation

Follow the mechanism and its limits

A change moves through edit, commit, review, merge and execution; production observations feed the next change.

A commit records a coherent change and its reason. A pull request explains its behavior, risks and checks. Merging records the decision; running and observing the result completes the loop.

Small batches make review and diagnosis easier. They do not guarantee low risk or safe rollback: DROP TABLE orders is one line. Undoing that line in Git does not recover the orders.

Recovery question Evidence to require
Can the code revert cleanly? Apply the revert on a branch and run checks
Can old code read new writes? Test schema and protocol compatibility
Can we recover deleted data? Restore from a tested backup/recovery path
Have effects already escaped? Reconcile or compensate payments/events
Diagram: Follow the mechanism and its limits

the new version writes a field the old version ignores. A rollback may work, but only if old readers can still interpret every required value. Check that contract rather than assuming that a small diff is reversible.

Refactor or behavior change?

A refactor preserves the supported observable contract. Test imports, fixtures and structure may need to move with the implementation. Changed expectations deserve special attention; unchanged tests are not proof either.

Review example Decision and reason
Move prices.py into checkout/; update test imports; keep total(1999, 200) == 1799 Accept as a refactor if the supported API and behavior remain intact
Return 1800; replace the exact assertion with total(...) > 0 Reject the refactor claim: the assertion hides changed behavior
Correct a calculation and add its regression test One coherent change; the word “and” is not a problem
Rename logging classes while changing checkout rounding Separate unrelated changes, even if the title contains no “and”

Ask an assistant for a reviewable change

Implement <one observable behavior>.
State the contract and examples first. Propose coherent, reviewable commits.
Keep unrelated refactoring separate. Include tests with their behavior change.
For stateful changes, explain compatibility and recovery before removing data.
For each commit, state what changed, why, and the checks actually run.

Review the diff yourself. Sort each hunk into “needed for this behavior” or “unrelated.” Look for missing failure paths, tests and migration steps. A useful review may approve the patch unchanged. Do not manufacture objections to meet a quota.

Review this diff against the agreed contract.
Identify behavior changes, accidental changes, and tests that would detect them.
Cite the relevant hunks. State unknowns and checks you did not run.
Approve, request changes, or ask a specific question, with evidence.

Apply this lesson to the reading-list application

Start Stage 1: Build the shared reading-list application with a repository, .gitignore, a lockfile decision and a short scope note. Build a runnable sign-up/sign-in slice in a few coherent commits. Keep secrets out of history. Review it through a pull request, even when working alone.

Acceptance: another person can reproduce the behavior from your PR; the commit history explains the decisions; required checks pass; and stateful changes have an explicit recovery boundary. An unchanged approval is valid when supported. A one-line destructive migration without recovery is not.

Practice failure detection using a labeled disposable fixture, not by secretly introducing bugs into a real team’s work. A negative control proves sensitivity to the particular defect you planted, not every possible defect.

Words you now own

Diff/hunk: a change or contiguous part of it. Revert: a new commit that reverses an earlier code change. Merge queue: checks proposed combined changes before landing them. Lockfile: the resolved dependency graph used to reproduce an install. Review latency: time to meaningful review, measured from timestamps rather than inferred from file count.

Draw it from memory · Make a change reviewable

Diagram: Draw it from memory · Make a change reviewable

show why a clean Git revert cannot undo an already sent payment or restore a deleted database row.

Choose checks that reveal the behavior a change can break · Learning sequence · Independent practice