Python Decision Documentation
Begin
13 pages · ~26 min
Interactive digital-human course

Python Decision Documentation

This training teaches Python programmers how to document coding decisions clearly and consistently, improving code maintainability for developers and technical teams.

A digital instructor presents all 13 pages. Hold “Ask” at any point and ask out loud — the answer comes from this course. No sign-up needed.

26 minFree to watchDownloads

What you’ll learn

  1. 01Documenting Decisions in Python ProgrammingWelcome. Over the next several slides, we are going to talk about documenting decisions in Python programming. The goal is simple. Capture the reasoning behind significant design choices, not just the code that resulted from them. Python is flexible by design. There are usually several valid ways to structure a module, pick a dependency, or shape an interface. The code shows what you chose. It rarely shows why, or what you rejected. That gap hurts most when someone else inherits the work. A new developer, a tech lead, or a maintainer joining a long-lived service has to reverse-engineer intent from pull requests and commit messages. Here is the roadmap. We will build a shared vocabulary, look at formats like architecture decision records, practice writing the rationale, connect decisions to code, review tooling and workflow, and call out common pitfalls. By the end, you should be able to capture rationale, link decisions to code, and sustain a lightweight decision log your team will actually keep. Next, we will look at why Python projects lose rationale in the first place.Documenting Decisions in Python Programmingdocs.python.orggithub.comzuniweb.com+22 min
  2. 02Why Python Projects Lose RationaleLet's look at why Python projects lose rationale in the first place. Python rarely hands you one obvious design. Several idiomatic approaches will fit the same problem, so the one you ship is a decision, not a default. Dynamic imports, plugin registries, and runtime flexibility make it worse. They work, but a reader can no longer see intent from the module tree alone. Then there's turnover. Oral history erodes faster than code changes, so the reasoning leaves with the people who held it. Refactoring without that context quietly reverses deliberate trade-offs. A scheduler becomes a thread pool because the original constraint was never written down. And remember the split. Docstrings say what the code does. Decision records say why. When an auditor, a new hire, or a compliance reviewer asks why, that traceable rationale is the artifact that answers them. Core Concepts and Vocabulary.Why Python Projects Lose Rationaledocs.python.orggithub.comzuniweb.com+21 min
  3. 03Core Concepts and VocabularyLet's establish the vocabulary we will use for the rest of this course. A decision is the choice itself. Rationale is why you made it. Context is the forces and constraints at the time. Consequence is what you now live with. Status tracks where the decision stands. Supersession links a decision to the one that replaced it. An ADR is one short, dated, immutable record of a significant decision. The decision log is simply the collection of those records. Keep them in the repository, in docs slash a d r, numbered sequentially. Separate the artifact types. Design docs describe what was built. RFCs propose and gather input before a decision lands. ADRs record the decision after the fact. Statuses follow a lifecycle: proposed, accepted, deprecated, and superseded by a later record. Some teams add rejected when they want a paper trail. Once accepted, a record stays immutable. Update additively, and supersede rather than rewrite. That preserves the history. Issues, pull requests, and commit messages supply evidence, but they are not durable decision records. They disappear into thread history. The ADR is the artifact you cite a year later when someone asks why. Next, we will look at choosing the right format and granularity.Core Concepts and Vocabularymartinfowler.comgithub.comarchyl.com+22 min
  4. 04Choosing the Right Format and GranularityNow let's talk about choosing the right format and granularity. Match the format to the impact of the decision. For a quick call, use a Y-statement. It is one sentence: in the context of X, facing Y, we decided Z, to achieve a goal, accepting a trade-off. For most decisions, start with Nygard's five parts: title, status, context, decision, and consequences. It is the easiest entry point. When a decision is contested or needs sign-off, use MADR. It adds decision drivers, options with pros and cons, and a confirmation step. Here is the practical filter. Write a record when the decision is hard to reverse or crosses team boundaries. Skip version bumps and formatter debates. Those belong in the pull request. And guard against over-documentation. Two clear paragraphs often beat four pages. If you find yourself writing an essay, you are probably writing a design doc, not a decision record. Next, let's look at writing decision records that stay useful.Choosing the Right Format and Granularitymartinfowler.comgithub.comarchyl.com+22 min
  5. 05Writing Decision Records That Stay UsefulNow let's look at what makes a decision record stay useful six months after you write it. Start with context and forces, not the conclusion. Name the constraint, the quality attribute, the pressure that made this decision necessary. Then record at least two options, and say plainly why each one lost. In the context of moving session data out of application memory, you might note that you decided for Redis and against sticky sessions, to achieve horizontal scaling, accepting an added failure mode. That is a Y-statement, and it fits in one sentence. Next, list honest consequences. What gets easier, harder, riskier, more expensive. If your consequences section reads like marketing copy, a reviewer should reject it. Use plain, neutral language and drop the adjectives. Link the issue, the benchmark, or the prototype that informed the choice, and add a review trigger. A trigger names the observation that would justify revisiting the decision, and someone owns it. Aim for two hundred to five hundred words, readable in one review sitting. If it runs longer, you are probably documenting several decisions. Split them. Worked Examples: Python-Specific Decisions.Writing Decision Records That Stay Usefuladr.github.ioadr.zonegithub.com+22 min
  6. 06Worked Examples: Python-Specific DecisionsLet us ground this in Python-specific decisions you can record today. Start with dependency choice. State why the standard library won over a third-party package, and name the lock-in and supply-chain cost you accept. Next, concurrency. If you chose asyncio over sync I/O, or a thread pool over an event loop, record the workload that forced it and what you gave up. Then packaging. If you use a hub-and-internals layout, with re-export hubs over direct imports, write down that rule so new modules follow it. Type hints follow the same pattern. Say whether typing is gradual or strict, and estimate the migration cost for each option. Test strategy matters too. Record whether you target a coverage number, which fixtures and pytest plugins you rely on, and when a custom harness beats a standard one. Every record should show the same four fields: context, alternatives, the decision, and the accepted trade-offs. That shape lets a maintainer join in two years and still see why the code looks the way it does. Next, we will look at embedding decisions in Python code and repositories.Worked Examples: Python-Specific Decisionsdocs.python.orggithub.comzuniweb.com+21 min
  7. 07Embedding Decisions in Python Code and RepositoriesNow let's put decisions where engineers actually work: inside the code and the repository. In Python, anchor rationale in module headers, docstrings, and targeted inline comments. Follow a consistent convention, for example a hash comment reading ADR: 2025-12-01-redis-session-cache, followed by the reason for the choice. Then reinforce it in commit messages and pull request descriptions. Link both directions. The code cites the ADR, and the ADR lists the implementing files. Store the records next to the source under docs slash A D R, versioned with the code. When a decision spans packages, keep one authoritative record and leave short local notes that point back to it. That keeps the reasoning findable at the moment someone touches the code. Tooling and Automation is where we take this next.Embedding Decisions in Python Code and Repositoriesgithub.comgithub.comgithub.com+21 min
  8. 08Tooling and AutomationNow let's talk tooling and automation. Start minimal. A numbered docs slash a d r directory, one template, and a README convention will carry you a long way. Number the files sequentially, write the first record about adopting decision records, and resist hand-editing an index. When volume grows, add a CLI. Tools like adr-toolkit and adrpy-ai scaffold, number, index, and wire supersession links, so superseding record zero zero zero three updates both files and never deletes history. Prefer zero-dependency, standard-library Python tooling. Decision records are infrastructure. The tool that manages them should never be the reason a build breaks, and pure standard library means no version drift and no transitive vulnerabilities. Then enforce it in continuous integration. Have CI validate required sections and fail on broken supersession links or inconsistent numbering. adrpy check does exactly this and changes nothing when the repository is broken. For broader audiences, a static site build makes the log browsable by product managers, auditors, and non-engineers who will never open the repository. Finally, AI can help. Let a model draft a record from a pull request, an issue thread, or meeting notes. But humans own acceptance and the trade-offs. Always review the rejected alternatives and the consequences before you merge. Let's move on to team practices, review, and culture.Tooling and Automation2 min
  9. 09Team Practices, Review, and CultureNow let's talk about making this stick, because team practices, review, and culture decide whether decision records survive past the first quarter. First, make the record a normal design-review step, not an optional follow-up. When a pull request changes a shared contract, the reviewer asks for the record before merging. Default to PR-based review. The proposer opens the pull request, discussion happens inline, and the record merges with the change. Assign one decision owner. Anyone may write, but one person maintains the record. Then classify by scope: service-local, cross-team, or foundational. Scale review depth accordingly, and prefer consent-based governance, meaning merge unless someone blocks, rather than requiring full consensus. Reuse the log for onboarding. Point new hires at the foundational records first; reading key decisions beats reconstructing history from Slack threads. Finally, watch for documentation fatigue. Most practices die in the first quarter when they feel optional. Keep the ceremony proportional to the decision, and the habit survives. Next, we move into maintenance, supersession, and long-term stewardship.Team Practices, Review, and Culture1 min
  10. 10Maintenance, Supersession, and Long-Term StewardshipNow let's talk about stewardship, because a decision record is only useful if it stays honest. Keep statuses true: accepted, deprecated, or superseded. Say what is currently true. A record still marked accepted after the team quietly reversed the call is a lie with a timestamp, and it costs real money when a new engineer builds on it. So supersede rather than rewrite. Write a new record, link it both ways, and flip the old status in the same pull request that adds the replacement. Deprecate when the context dissolved and nothing took its place, like a feature removed in a rebuild. Supersede when a specific new decision replaces the old one. Never delete an accepted record. The chain of supersession is the evolution of your architecture, and it keeps you from re-litigating decisions you already made. Review quarterly, and again after migrations, incidents, or vendor changes. Crucially, reconciling drift beats hiding it. Verify that implementation actually matches the recorded state. If code and record disagree, that is a signal, not a secret. Next, common pitfalls and anti-patterns.Maintenance, Supersession, and Long-Term Stewardshipmartinfowler.comgithub.comarchyl.com+22 min
  11. 11Common Pitfalls and Anti-PatternsLet's talk about the pitfalls that quietly erode a decision log. Each one is a small habit, but together they turn records into noise. First, writing records after the fact. Six months later, the ADR becomes a justification for what you already built, not the reasoning that drove it. Record during the decision. Second, splitting. One decision per record. If you chose a database, a broker, and an auth provider in the same meeting, that's three records, each with its own lifecycle. Third, skipping alternatives and negative consequences. We chose Postgres because we evaluated MongoDB and DynamoDB and the consistency story fit our billing data. List the rejected options, name who now monitors or maintains the choice, and state what gets harder. Fourth, quietly editing accepted records. Once accepted, they are immutable. Supersede, don't rewrite. One line change, Accepted becomes Superseded by ADR-0023, saves days of confusion. Fifth, storing them in a wiki. If they live in Confluence or Notion, engineers won't find them at decision time. Keep them in the repo, in docs adr, linked from related pull requests and code comments. Sixth, treating records as approval gates. They record decisions the team made; they don't authorise them. Debate belongs in an RFC or the pull request. Seventh, trivial records piling up while load-bearing ones go unrecorded. Prettier versus ESLint is not an ADR. Session state in the database instead of memory is. Write when the choice outlasts the sprint and someone will ask why in six months. Next, we'll put this into practice in the hands-on exercise.Common Pitfalls and Anti-Patterns2 min
  12. 12Hands-On Exercise: Write or Improve a Decision RecordLet us put this into practice. Pick one real design choice in your Python codebase that a newcomer would question. Maybe why sessions live in Redis instead of memory, or why an interface is abstract. Then draft five parts: context, alternatives, decision, consequences, and a review trigger. Keep the alternatives honest. If you only list one option, you have not made a decision, you have written a report. Next, add a Y-statement summary for pull requests and stand-ups. In the context of our session store, facing container restarts, we decided for Redis, to achieve durability, accepting an extra service to operate. Then reference the record in a module docstring or inline comment, something like ADR colon twenty twenty five dash twelve dash zero one redis session cache. That is how a future maintainer finds the reasoning at the point of code. Now review with a peer. Ask for concrete alternatives, honest trade-offs, and a word budget. If a consequence section has no negatives, push back. Every architectural decision costs something. Fix the wording. Then commit the file to docs slash A D R, and agree on the next record to capture. Recording one decision this week beats planning a perfect process. Up next, the adoption roadmap and recap.Hands-On Exercise: Write or Improve a Decision Recordadr.github.ioadr.zonegithub.com+22 min
  13. 13Adoption Roadmap and RecapLet's close with a roadmap you can act on tomorrow. Start small. Pick the next significant decision your team makes, write one record in docs adr, and link it from the pull request. Don't backfill history; that produces sanitized reasoning. Prioritize the load-bearing decisions and your current architectural seams instead. Choose the lightest format first, and add structure only when a real gap appears. Pair the log with one current-state view, so history stays distinct from reality. Then use these records where they already pay off: onboarding, design review, postmortems, and migrations. Measure time to onboard and re-litigation avoided, not document count. So remember the core loop: capture the rationale, link to code, review records like code, and supersede rather than rewrite. Thank you for working through this course. Go write one record this week, and let it earn its keep.Adoption Roadmap and Recap2 min

Take the deck with you

Download this course as a file — free, no sign-up needed.

Free to use in your own training — please keep the PersonWise credit page at the end.

Have your own deck? Turn it into a course

Sources consulted

Web sources consulted while building this course.

Python Decision Documentation — Free interactive course