Software Design Reference Reference · Glossary

Reference document · canonical vocabulary

Glossary

The canonical language of this course. Every lesson uses these terms in these senses; when a term is used loosely elsewhere, the resolution chosen here wins. Each entry carries the lesson that teaches it, and an Avoid line naming the words that blur it.

All 70 terms, A–Z Abstraction· Adapter· Aggregate· Anti-corruption layer· Architecture Decision Record· Architecture driver· Assumption map· Blast radius· Boundary· Bounded context· Branch by abstraction· Change amplification· Characterization test· Cohesion· Composition· Composition root· Config graveyard· Control coupling· Correlation id· Coupling· Dead-letter queue· Decision rights· Deep module· Dependency direction· Domain· Domain invariant· DRY — Don't Repeat Yourself· Entity· Event-driven architecture· Eventual consistency· Expand / contract· Fail-fast· False DRY· Feature flag· Fitness function· Global coupling· Higher-order function· Idempotency key· Idempotent· Information hiding· KISS — Keep It Simple· Law of Demeter· Message bus· Port· Product outcome· Protocol· Quality-attribute scenario· Reason to change· Repository· Rollout gate· Rule of three· Seam· Shared kernel· Shared state· Speculative generality· SRP — Single Responsibility Principle· Story map· Strangler fig· Strategy pattern· Tell, Don't Ask· Tolerant reader· Trade-off· Train wreck· Unit of work· User story· Value object· Vertical slice· Walking skeleton· Work in progress· YAGNI — You Ain't Gonna Need It

Structure and complexity

The vocabulary for talking about shape: what makes code hard to change, and how you measure it.

Coupling

How much one module depends on the internals or behavior of another. Low coupling means a module can change without forcing changes in its neighbors.

Avoid: tight coupling, entanglement, "spaghetti"

Taught in: lesson 0001

Cohesion

How strongly the elements inside one module belong together — whether they serve one purpose. High cohesion means a module has one reason to exist.

Avoid: god class, grab-bag module, "utils" folder

Taught in: lesson 0001

SRP — Single Responsibility Principle

A module should have one reason to change. The reason, not the responsibility, is the unit of design.

Avoid: "does one thing" (too vague), "one method" (too literal)

Taught in: lessons 0002, 0006

Reason to change

The concrete force (a new requirement, a new technology, a new policy) that would make you edit a module. Design units of code around single reasons to change.

Avoid: "responsibility" (fuzzier), "feature" (too coarse)

Taught in: lesson 0006

Change amplification

The number of places you must edit to make one logical change. It is the most direct measurement of design debt.

Avoid: "shotgun surgery" (the smell it produces)

Taught in: lessons 0006, 0033

DRY — Don't Repeat Yourself

Every piece of knowledge should have a single, unambiguous representation in the system. DRY targets knowledge, not text: two identical lines can encode different knowledge.

Avoid: copy-paste, WET ("write everything twice")

Taught in: lessons 0002, 0028

False DRY

Deduplication of text that encodes two different pieces of knowledge. The two copies look identical today because the facts happen to coincide; merging them couples parties that will diverge, and the first divergence has to be bent into the shared shape.

Avoid: “removing duplication” (when the duplication was never knowledge)

Taught in: lessons 0002, 0028

Rule of three

Wait for the third occurrence before extracting an abstraction. At one occurrence there is no pattern; at two the shape is a guess; by three the variation is visible and the change-rent of the copies is real.

Avoid: “don't repeat yourself” read as “never type it twice”

Taught in: lessons 0002, 0028, 0030

KISS — Keep It Simple

Prefer the solution with the least complexity that meets the requirement. Simplicity is a design target, not a default.

Avoid: cleverness, over-engineering, speculative generality

Taught in: lesson 0002

YAGNI — You Ain't Gonna Need It

Do not build capability you have no current evidence of needing. Unused generality is paid for forever and used never.

Avoid: speculative features, "just in case" hooks

Taught in: lessons 0002, 0030

Speculative generality

Parameters, hooks and layers built for cases that do not exist. It is paid for on every read of the current code and used by nobody. The counter-test: does the generality make today's case simpler? (Ousterhout)

Avoid: “future-proofing”, “extensible by design”

Taught in: lesson 0030

Abstraction

A simplified interface that hides the complexity of what lies behind it. A good abstraction is deeper than the sum of its parts.

Avoid: leaky abstraction, façade without substance

Taught in: lessons 0028, 0030

Deep module

