codebase-design
Codebase Design
Design deep modules: a lot of behavior behind a small interface, placed at a clean seam, testable through that interface.
Glossary
Use these terms exactly, in place of the words each entry lists under Avoid: consistent language is the whole point.
Module: anything with an interface and an implementation. Deliberately scale-agnostic: a function, class, package, or tier-spanning slice. Avoid: unit, component, service.
Interface: everything a caller must know to use the module correctly: the type signature, but also invariants, ordering constraints, error modes, required configuration, and performance characteristics. Avoid: API, signature, the TypeScript interface keyword, a class's public methods (all too narrow: they name only the type-level surface).
Implementation: what is inside a module, its body of code. Distinct from Adapter: a thing can be a small adapter with a large implementation (a Postgres repo) or a large adapter with a small implementation (an in-memory fake). Reach for "adapter" when the seam is the topic; "implementation" otherwise.
Depth: leverage at the interface. The amount of behavior a caller (or test) can exercise per unit of interface they have to learn. A module is deep when a large amount of behavior sits behind a small interface, shallow when the interface is nearly as complex as the implementation. Ousterhout weighs the functionality a module provides against the complexity of its interface; measure that leverage, not a ratio of implementation lines to interface lines, which rewards padding the implementation.