THE FUTURE MARKETACADEMY
Your classroomRoom 07 · Tech Lab
School of Data & Tech

Python Engineering: design, review and mentoring

Step 8 of 8 in Tech Lab

Next in your path: 7.6.4 Web Business Lead: manage client sites

What you'll be able to do
  • Design Python code that is easy to change: a pure core, a thin outer shell, and dependencies passed in.
  • Use type hints, dataclasses and protocols as clear contracts, and check them with a type checker.
  • Write a short coding standard for a team, based on PEP 8 and PEP 257, and let tools enforce the boring parts.
  • Run code reviews that improve the code and the people: what to look for, how to write comments, how fast to answer.
  • Change code that other people already use, safely: tests first, small steps and deprecation warnings.
  • Mentor beginners: teach them to read tracebacks, use the debugger and learn from review.
  • Set up a team codebase: contribution guide, code owners, protected branches and an onboarding checklist.

This is the expert level of the Python track. Before, you learned to write code that works. Now you learn to lead: to design code a team can live with for years, to review other people's work fairly, to set standards and to teach. The examples continue the small ordertools project from course 7.5.3, now imagined as a tool that a team of four looks after.

Every code example marked "tested" was run for this course with Python 3.9.6, pytest 8.4.2, Ruff 0.17.5 and mypy 1.19.1 on a Mac. Workflow files marked "from the docs" are shown as the official documentation describes them and were not run here, because they need a GitHub repository. On Windows, type py or python where the course says python3.

Words in this course 58Open the Vocabulary Hall
01

Design for change

In simple words

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.

Key facts
  • 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.
  • Do not over-engineer. Google's code review guide warns reviewers to watch for code that is more generic than needed or adds features the system does not need yet. Design for the changes you can see coming, not for every possible future.
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.

Step by step
  1. Make a folder l1 and save the "before" code as before.py, with report("order.csv") as the last line, and the order.csv file from course 7.5.3 next to it. Run it.
  2. On paper, list every job the report function does. You should find at least four (open the file, read rows, calculate, check the date, print).
  3. Save the "after" code as after.py and the tests as test_after.py in the same folder.
  4. Run python3 -m pytest -q and check you see 3 passed.
  5. Point to the pure core (order_total) and the shell (read_lines, main). Say out loud which one touches the outside world.
  6. Change WEEKEND_DISCOUNT to 0.15 and run the tests: one fails. That is the point: the rule lives in one named place, and a test guards it. Change it back.
  7. Check: you can explain why passing day into order_total makes it testable on any day of the week.
LESSON 01Design for change
LESSON 01 / ANIMATED LESSON / AI VOICE00:00 / 01:00
Read the video script
[Host] "Code is read far more often than it is written. So design it to be read, and changed."
[Screen: the before function with four jobs highlighted] "This one function opens a file, does maths, checks the calendar and prints. You can only test Saturday on a Saturday."
[Screen: order_total(lines, day)] "Split it. A pure core does the maths. The date comes in as an argument."
[Screen: test with date(2026, 11, 14) passing] "Now a test can pretend it is Saturday, any day of the week."
[Text on screen: High cohesion. Low coupling. No gold plating.] "One job per part, few ties between parts, and no features nobody asked for."
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.
Open Claude
Sources
My notes
02

Types, dataclasses and protocols as contracts

This lesson is part of full access: every course and every level for one payment.

03

A team coding standard, enforced by tools

This lesson is part of full access: every course and every level for one payment.

04

Running code reviews

This lesson is part of full access: every course and every level for one payment.

05

Changing code that others depend on

This lesson is part of full access: every course and every level for one payment.

06

Mentoring beginners

This lesson is part of full access: every course and every level for one payment.

07

Leading a team codebase

This lesson is part of full access: every course and every level for one payment.

++

Final project

This lesson is part of full access: every course and every level for one payment.

??

Quiz

  1. Why should a function receive today's date as an argument instead of calling date.today() inside?

  2. What do high cohesion and low coupling mean?

  3. Does Python stop a program when a call breaks a type hint?

  4. What does frozen=True do in a dataclass?

  5. Why use Decimal built from strings for money?

  6. Why is a list as a default argument a bug?

  7. What should a written coding standard contain?

  8. When should a reviewer approve a change?

  9. What does the label "Nit:" mean in a review comment?

  10. How should you rename a public function without breaking users?

  11. Which line of a traceback tells you what went wrong?

  12. What does a CODEOWNERS file do?

EX

Final exam

This lesson is part of full access: every course and every level for one payment.

CE

Certificate

This lesson is part of full access: every course and every level for one payment.