Software Design Reference Five phases · plus capstone, code lab, and assessments

A self-learning course · 60 lessons · capstone, code lab, and assessments

From good code to consequential decisions

Move from designing good code to leading consequential software decisions—from module boundaries and domain models through architecture, product discovery, team execution, and safe operation.

Then prove it: a fully worked capstone to compare your own against, a flawed Python codebase to improve, scored assessments against a four-level rubric, and a portfolio you can take to a promotion conversation.

60lessons
5phases
12trade-offs
158glossary terms

Who this is for

You already know how to ship production software. You are the engineer people ask when a design spans modules, teams, or an uncertain roadmap—and you want a repeatable way to make those calls as a tech lead or architect.

This is not a language tutorial, a pattern catalog to memorize, or a generic management course. It connects code-level design judgment to the work senior technical leaders actually carry: clarifying product intent, exposing architectural forces, making consequential decisions, sequencing risk, aligning a small cross-functional team, and owning what happens after release.

Prerequisites, stated plainly

Not for you (yet): developers in their first year or two, who will get more from writing a lot of code than from reasoning about the shape of it; and anyone looking for a management course — this one is about technical decisions and the collaboration they require, not about performance reviews or hiring.

The outcome

By the end of this program you will be able to design with judgment — and you will hold the artifacts that prove it.

What you'll be able to do

  • Design code that remains clear as it grows.
  • Structure systems that evolve without constant rewrites.
  • Use AI effectively without sacrificing design quality.
  • Make architectural decisions with clarity and control.
  • Lead product, design, and engineering from discovery through rollout and learning.

What you walk away holding

Each one produced by a practice task, on your own code:

  • A five-point structural checklist you run on any AI output, and the boundary spec you write before generating (lessons 0005, 0010).
  • An import table for your folders — which may import which — enforced by a test rather than a README (lesson 0022).
  • An inventory of every technology your domain touches, its port, and its fake in tests (lesson 0023).
  • A cost ledger with a break-even year in it, for the next build-vs-buy argument (lesson 0027).
  • An answered failure inventory — ordering, duplicates, dead letters, tracing — before you adopt a queue (lesson 0031).
  • A three-line debt ledger — borrowed, interest, repay-when — for the shortcuts you take on purpose (lesson 0038).
  • A complete initiative packet — frame, assumption and story maps, architecture drivers and diagrams, ADR, delivery map, team charter, and rollout contract — traced from outcome to evidence (lessons 0039–0050).
  • A from-scratch design packet — problem map, domain glossary, responsibility boundaries, state machines, invariant and contract reviews, data-model choice, style decision, and pipeline design (lessons 0051–0060).
  • Your own capstone packet, reviewed against a strong and a deliberately weak version of the same initiative, with the reviewer's notes explaining which differences actually matter.
  • The lab codebase as you left it: characterization tests around behaviour you did not fully understand, seams where there were none, and fitness functions that fail when the boundaries erode again.
  • An assessment record — entry diagnostic, five phase assessments, the capstone score, and the exit diagnostic on comparable scenarios, so the change in your judgment is visible rather than asserted.
  • A portfolio narrative of one real initiative, anonymized, told at executive, product and engineering depth, separating your contribution from the team's.

How this course works

Each lesson is a single HTML page you can finish in one sitting. It gives you one tangible win: a concept, shown on real code, then practiced through a short quiz and a task on your own code. Lessons are short on purpose — working memory is small, and storage strength comes from doing, not from reading.

01

Knowledge

Each lesson points to a high-trust primary source to read or watch.

02

Skills

Instant-feedback quizzes and practice tasks build durability.

03

Wisdom

Take the practice tasks to a real community (see resources); trade-offs only become judgment in the wild.

Mark each lesson complete when you finish — your progress appears here. Reference sheets (glossary, principles, patterns, trade-offs) live under reference/ for quick lookup; the glossary is the canonical vocabulary of this course.

Where you are

Progress is stored in this browser.

Completion is kept in this browser's local storage — it does not follow you to another machine, and clearing site data resets it. Export it below and that stops being true.

Export progress

