How do you review a mutation bug?
Write a review comment that gives a teammate a reproducible failure.
The question
Patchwell is a fictional team that builds scheduling software. This is an authored practice case. A helper formats the next three shifts. The caller also uses the same array to show the manager’s chosen order.
function nextThree(shifts) { return shifts.sort((a, b) => a.start - b.start).slice(0, 3); }
| Observed | |
|---|---|
| Before helper | IDs in manager order: B, A, C |
| After helper | IDs in caller: A, C, B |
Authored example. Values are supplied for this case.
Return the three earliest shifts. Preserve the caller’s array order.
“Draft a blocking comment. Which repair would you request, and what would you leave out?”
Not saved by this site. Your browser may restore text when you navigate back.
A strong answer, step by step
Open each step in turn. This is one strong answer, not the only one.
Step 1: Identify the observable defect
What would you do here? Open the move you’d make.
Say the helper needs cleaner naming
Tempting, but it misses something. A naming preference does not explain the broken order.
Explain the input mutation
The strong move. It connects the code operation to a visible failure.
See how a strong candidate says it
“sort mutates the original array. The helper returns the expected earliest shifts but also changes the manager’s order in its caller. That violates the second requirement.”
Why it works: A correct return value can hide a side effect.
Step 2: Supply a minimal reproduction
What would you do here? Open the move you’d make.
Assert output and unchanged input
The strong move. Both parts of the contract need proof.
Assert only that three shifts return
Tempting, but it misses something. The mutating implementation passes that test.
See how a strong candidate says it
“Use an input ordered B, A, C with start times 30, 10, 20. Call nextThree, then assert the input IDs remain B, A, C and the returned IDs are A, C, B.”
Why it works: The author can reproduce both the output and the side effect.
Step 3: Request the bounded change
What would you do here? Open the move you’d make.
Deep-clone every object through JSON
Tempting, but it misses something. That adds cost and can alter value types without a need.
Copy the array before sorting
The strong move. It preserves caller order for this implementation.
See how a strong candidate says it
“I would request a copy before sorting, such as [...shifts].sort(...).slice(0, 3), or toSorted if the target runtime supports it. A shallow copy is enough here because the comparator only reads start.”
Why it works: It avoids mutation without making an unsupported deep-copy claim.
Step 4: Write the comment
What would you do here? Open the move you’d make.
Mark the behavior bug as blocking
The strong move. The defect violates the given contract.
Mix the bug with a full style rewrite
Tempting, but it misses something. The author cannot see which change is required.
See how a strong candidate says it
“Blocking: sort changes the caller’s array. For B(30), A(10), C(20), the caller becomes A, C, B. Please sort a copy and add an assertion that input order stays unchanged. I would keep naming suggestions separate.”
Why it works: A useful comment states impact, evidence, and an actionable request.
The answer, in short
- Decision
- Block on input mutation and request a copy-before-sort repair.
- Because
- The return value is correct while shared state is changed.
- What would change it
- If mutation were an explicit caller contract, copying would be unnecessary.
Common traps
- Checking only the return value.
- Calling a shallow copy unsafe without examining what the code mutates.
Check your answer
- Did you identify the shared reference?
- Did you give a concrete reproduction?
- Did you test the input after the call?
- Did you separate required repair from optional style?
Last reviewed Nov 10, 2026