paulrberg/agent-skills

codebase-design

Shared vocabulary for designing deep modules.

소스 보기
원본 Skill 문서

원본 저장소의 제목, 예시, 코드, 표, 링크, 이미지를 유지해 표시합니다.

Codebase Design

Design deep modules: substantial behaviour behind a small interface at a clean seam, testable through that interface. Use this vocabulary when it clarifies a design decision. The aim is leverage for callers, locality for maintainers, and testability.

Glossary

Use these terms consistently where their distinctions matter.

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 (too narrow — they refer only to the type-level surface).

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).

Adapter — a concrete thing that satisfies an interface at a seam. Describes role (what slot it fills), not substance (what's inside).

Leverage — what callers get from depth: more capability per unit of interface they learn. One implementation pays back across N call sites and M tests.

Locality — what maintainers get from depth: change, bugs, knowledge, and verification concentrate in one place rather than spreading across callers. Fix once, fixed everywhere.

Deep vs shallow

Deep module — small interface (few methods, simple params) hiding a lot of implementation.

Shallow module (avoid) — interface nearly as large as its thin, pass-through implementation.

When designing an interface, ask:

  • Can I reduce the number of methods?
  • Can I simplify the parameters?
  • Can I hide more complexity inside?

Principles

  • 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.

Designing for testability

Good interfaces make testing natural:

  • At a real seam, accept the dependency as a parameter instead of constructing it inside the module.
  • Prefer returning results to side effects when that keeps the interface simpler.
  • Keep the surface small: fewer methods and parameters mean fewer, simpler tests.

Relationships

  • A Module has exactly one Interface (the surface it presents to callers and tests).
  • Depth is a property of a Module, measured against its Interface.
  • A Seam is where a Module's Interface lives.
  • An Adapter sits at a Seam and satisfies the Interface.
  • Depth produces Leverage for callers and Locality for maintainers.

Rejected framings

  • 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.

Output Contract

When applying this vocabulary to a design or review, report the recommended module, interface, and seam; explain how the result improves depth, leverage, locality, or testability; and identify material tradeoffs or unresolved evidence. When this skill is only supporting another requested artifact, incorporate that analysis into the artifact instead of adding a separate report.

Going deeper

categories, seam discipline, and replace-don't-layer testing.

parallel sub-agents to design the interface several radically different ways, then compare on depth, locality, and seam placement.

Forked from mattpocock/skills.

같은 저장소의 Skills

더 많은 Skills

모든 Skills