Everything this course has stored about you: which lessons you marked complete, and which option you chose on each quiz. Copy it into a note, a gist, or your own repository — it is a small JSON object with no personal data in it.

{}
Import progress

Paste a record exported from another browser or machine. It is merged, never substituted: a lesson finished here stays finished even if the file you paste predates it, and keys outside this course's namespace are ignored.

Print or offline package: the complete course on one page — every lesson and reference document in order, quizzes shown with the answer marked, no JavaScript. Print it, or keep it for a flight.

Starting somewhere other than the beginning

The lessons are ordered, and later ones assume earlier ones. But if some of this is already yours, start where it stops being true — the honest test is whether you could do the thing today, on your own code, not whether you recognise the words.

The recommended route: take the entry diagnostic first. It asks you to find a structural problem, spot a leaking boundary, protect an invariant, compare a trade-off, turn a vague requirement into a quality-attribute scenario, and replan after evidence changes — then routes you to the earliest phase where your applied judgment stops being consistent. The table below is the faster, rougher version of the same question.

If you can already…Start at
name what is structurally wrong with a function, without running a toollesson 0006
say who owns every interface your domain depends on, and whylesson 0011
make invalid states unrepresentable in code you maintainlesson 0015
keep every technology behind a port, and run the domain's tests offlinelesson 0027
compare architectural options against measured forces and explain the accepted costlesson 0039
design a system from scratch in sequence — problem, domain, state, invariants, components, contracts, data, architecture, deploymentlesson 0051
none of these comfortablylesson 0001

Skipping forward is cheap. Skipping back is the more common need: every lesson links the ones it builds on, so follow those rather than re-reading in order.

The program, phase by phase

Sixty lessons in five phases — from seeing structure in a single function to owning a cross-functional initiative, and designing a new system from scratch. The reference documents at the end of each phase are the compressed essence of the course.

I

Phase I

Core Designer

You learn to recognize structural problems and build code that is clear, resilient, and grounded in the domain.

Reference for this phase: Design Principles and the Glossary.

Prerequisites

  • Production experience with code other people depend on.
  • You can read Python; you do not need to write it well.
  • A codebase of your own — or the lab — to change.

Exit capabilities

  • Name what is structurally wrong with a function without running a tool.
  • Point every dependency at the domain, through ports you own.
  • Make an invalid domain state impossible to construct, not merely rejected.

1. Seeing Structural Problems

Learn to see what's wrong before trying to fix it.

  1. Identify coupling and cohesion issues in real code
  2. Apply SRP, DRY, KISS, and YAGNI in context (not as rules)
  3. Understand the Law of Demeter and why it matters
  4. Recognize when patterns like Strategy are emerging naturally
  5. Detect common structural issues in AI-generated code

2. Structuring for Stability

Turn messy code into designs that resist change.

  1. Design around reasons to change, not just responsibilities
  2. Replace inheritance with composition where it matters
  3. Use patterns like Strategy, Adapter, and Facade intentionally
  4. Control dependency direction with Ports & Adapters
  5. Guide AI toward better structure instead of patching bad outputs

3. Protecting the Domain Core

Make invalid states impossible.

  1. Model domain invariants directly in your code
  2. Use value objects and aggregates to protect integrity
  3. Design repository boundaries that don't leak complexity
  4. Apply fail-fast error handling at the right boundaries
II

Phase II

System Designer

You move beyond individual modules and learn to design systems that evolve safely, with stable boundaries and well-directed dependencies.

Reference for this phase: Patterns Quick Reference, indexed by the problem you have.

Prerequisites

  • Phase I, or you already control dependency direction in code you own.
  • A codebase with enough folders that they import each other.
  • Somewhere you have felt shared mutable state cost you a day.

Exit capabilities

  • Choose classes or functions from what must change, not from habit.
  • Organize modules around boundaries and enforce the import rules with a test.
  • Keep concurrency, I/O and events outside the domain, behind adapters.

1. Writing Flexible and Composable Code

Structure code so behavior can evolve without constant rewrites.

  1. Decide when to use classes and when simple functions are enough
  2. Inject behavior using strategies and higher-order functions
  3. Use protocols and abstract base classes to design clean extension points
  4. Build memory-efficient data pipelines with generators and streaming