A module with a small, simple interface hiding substantial implementation. The opposite of a shallow module, which exposes most of its work through the interface. (Ousterhout)

Avoid: "thin layer" (a shallow module by another name)

Taught in: lessons 0001, 0034

Information hiding

Keeping design decisions that are likely to change inside a module, invisible to its users.

Avoid: encapsulation (usually used for the same idea, but includes runtime state protection)

Taught in: lessons 0019, 0034

Boundary

The edge of a module where one set of concerns hands off to another. Boundaries are where you enforce invariants, translate representations, and choose failure behavior.

Avoid: "layer" (a boundary is a seam, a layer is a convention)

Taught in: lessons 0014, 0022

Seam

A place where you can alter behavior without editing the code in question — a hook, an interface, a dependency-injection point. Seams make change and testing possible.

Avoid: "extension point" (a seam with a designed-for purpose)

Taught in: lessons 0005, 0035

Objects and the domain

The words for the things the software is actually about, and the shapes that protect them.

Domain

The problem space the software exists to serve: the rules, entities, and workflows that are true regardless of technology.

Avoid: "business logic" (if you must, mean the same thing)

Taught in: lesson 0011

Domain invariant

A rule the domain cannot violate, enforced by the domain itself — not by callers' good behavior. Example: an order can never be confirmed twice.

Avoid: business rule (weaker: often means "policy")

Taught in: lesson 0011

Value object

An immutable object whose identity is its value: two instances with equal fields are interchangeable. Safe to share, trivial to test.

Avoid: mutable DTOs, "entity-lite"

Taught in: lesson 0012

Entity

An object with a continuous identity across changes, tracked over time.

Avoid: "model" (overloaded), "record"

Taught in: lesson 0012

Aggregate

A cluster of domain objects treated as one unit for changes, with a single root that guards the invariants of the whole cluster.

Avoid: aggregate root (the root is one part; the aggregate is the cluster)

Taught in: lesson 0012

Repository

A domain-facing collection-like interface for retrieving and persisting aggregates, hiding the storage technology behind it.

Avoid: "DAO" (data-oriented, leaks storage thinking), repository leaking query APIs

Taught in: lesson 0013

Unit of work

The object that owns a transaction's boundary: what is written together, committed together, and rolled back together. Repositories operate inside it; the domain never sees it.

Avoid: save() scattered through the domain, autocommit-per-call

Taught in: lesson 0013

Law of Demeter

A method should only talk to its immediate neighbors: itself, its own fields, its arguments, objects it creates, and the direct members of its own collection. No chain-walking into strangers.

Avoid: "train wrecks" like a.b().c().d(), the principle of least knowledge

Taught in: lesson 0003

Tell, Don't Ask

Ask an object to do something for you instead of interrogating its state and doing it yourself. The natural companion of the Law of Demeter.

Avoid: getter chains, "ask, then act" sequences

Taught in: lesson 0003

Train wreck

A chain of calls that walks through objects the caller does not own — order.customer.address.city. The caller now depends on the internal geography of three objects, and any restructuring of them breaks it.

Avoid: “fluent interface” (a builder returning self is not a wreck)

Taught in: lesson 0003

Composition

Building behavior by holding objects and delegating to them, rather than inheriting from them.

Avoid: "has-a" (shorthand only); composition does not mean "put everything in one class"

Taught in: lesson 0007

Strategy pattern

Extracting a varying behavior behind an interface so the behavior can be swapped at runtime without touching its caller.

Avoid: "policy" (same shape, different name)

Taught in: lessons 0004, 0008

Higher-order function

A function that takes or returns a function. In Python it is the cheapest strategy interface there is: no protocol, no class, no registration.

Avoid: a one-method class used once

Taught in: lesson 0016

Protocol

A structural interface in Python: an object conforms to it by having the right methods, no inheritance required.

Avoid: "duck typing" (untyped protocols), abstract base class (nominal, heavier)

Taught in: lesson 0017

Dependencies and boundaries

Who is allowed to know about whom, and where that rule is written down.

Dependency direction

Which way arrows point between modules. Well-directed dependencies point inward: domain code depends on nothing; infrastructure depends on domain.

Avoid: upward dependencies, dependency cycles

Taught in: lesson 0009

Port

An interface on the edge of a module that defines what the module needs from the world (driven port) or offers to it (driving port). The domain defines the ports; the world provides the adapters.

Avoid: interface owned by the infrastructure

Taught in: lessons 0009, 0023

Adapter

Code that translates between a port (our interface) and a concrete external thing — a database, an API, a file format — so the external thing never touches the domain.

