update skills

This commit is contained in:
nessar committed 2026-09-25 10:00:00 +02:00
1 parent 9fb18f57ec
commit ff86cf48b4
82 files changed
+2156 -650

No files matched your search

+8 -8
View File
@@ -9,17 +9,17 @@ Design **deep modules**: a lot of behaviour behind a small interface, placed at
## Glossary
Use these terms exactly — don't substitute "component," "service," "API," or "boundary." Consistent language is the whole point.
Use these concepts to explain the design, while preserving the repository's actual names and domain vocabulary. A component, service, or API can be the module or interface under discussion; explain the distinction when it matters instead of banning familiar terms.
**Module** — anything with an interface and an implementation. Deliberately scale-agnostic: a function, class, package, or tier-spanning slice. _Avoid_: unit, component, service.
**Module** — anything with an interface and an implementation: a function, component, service, class, package, or tier-spanning slice.
**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 (too narrow — they refer only to the type-level surface).
**Interface** — everything a caller must know: signatures, invariants, ordering, errors, configuration, and relevant performance characteristics. An API signature alone may describe only part of that contract.
**Implementation** — what's 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 behaviour a caller (or test) can exercise per unit of interface they have to learn. A module is **deep** when a large amount of behaviour sits behind a small interface, **shallow** when the interface is nearly as complex as the implementation.
**Seam** _(Michael Feathers)_ — a place where you can alter behaviour without editing in that place; the *location* at which a module's interface lives. Where to put the seam is its own design decision, distinct from what goes behind it. _Avoid_: boundary (overloaded with DDD's bounded context).
**Seam** _(Michael Feathers)_ — a place where behavior can be varied without editing that place. Distinguish a test or substitution seam from a domain or deployment boundary when the difference affects the design.
**Adapter** — a concrete thing that satisfies an interface at a seam. Describes *role* (what slot it fills), not substance (what's inside).
@@ -61,8 +61,8 @@ When designing an interface, ask:
- **Depth is a property of the interface, not the implementation.** A deep module can be internally composed of small, mockable, swappable parts — they just aren't part of the interface. A module can have **internal seams** (private to its implementation, used by its own tests) as well as the **external seam** at its interface.
- **The deletion test.** Imagine deleting the module. If complexity vanishes, it was a pass-through. If complexity reappears across N callers, it was earning its keep.
- **The interface is the test surface.** Callers and tests cross the same seam. If you want to test *past* the interface, the module is probably the wrong shape.
- **One adapter means a hypothetical seam. Two adapters means a real one.** Don't introduce a seam unless something actually varies across it.
- **Prefer behavior-level test surfaces.** Test through the relevant contract, while retaining focused checks for internal algorithms or integration invariants when they catch failures the higher interface does not.
- **Justify seams by a current need.** Test isolation, ownership, external integration, or real variation may justify a boundary even with one runtime implementation. Do not add an adapter merely to satisfy a count, or a speculative abstraction with no concrete benefit.
## Designing for testability
@@ -80,7 +80,7 @@ Good interfaces make testing natural:
}
```
2. **Return results, don't produce side effects.**
2. **Prefer pure results for calculations; keep necessary effects explicit.**
```typescript
// Testable
@@ -106,7 +106,7 @@ Good interfaces make testing natural:
- **Depth as ratio of implementation-lines to interface-lines** (Ousterhout): rewards padding the implementation. We use depth-as-leverage instead.
- **"Interface" as the TypeScript `interface` keyword or a class's public methods**: too narrow — interface here includes every fact a caller must know.
- **"Boundary"**: overloaded with DDD's bounded context. Say **seam** or **interface**.
- **Unqualified boundaries**: clarify whether a boundary concerns tests, domain ownership, deployment, or caller contracts when that distinction matters.
## Going deeper