2. Managing Complexity in Growing Applications

Prevent complexity from spreading through your codebase.

  1. Identify and reduce global coupling in applications
  2. Manage shared state and understand state ownership
  3. Design practical and maintainable error handling strategies
  4. Organize modules and folders around responsibilities and boundaries

3. Designing Systems That Scale

Design applications that integrate cleanly with external systems and asynchronous workflows.

  1. Apply Ports & Adapters to isolate infrastructure concerns
  2. Keep concurrency and async execution out of domain logic
  3. Use event-driven architecture to decouple workflows and components
  4. Understand when to use libraries/packages vs building solutions yourself
III

Phase III

Master Designer

You learn to make architectural decisions under real constraints, balancing trade-offs while keeping systems maintainable long-term.

Reference for this phase: the Trade-Offs Cheat Sheet — every trade-off below, with the signal that you chose wrong.

Prerequisites

  • Phases I–II, or you can already isolate infrastructure behind ports.
  • One decision actually pending at work — build vs buy, sync vs async — to spend these lessons on.
  • Enough history with a system to have seen a cheap decision become expensive.

Exit capabilities

  • Write both columns of a trade-off, with a unit of decision and a reversibility class.
  • Price a build-vs-buy argument down to a break-even year.
  • Take debt deliberately, recorded with its interest and a repayment trigger.

1. Managing Complexity Trade-Offs

Learn how to balance flexibility, simplicity, and reuse when designing software.

  1. Build vs Buy — write both cost ledgers, then apply the differentiator test that overrules them
  2. Abstraction vs Duplication — price the two rents, and refuse the abstraction that has not been earned
  3. Configuration vs Convention — run the measured-variation test on every knob, and clear the graveyard
  4. Generality vs Specificity — tell earned generality from speculative, and strip out the difference

2. Managing System Trade-Offs

Design scalable systems while keeping operational complexity under control.

  1. Synchronous vs Asynchronous Systems — choose per workflow, and answer the async failure inventory before adopting it
  2. Consistency vs Availability — cost a stale read against a timeout, per operation rather than per database
  3. Coupling vs Coordination — choose which currency you pay, and write the compatibility contract down
  4. Performance vs Maintainability — demand a number first, then hide the hot path behind a deep module

3. Managing Evolution Trade-Offs

Make architectural decisions that allow software to evolve without losing quality.

  1. Stability vs Speed of Change — slice any large change into small reversible steps, and remove the machinery after
  2. Isolation vs Integration — draw context lines where meanings diverge, not where the words happen to match
  3. Correctness vs Delivery Speed — classify a change as reversible or not, and spend the apparatus accordingly
  4. Short-Term Productivity vs Long-Term Maintainability — take the loan deliberately, and record it with an interest line and a trigger
IV

Phase IV

Initiative Lead

You lead a 6–8 person product, design, and engineering team from an ambiguous brief through discovery, architecture, delivery, rollout, and learning.

Reference for this phase: the Initiative Lead Playbook — every workshop and artifact below, ready to copy.

Prerequisites

  • Phases I–III, or equivalent architecture experience under real constraints.
  • A real initiative to apply this to — or the returns-resolution case the lessons carry throughout.
  • Working relationships with a product and a design counterpart, even informal ones.

Exit capabilities

  • Turn a brief into outcomes, guardrails, assumptions, and explicit decision rights.
  • Turn vague quality goals into measurable drivers, and preserve the reasoning in ADRs.
  • Sequence a walking skeleton and release through gates with rehearsed reversal.

1. Frame the Work

Turn requested output into a shared problem, credible options, and a thin path to evidence.

  1. Turn a product brief into an outcome, guardrails, scope, constraints, and explicit unknowns
  2. Run brainstorming that produces independent options, tested assumptions, useful dissent, and a decision
  3. Discover behavior, domain language, policies, waiting, and candidate boundaries from a real workflow
  4. Build a story map and cut executable, end-to-end slices that earn product and technical evidence

2. Design the Smallest Responsible System

