6.3Best practices & pitfalls
The essentials in 30 seconds
- Golden rule: readable (black), proven (pytest), portable (venv), delivered (CI) — applied always, not once.
- Do: explicit names, return + immutable defaults, with + pathlib, .get, narrow try, pinned venv, tests first, vectorise, pre-commit, guardian CI.
- Avoid: cryptic names, print instead of return, + concatenations, bare except, committed .venv, “later” CI, plain-text secrets.
Nabil thread — the criteria stuck on the wall
After one year, Nabil stuck four words on the wall in Algiers: readable, proven, portable, delivered. What counted most was not a library but three habits — naming explicitly, testing first, isolating in a venv — and his biggest narrowly avoided trap: a committed .venv with plain-text secrets during a rush week.
Pick a single habit to anchor in your routine, then move to the next.
The trust contract
Healthy code rests on few rules, applied always. Here they are, with their opposites to ban.
✓ Do
- Explicit names (verbs, snake_case), one responsibility per function.
- return the result, immutable defaults (None), data as arguments.
- f-strings, with + encoding, pathlib for paths.
- Right container for the right use, .get() with a default, conscious copies.
- Narrow precise try blocks, else/finally, raise early, never a bare except.
- Standard library first, venv + pinned requirements, absolute imports.
- Tests first (red-green), limits + errors, hints at boundaries.
- Vectorise the large, yield the giant, async the waiting.
- black/ruff in pre-commit, named patterns, pragmatic SOLID.
- Guardian CI, versions + rollback, secrets out of code.
✗ Don't
- Cryptic names (x2, tmp2, data2) and 200-line functions.
- print instead of return, mutable defaults, modified globals.
- + concatenations, open() without with, hard-coded paths.
- Lists for key lookup, direct access without get, = for copying.
- except: pass, try around everything, silencing failures.
- Everything global, committed .venv, from x import *.
- Tests after (or never), nominal only, 100% fetish.
- for loops over millions, giant lists, requests inside async.
- Style debated by hand, god-objects, factories for 50 lines.
- “Later” CI, plain-text secrets, prod with no way back.
Ready-to-say script — checking your practice before delivering (30 s)
“Readable (black)? Proven (pytest nominal + limits)? Portable (rebuilt venv)? Delivered (green CI, secrets out of code)? If any no, I fix before delivering.”
Copy-paste template — clean function (return, immutable default, pathlib)
from pathlib import Path
def charger_lignes(chemin: Path, lignes: list[str] | None = None) -> list[str]:
lignes = [] if lignes is None else list(lignes)
with chemin.open("r", encoding="utf-8") as f:
lignes.extend(line.strip() for line in f)
return lignes
VSE / small budget
One habit per quarter is enough: venv + tests first, the rest after.
SME Algiers
Adapt routines to peaks and travel: one kept black + pytest slot each week.
Remote / hybrid
The #1 discipline at a distance: written reviews and green CI, even for small fixes.
Intercultural
Check local usages rather than assuming: an unusual CSV format must raise flags everywhere.
48h challenge — apply tomorrow
Screen your main script: zero bare except, zero committed .venv, zero plain-text secret. Fix the first gap found.
- I know the 10 reflexes to adopt and the 10 traps to avoid.
- I checked my 3 critical points (except, venv, secrets).
- I did the 48h challenge or scheduled its date.
Before delivering, Nabil checks his practice. Which reflex protects him best?
Stick the thread project's criteria on the wall: readable (black), proven (pytest), portable (venv), delivered (CI).