A request to “clean this up” leaves room for a new shipping policy, different rounding or a changed return type. Those could be worthwhile changes, but they need their own requirements and checks.
Choose a small seam in the existing code
This original Python example mixes a charge rule with presentation. Inputs are a list of nonnegative integer prices in cents and a customer name string. Shipping is zero when the subtotal is at least 5,000 cents; otherwise it is 700 cents, including an empty order. That empty-order rule is deliberately part of this exercise's existing behavior.
def invoice_text(name, prices):
subtotal = sum(prices)
shipping = 0 if subtotal >= 5000 else 700
total = subtotal + shipping
return f"{name}: {total // 100}.{total % 100:02d} USD"
The extraction goal is to reuse the charge calculation in another presentation later. It does not require changing today's text, accepting new input types or introducing a class.
Write down the behavior that tends to disappear
The helper should return the total in integer cents. The public function still returns a string, and neither function should modify the supplied list. Keep these independently calculated fixtures:
| Name and prices | Required output |
|---|---|
| Ana, [] | Ana: 7.00 USD |
| Ana, [4999] | Ana: 56.99 USD |
| Ana, [5000] | Ana: 50.00 USD |
| Bo, [1299,2501] | Bo: 45.00 USD |
The boundary at 5,000 matters because both the charge and the result change there. Empty input matters because a well-intentioned rewrite might waive its shipping charge. Check punctuation and spacing too when downstream code or snapshots depend on the exact string.
Give the refactor a clear limit
Refactor the Python function below by extracting its total-in-cents
calculation into a pure helper. Keep invoice_text(name, prices),
its return type, exact output and all existing charge rules unchanged.
Inputs: list of nonnegative integer cents; customer name is a string.
Neither function may modify the list. Do not add dependencies,
validation policy, new classes or a new shipping rule.
Current code and callers: [PASTE PERMITTED CODE]
Expected fixtures, including empty and threshold cases: [PASTE]
Explain the extraction boundary, then give the small diff and checks.
Keep suspected business-rule improvements separate from this change.
Do not claim tests ran unless actual execution evidence is supplied.
OpenAI's prompting guidance, checked October 24, 2026, supports giving the desired result and relevant boundaries. Here, an unchanged charge rule is the boundary most likely to prevent accidental extra work.
Compare the extracted version
def total_cents(prices):
subtotal = sum(prices)
return subtotal + (0 if subtotal >= 5000 else 700)
def invoice_text(name, prices):
total = total_cents(prices)
return f"{name}: {total // 100}.{total % 100:02d} USD"
Run the same fixtures against both versions and compare each with the explicit expected string. Comparing old and new alone can preserve an existing defect; the independent expectations establish what this exercise requires. Also compare the input list before and after the call.
Python's unittest documentation explains assertions for expected values. In an existing project, use its current test framework and relevant caller tests. Avoid replacing those with a large new harness for this small extraction.
Keep the review about the extraction
Read the resulting diff for changed signatures, new side effects and policy changes hiding among moved lines. The function above provides a separate calculation you can call without rendering an invoice, while callers of invoice_text keep the same result.
If someone wants free shipping for empty orders, describe that as a new rule with new expectations after this refactor. The code-review workflow helps turn a suspected defect into a reproducible finding; the unit-test guide helps preserve a specific function contract. Finish this change when the extraction and its existing callers have passed their agreed checks.