PWI
Aphorism Glossary
The recurring phrases used across the chapters, and what each one actually means. A phrase means one thing everywhere it appears, which is the point of writing the definitions down once.
Chapters list which aphorisms apply to them. The definitions live here, so the same phrase carries the same meaning in every chapter that invokes it.
Where a chapter on this site uses an aphorism, it is listed underneath the definition.
Core Design Aphorisms
- #“Express your intent in code, not comments”
Names, types, signatures, and structure should communicate what the code means. Comments explain why, constraints, or protocol quirks; they do not narrate obvious code.
Used inClass Design in C#, Class Design in Python, Naming Conventions in C#, Naming Conventions in Python, Type Annotations in Python
- #“Don't make me think”
Code should read as a clear sequence of domain intent. High-level methods show what happens; lower-level methods and collaborators handle how.
Used inArchitecture Layers in C#, Architecture Layers in Python, Method Design in C#, Method Design in Python, Naming Conventions in C#, Naming Conventions in Python
- #“Don't make me wonder”
Remove ambiguity from contracts. If absence is impossible, do not mark a value optional. If only `None` has absence meaning, do not also treat empty strings or other sentinels as absence.
Used inLINQ and Query Semantics in C#, Method Design in C#, Naming Conventions in C#, Naming Conventions in Python, Type Annotations in Python
- #“We don't expose our privates”
Internal implementation stays hidden. Public surface area is intentional, and foreign/provider details do not leak across system boundaries.
Used inArchitecture Layers in C#, Architecture Layers in Python
- #“Need-to-know basis”
Pass only the values a method needs. Do not pass broad objects or providers when a smaller, explicit value or DTO expresses the contract.
Used inArchitecture Layers in C#, Architecture Layers in Python, Method Design in C#, Method Design in Python
- #“Don't invent names”
A single instance of a well-named type is named after the type (`http_client`, `xml_schema`); what `get_x` returns is called `x`; an operation keeps one name through every layer it flows through. Inventing a fresh name at each site is where wrong names come from — and if the type's name keeps feeling insufficient, fix the *type's* name, not the variable's.
Used inNaming Conventions in C#, Naming Conventions in Python
- #“Caveat emptor”
Internal methods trust their callers. Validation happens at domain entry points and external boundaries, not repeatedly inside trusted internal flows.
Used inMethod Design in C#, Method Design in Python, Validation and Exception Handling in C#, Validation and Exception Handling in Python
- #“Lock the front door, lock the back door so you're safe in the house”
Validate and normalize data at every ingress boundary. The front door is the normal business entry point. Back doors are all other places foreign data enters, such as configuration, external services, files, messages, or structured LLM output. Inside the house, data is clean and trusted.
Used inValidation and Exception Handling in C#, Validation and Exception Handling in Python
- #“Don't let the boogieman in”
Invalid states must be blocked at boundaries so internal code never has to defend against impossible values.
Used inValidation and Exception Handling in C#, Validation and Exception Handling in Python
- #“Rule of thirds”
Do not generalize until the pattern has appeared enough times to prove its shape. Complex repeated logic may justify earlier extraction when duplication itself creates risk.
Used inClass Design in C#, Class Design in Python, Method Design in C#, Validation and Exception Handling in C#, Validation and Exception Handling in Python
- #“Fail fast and fail visibly”
Fail at the point of truth with a clear exception instead of silently producing wrong results, fabricated defaults, or hidden partial success.
Used inLINQ and Query Semantics in C#, Validation and Exception Handling in C#, Validation and Exception Handling in Python
Design Process Aphorisms
- #“Common practice is not common sense”
The fact that a practice is widely followed says only that it is widely followed. Question every convention against the value it actually delivers; adopt or reject on evidence, not popularity.
- #“We do what we can, not what we should”
The streetlight trap: people gravitate to the work they know how to do (and then rationalize it) instead of the work the problem requires. Catch yourself choosing a technique because it is familiar rather than because it is right.
- #“Never be married to your design”
A week of design work is not a reason to keep a design. When a better idea arrives — from anyone — throw yours away without ceremony. Designs earn their keep continuously or not at all.
- #“When in doubt, leave it out”
If the requirement in hand does not demand a parameter, property, method, or abstraction, do not add it. Imagining the future makes APIs worse, not safer; certainty comes from requirements, not speculation.
- #“A bad abstraction is worse than no abstraction”
Wrong abstractions actively mislead every reader and harden into load-bearing structure. If you are not sure an abstraction is right, don't abstract yet — duplication is recoverable, a wrong abstraction resists removal (Sandy Metz: "the best way forward is to go back").
Structure and Boundary Aphorisms
- #“Orchestrate or implement, never both”
A method either coordinates named steps or performs low-level work. Mixing both creates inconsistent abstraction levels.
- #“Show me the what, not the how”
Public workflows and tests should reveal intent at a glance. Detailed mechanics belong behind named methods, collaborators, or assertion helpers.
- #“Protocols over inheritance”
Prefer structural contracts via `Protocol` when behavior depends on a shape rather than a shared implementation hierarchy.
- #“Infrastructure once, domain every time”
Shared infrastructure handles wiring and cross-cutting mechanics. Domain classes and subclasses focus on domain-specific behavior.
- #“State/behavior separation”
State-only models are immutable DTOs. Behavior lives in separate classes that do not accumulate mutable state across calls.
Messaging and Test Aphorisms
- #“Frozen immutability”
Message and DTO instances do not mutate after creation. Use replacement/copy construction when a modified value is required.
- #“Tests are executable specifications”
Test names, structure, and assertion messages should document system behavior in language a non-implementer can understand.
- #“The prompt drives the design”
An LLM processor exists to execute a specific prompt contract; the prompt's requirements shape the processor's API and responsibilities.