Avoid: wrapper (when the translation is cosmetic), leaky adapter

Taught in: lessons 0008, 0023

Composition root

The single place — usually one function near the program's entry point — where every concrete adapter is constructed and injected. Nothing else in the system names a technology.

Avoid: service locator, ambient container, “wiring everywhere”

Taught in: lessons 0019, 0023

Anti-corruption layer

An adapter at the edge of a bounded context that translates another context's vocabulary into this one's, so a foreign model never leaks inward. (Evans)

Avoid: “just import their types”, a shared DTO package

Taught in: lesson 0036

Bounded context

The boundary within which one model and one vocabulary are consistent. The same word may mean different things in two contexts — and that is the signal to keep them apart.

Avoid: “the one true model”, a global schema

Taught in: lesson 0036

Shared kernel

The small, stable set of concepts two contexts genuinely share and agree to change together. Integration chosen on purpose, not integration by accident.

Avoid: a “core” or “common” package that only grows

Taught in: lesson 0036

Control coupling

One module steering another's internal path with a flag or mode argument, so the caller must understand the callee's branches. The usual fix is to inject the behaviour instead.

Avoid: boolean parameters, mode="..." strings

Taught in: lesson 0016

Global coupling

Dependence on shared, reachable-from-anywhere state or services (singletons, module globals, ambient context). Changes to one consumer affect all consumers — silently.

Avoid: "ambient state", hidden global dependencies

Taught in: lesson 0019

Shared state

State that more than one component reads or writes. The owner is whoever is responsible for its correctness; unowned shared state is the source of most concurrency bugs.

Avoid: "global state" (a species, not the genus)

Taught in: lesson 0020

Fitness function

An automated check that an architectural property still holds — a test that fails the build when a dependency arrow, a layer rule, or a latency budget is violated. (Ford, Parsons & Kua)

Avoid: a README rule, a convention nobody enforces

Taught in: lesson 0022

Runtime, failure and evolution

What the system does when the world misbehaves, and how it changes without stopping.

Fail-fast

Failing as close to the cause as possible, loudly and immediately, instead of letting a bad value travel and corrupt far from its origin.

Avoid: silent None, ignored errors, deferred exceptions

Taught in: lessons 0014, 0021

Event-driven architecture

Components communicate by publishing and consuming events rather than by calling each other directly, so producers don't know their consumers.

Avoid: "event-based" (fine), "message-driven" (a sibling, not the same)

Taught in: lesson 0025

Message bus

A channel that routes events or commands from publishers to subscribers, decoupling the two sides.

Avoid: "event bus" (a species of message bus)

Taught in: lesson 0025

Idempotent

An operation that produces the same end state whether it runs once or five times. Idempotence is what makes at-least-once delivery survivable and retries safe.

Avoid: “safe to retry” (true only once the operation is idempotent)

Taught in: lessons 0031, 0032

Idempotency key

A caller-generated identifier for one intent, reused across every retry of that intent, so the receiver can return the first answer instead of acting twice.

Avoid: a fresh id per attempt (which buys nothing)

Taught in: lesson 0032

Dead-letter queue

Where a message goes after its handler has failed its allotted attempts. It only counts as a design if a human actually watches it.

Avoid: infinite retries, silent drops

Taught in: lesson 0031

Correlation id

An identifier attached to an event and to every log line produced while handling it, so one workflow can be followed across handlers that share no call stack.

Avoid: “grep the timestamps”

Taught in: lesson 0031

Eventual consistency

A guarantee that replicas converge if writes stop — with no promise about what a read sees in the meantime. Useful when a stale answer is cheap; dangerous when the reader will act on it as if it were current.

Avoid: “inconsistent” (it is a guarantee, not the absence of one)

Taught in: lesson 0032

Tolerant reader

A consumer that requires only the fields it uses and ignores everything else, so producers can add fields without a coordinated release.

Avoid: strict schema validation on inbound events

Taught in: lesson 0033

Characterization test

A test that records what code currently does, not what it should do — written to lock behaviour before restructuring unfamiliar or AI-generated code. (Feathers)

Avoid: “I'll refactor first and test after”

Taught in: lessons 0005, 0037

Strangler fig

A pattern for replacing a system incrementally: route new behavior around the old implementation, growing the new one until the old one can be deleted.

Avoid: "big bang rewrite" (the anti-pattern)

Taught in: lesson 0035

Branch by abstraction

A safe transition technique: insert an abstraction over a component, migrate all users to it, then swap the implementation behind it.