Make architecture answer measurable forces, durable state, and consequential decisions.

  1. Turn vague quality goals into measurable scenarios that shape design and tests
  2. Use context, container, and dynamic views to choose evidence-based system and ownership boundaries
  3. Design state transitions, authoritative data, failure semantics, privacy, and compatibility as one contract
  4. Compare real options, buy targeted evidence with spikes, and preserve reasoning in concise ADRs

3. Deliver, Operate, and Learn

Organize the team and rollout so integration, risk, and outcome evidence arrive while choices remain.

  1. Sequence a walking skeleton, evidence milestones, dependencies, and an honest forecast
  2. Establish decision rights, low WIP, collaborative ownership, useful cadence, and objective escalation
  3. Match tests to risk and release through observable stages with explicit gates and reversal
  4. Use evidence to continue, change, or stop, then transfer ownership and remove temporary machinery
V

Phase V

System Architect

You design a system from scratch in the order that makes it worth building: problem, use cases, domain model, behavior and state, rules, responsibilities, components, contracts, data, architecture, deployment — each stage deciding the next.

Reference for this phase: the Glossary (use case, operation contract, state machine) and Design Principles (deep modules).

Prerequisites

  • Phase IV, or you have carried at least one system design end to end.
  • A green-field system, a replacement, or a subsystem you can design in sequence.
  • Access to whoever owns the problem — the first three lessons are interviews, not diagrams.

Exit capabilities

  • Model a domain and cut boundaries by responsibility and rate of change.
  • Design state machines, invariants and contracts before choosing storage.
  • Choose an architecture style from drivers, and design a reversible release path.

1. Understand the Problem and the Domain

Find the valuable complexity before drawing any box.

  1. Analyze goals, constraints, and where the valuable complexity lives
  2. Extract the domain model and its vocabulary from real scenarios
  3. Cut boundaries by responsibility, change, and ownership

2. State, Invariants, and Components

Make the durable truths explicit, then carve the code that guards them.

  1. Design state as a machine with actors, rules, and history
  2. Place every rule where it can be enforced, atomically
  3. Carve components as deep modules hiding change

3. Contracts, Data, Architecture, Deployment

Agree the seams, choose the storage and the style, and make it all reversible.

  1. Design internal and external contracts with explicit evolution
  2. Map the model to storage and plan reversible migrations
  3. Choose the architecture style from drivers, not fashion
  4. Design the pipeline, migrations, and reversible release path

Prove it: practice, assessment, and evidence

Lessons teach; these are where you find out whether the teaching took. Everything below uses the same returns-resolution initiative the lessons build, so the artifacts compound instead of scattering.

Worked capstone

The complete returns-resolution packet, done well — frame, assumption map, workflows, story map, drivers, C4 views, contracts, an ADR with the rejected options, delivery map, team charter, rollout, and closeout. Then the same packet done badly, and reviewer notes on which differences actually change the outcome.

You walk away with: your own packet, and a defensible reason for every difference from the strong one

Companion code lab

One intentionally flawed Python system — mixed domain and infrastructure, global state, leaking repository and vendor contracts, weak invariants, a compatibility-sensitive API, a migration needing expand/contract, and some plausible-looking AI-generated code. Runs locally with one command; a checkpoint per phase, with reference solutions that explain forces rather than declare a winner.

You walk away with: a codebase you improved, protected by characterization tests and fitness functions

Assessments

An entry diagnostic that routes you to the right phase, a scored assessment after each phase, the capstone assessment against a twelve-dimension rubric, and an exit diagnostic on scenarios comparable to the entry one.

You walk away with: a record of where your judgment is consistent and where it is not

Brownfield modernization

Most technical leaders inherit a system rather than starting one. A coupled monolith with real customers, an undocumented shared database, an API that cannot change atomically, and a deadline-driven initiative that must continue throughout — worked with characterization tests, seams, strangler fig, expand/contract, a debt ledger, and one decision not to extract a service.

You walk away with: a modernization sequence in which every step is deployable and reversible

Decision-change simulations

Eight scenarios that give you incomplete information, let you commit, and then change the evidence: a vendor misses its latency target, the pilot loses four weeks, security finds a new trust boundary, volume arrives ten times over forecast. You decide continue, change, pause or stop — and supersede the affected decisions without rewriting history.

