Example (tested): before
import csv
from datetime import date
def report(path):
total = 0
for row in csv.DictReader(open(path)):
total += int(row["qty"]) * float(row["price"])
if date.today().weekday() == 5:
total = total * 0.9
print("Total:", round(total, 2))
It works (Total: 33.0 for the order file from course 7.5.3 on a Friday), but one function reads a file, does maths, checks the real calendar and prints. You can only test the Saturday discount on a Saturday, and the file is never closed explicitly.
Example (tested): after
"""Order totals: pure logic, with the outside world passed in."""
import csv
from datetime import date
SATURDAY = 5
WEEKEND_DISCOUNT = 0.10
def read_lines(path):
"""Return (qty, price) pairs from an order CSV file."""
with open(path, newline="", encoding="utf-8") as f:
return [(int(r["qty"]), float(r["price"])) for r in csv.DictReader(f)]
def order_total(lines, day):
"""Return the total of the lines, with the Saturday discount on that day."""
total = sum(qty * price for qty, price in lines)
if day.weekday() == SATURDAY:
total *= 1 - WEEKEND_DISCOUNT
return round(total, 2)
def main(path, today=date.today):
print(f"Total: {order_total(read_lines(path), today()):.2f}")
The tests no longer depend on the real calendar:
from datetime import date
from after import main, order_total
LINES = [(10, 2.50), (2, 4.00)]
def test_friday_has_no_discount():
assert order_total(LINES, date(2026, 11, 13)) == 33.0
def test_saturday_has_ten_percent_off():
assert order_total(LINES, date(2026, 11, 14)) == 29.7
def test_main_with_a_fixed_day(tmp_path, capsys):
f = tmp_path / "order.csv"
f.write_text("product,qty,price\nPen,10,2.50\nNotebook,2,4.00\n", encoding="utf-8")
main(f, today=lambda: date(2026, 11, 14))
assert capsys.readouterr().out == "Total: 29.70\n"
python3 -m pytest -q printed 3 passed. 13 November 2026 is a Friday and 14 November 2026 is a Saturday. main still uses the real date when nobody passes today, so normal users see no difference.
Try it now
Take one script you wrote in courses 7.5.2 or 7.5.3. Find a function that mixes calculation with files, printing, the clock or the network. Split it into a pure function and a thin shell, pass the outside thing in as an argument, and write two tests for the pure part. Write three sentences: what was hard to test before, what you changed, and what is easier now.
ClaudeStuck? Copy a ready-made prompt for Claude
Copy this, open Claude, paste it, and Claude will walk you through the lesson step by step.
For a grown-up: Claude is for adults (18+). Copy this, paste it into Claude, and use the answer to explain the lesson to your child.
I'm learning "Python Engineering: design, review and mentoring" on The Future Market. Lesson 1: "Design for change".
What the lesson teaches:
- Before this course: Python Projects: testing, packaging and version control (course 7.5.3). You should already know modules and the src layout, your own exception classes, pytest with fixtures and parametrize, git branches and merges, pyproject.toml and semantic versioning. This course does not repeat them.
- Much of the work on code comes after it is first written: people read it, fix it and change it. PEP 8, Python's style guide, puts it simply: code is read much more often than it is written.
- The Zen of Python (PEP 20, type import this in Python to see it) gives short design rules you can quote in reviews, for example "Readability counts.", "Simple is better than complex.", "Errors should never pass silently." and "If the implementation is hard to explain, it's a bad idea."
- Cohesion: everything in one function or module belongs to one job. Coupling: how much one part depends on the details of another. Aim for high cohesion and low coupling.
- Pure core, thin shell. Keep calculations and decisions in pure functions: same input, same output, no printing, no files, no clock, no network. Put the outside world (files, input(), printing, today's date, web calls) in a thin outer layer.
- Pass dependencies in. If a function needs today's date, a price list or a file, pass it in as an argument instead of reaching for it inside. Tests can then pass a fixed date or a fake price list. This is called dependency injection, and in Python it is often just an extra argument with a sensible default.
- Name things after what they mean: WEEKEND_DISCOUNT = 0.10 beats a bare 0.9 in the middle of a formula. Constants in capitals with underscores follow PEP 8.
The exercise I'm working on:
Take one script you wrote in courses 7.5.2 or 7.5.3. Find a function that mixes calculation with files, printing, the clock or the network. Split it into a pure function and a thin shell, pass the outside thing in as an argument, and write two tests for the pure part. Write three sentences: what was hard to test before, what you changed, and what is easier now.
I'm stuck. Please:
1. Explain the main idea in plain, simple words with one everyday example.
2. Walk me through the exercise one small step at a time. Ask me what I've done so far before giving the next step.
3. Don't just give me the final answer. Help me do it myself, and check my work when I share it.
I'm a parent helping my child (about 8 years old) with a lesson called "Design for change" from the course "Python Engineering: design, review and mentoring".
Here's what the lesson says:
Think of a toaster with the plug built into the wall. It works, but you cannot move it, test it on the kitchen table or swap the plug. Good design gives every part a plug: the toasting part does one job, and the power comes in through a cord you can unplug. Then you can test it anywhere and change one part without breaking the others.
The activity:
Take one script you wrote in courses 7.5.2 or 7.5.3. Find a function that mixes calculation with files, printing, the clock or the network. Split it into a pure function and a thin shell, pass the outside thing in as an argument, and write two tests for the pure part. Write three sentences: what was hard to test before, what you changed, and what is easier now.
Please explain this so an 8-year-old understands: short sentences, a fun everyday example, and no hard words.
Then give me 3 simple questions I can ask my child to check they understood, and a way to do the activity together, one tiny step at a time.