Avoid: long-lived feature branches (the coordination cost is the point)

Taught in: lesson 0035

Expand / contract

A four-step data migration — add the new field and write both, backfill, switch reads, then stop writing and drop the old — so a rename becomes four reversible deploys instead of one irreversible one. Also called parallel change.

Avoid: the one-step rename, the “quick” migration

Taught in: lesson 0035

Feature flag

A runtime switch that separates deploying code from releasing behaviour, so rollback is a flip rather than a revert. A flag that outlives its transition becomes configuration debt.

Avoid: permanent flags, flags used as a state model

Taught in: lesson 0035

Config graveyard

The accumulated settings nobody has ever varied: knobs added “just in case”, each one documented, validated, tested and combinatorially possible — for no measured variation at all.

Avoid: “configurable”, “flexible” (as unexamined virtues)

Taught in: lesson 0029

Trade-off

A decision between forces that cannot both be maximized. The craft is making the trade-off explicit, deliberate, and reversible — not avoiding it.

Avoid: "best practice" (implies no cost), "silver bullet"

Taught in: lessons 0027, 0038

Initiative leadership

The vocabulary for turning an ambiguous brief into measurable system and team decisions.

Product outcome

An observable change in user or business behaviour, stated with a baseline, target, cohort, and time boundary. It preserves freedom to change the solution while holding the initiative accountable for its effect.

Avoid: feature, deliverable, launch date, “ship the portal”

Taught in: lesson 0039

Assumption map

A map of beliefs by impact if false and strength of evidence, often grouped as value, usability, feasibility, and viability. The high-impact, weak-evidence corner becomes the discovery priority.

Avoid: risk list with no evidence axis, brainstorm vote

Taught in: lesson 0040

User story

A placeholder for a conversation about one user's need and the behaviour that may satisfy it. The sentence alone is not a requirement; examples provide confirmation.

Avoid: mini-specification, task disguised as user value

Taught in: lesson 0042

Story map

A two-dimensional product map: user activities run left to right as a journey, while alternatives and detail run downward. Horizontal lines cut coherent release or learning slices across the journey.

Avoid: flat backlog, dependency graph, feature inventory

Taught in: lesson 0042

Vertical slice

A narrow piece of observable behaviour that crosses the necessary technical layers end to end. It is small by cohort, rule, variation, or quality threshold—not hollowed into disconnected component tasks.

Avoid: “backend story”, schema-only milestone, horizontal layer

Taught in: lesson 0042

Architecture driver

A functional need, quality attribute, constraint, or risk important enough to shape system structure. It distinguishes between plausible designs; most requirements do not.

Avoid: every requirement, technology preference, generic “best practice”

Taught in: lesson 0043

Quality-attribute scenario

A measurable statement of how a system must respond: source, stimulus, environment, affected artifact, response, and response measure. It turns “fast” or “available” into design and test input.

Avoid: vague non-functional requirement, unmeasured “-ility”

Taught in: lesson 0043

Blast radius

The people, operations, data, components, or requests exposed when a change or failure goes wrong. Reducing blast radius makes learning and reversal cheaper.

Avoid: impact (too vague), server count alone

Taught in: lessons 0043, 0049

Architecture Decision Record

A short, durable record of one consequential decision: context, forces, credible options, decision, consequences, dissent, and a revisit trigger. A later decision supersedes rather than edits it.

Avoid: architecture novel, meeting transcript, rewritten history

Taught in: lesson 0046

Walking skeleton

The thinnest production-shaped end-to-end implementation: real build and deployment, representative boundaries and storage, telemetry, and tiny behaviour. It proves the delivery path before behavior fills it.

Avoid: throwaway prototype, complete infrastructure phase

Taught in: lesson 0047

Decision rights

An explicit statement of who makes the final call in a decision domain and whose advice they must seek. It enables broad collaboration without turning consensus into a veto.

Avoid: RACI for every task, authority left implicit

Taught in: lessons 0039, 0048

Work in progress

Work the team has started but not finished into evidence. Limiting it reduces queues, context switching, and elapsed time; swarming values system flow over individual utilization.

Avoid: everyone must stay busy, one item per specialist

Taught in: lesson 0048

Rollout gate

A decision boundary between exposure stages with explicit entry evidence, observation window, advance threshold, stop threshold, decider, and reversal. It turns launch into a controlled sequence.

Avoid: “looks good”, arbitrary percentage ramp, calendar-only gate

Taught in: lesson 0049