You walk away with: practice at adapting coherently, which no amount of hindsight-perfect design teaches

Portfolio guide

How to turn this work into evidence somebody else will credit: anonymizing workplace artifacts, a portfolio template, an architecture narrative for a technical interview, a five-minute executive summary, the deeper technical-review version of the same initiative, and how to describe your contribution honestly against the team's.

You walk away with: one initiative you can tell at three depths without leaking anything proprietary

Artifact template pack

Blank and completed versions of every artifact the course produces — initiative frame, assumption map, workshop agenda, workflow and EventStorming board, story map and example card, driver table, C4 checklist, state and contract review, option table, spike brief, ADR, delivery map, team charter, rollout contract, weekly review, closeout. Printer-friendly HTML plus Markdown for your repository.

You walk away with: the blanks, so the next initiative starts from a page rather than a blank page

Supplements

Five focused pieces the phases point at but do not have room for: multi-team architecture (Conway's law, team APIs, governance without a review board), architecture economics (cost of delay, total cost of ownership), technical influence (executives, uncertainty, dissent), security, privacy and accessibility by design, and working with AI without letting generated artifacts stand in for evidence.

You walk away with: the organizational, economic and safety vocabulary that architecture decisions actually turn on

How the rubric works

Every capstone dimension is scored against four behaviourally anchored levels rather than a number: Developing identifies symptoms and states a preference without forces or evidence; Practicing names the relevant forces and proposes a workable design with some consequences missing; Lead-ready compares credible options, accepts the costs explicitly, and connects the decision to evidence and to operation; Architect-ready reasons across technical, organizational, economic and evolutionary consequences while keeping the decision understandable and revisable.

Because the anchors describe behaviour rather than a correct answer, more than one design can score well — every score has to cite observable evidence in your own work, and every score comes with the next specific thing to practise rather than a grade. See the full twelve-dimension table in the capstone rubric.

See it before you commit

One sample lesson from each phase, complete and unlocked: 0001 · Seeing Coupling & Cohesion (Phase I), 0019 · Identifying and Reducing Global Coupling (Phase II), 0027 · Build vs Buy (Phase III), 0039 · Turn a Product Brief into an Initiative Frame (Phase IV), and 0054 · Design State as a Machine, Not a Column (Phase V). The completed capstone packet and the rubric are open too — the evidence for what this course claims should be readable before you spend time on it.

No pilot feedback is published here yet. This course has not run a pilot cohort, so there is nothing honest to quote about changed workplace behaviour; inventing testimonials would contradict the standard of evidence the course spends sixty lessons arguing for. Judge it on the sample lessons, the worked capstone, and the rubric instead.

Reference documents

Lessons are rarely revisited — these are. They are the compressed essence of the course, formatted for quick lookup. Print them; pin them.

Glossary

One hundred fifty-eight terms, A–Z, each with the words to avoid and the page that teaches it. If terms conflict with other sources, this document wins.

The canonical vocabulary of the course

Design Principles

Nineteen principles, each with its job, the check that applies it, and the way it fails when followed as a rule.

Core & System Designer reference

Patterns Quick Reference

Nineteen patterns with a Python skeleton each, indexed by the problem you have rather than the pattern's name.

System Designer reference

Trade-Offs Cheat Sheet

All twelve Master Designer trade-offs: the forces, the deciding questions, the default, and the signal you chose wrong.

Master Designer reference

Initiative Lead Playbook

Twelve reusable templates covering the brief, workshops, architecture, decisions, delivery, team operation, rollout, and closeout.

Initiative Lead reference

Resources

Every primary source the lessons cite: books with chapter pointers, articles, talks, and the communities where trade-offs become judgment.

The sources behind the course

Each reference entry names the lesson that teaches it, and each lesson links back to the entries it uses — so either direction works once you are past the first read.

Before you begin

Mission: build the judgment of a senior technical leader — code that stays clear as it grows, systems that evolve without rewrites, AI used without losing control, and cross-functional initiatives led from ambiguity to evidence. Each lesson returns to this.