SuperAPI AI Directory

codebase-design

Design & creation

View repository

Updated 10-15 21:08

About this skill

Codebase Design

Design deep modules: a large amount of behavior behind a small interface, placed at a clean seam, testable through that interface. Everywhere you design and refactor code, use this vocabulary and these principles. The goal is: leverage for callers, locality for maintainers, testability for everyone.

Glossary

Use the following terms precisely — do not substitute "component", "service", "API", or "boundary". Using consistent language is exactly the point.

Module — Anything with an interface and an implementation. Deliberately scale-agnostic: a function, class, package, or cross-layer slice.Avoid using: unit, component, service.

Interface — Everything a caller needs to know to use the module correctly: type signatures, but also invariants, ordering constraints, error modes, required configuration, and performance characteristics.Avoid using: API, signature (too narrow — they refer only to the type-level surface).

Implementation — What is inside the module, its code body. Different from Adapter : something can be a small adapter with a large implementation (such as a Postgres repository), or a large adapter with a small implementation (such as an in-memory fake). Use "adapter" when the discussion is focused on the seam; otherwise use "implementation".

Depth — Leverage at the interface: the amount of behavior a caller (or test) can invoke per unit of interface they must learn. When a module carries a large amount of behavior behind a small interface, it is deep; when the interface is almost as complex as the implementation, it is shallow。

Seam (Michael Feathers) — A place where behavior can be changed without modifying something elsewhere; the place where a module interface lives. Where a seam goes is itself a design decision, separate from what goes behind it.Avoid using: boundary (overloaded with DDD's bounded context).

Adapter — A concrete implementation that satisfies an interface at a seam. It describes therole(what slot it fills), not the substance (what is inside).

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

Locality — The benefit maintainers get from depth: changes, defects, knowledge, and verification are concentrated in one place rather than scattered across callers. Fix once, effective everywhere.

Deep vs shallow

Deep module = small interface + large implementation:

┌─────────────────────┐
│   小型接口           │  ← 少量方法,简单参数
├─────────────────────┤
│                     │
│  深度实现            │  ← 隐藏的复杂逻辑
│                     │
└─────────────────────┘

Shallow module = large interface + small implementation (avoid):

┌─────────────────────────────────┐
│       大型接口                   │  ← 大量方法,复杂参数
├─────────────────────────────────┤
│  薄实现                         │  ← 仅透传
└─────────────────────────────────┘

When designing an interface, ask yourself:

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

Principles

  • Depth is a property of the interface, not the implementation. A deep module can internally consist of small, mockable, replaceable 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 external seams。
  • The deletion test. Imagine deleting this module. If the complexity disappears, it is a pass-through. If the complexity reappears across N callers, then it is valuable.
  • The interface is the test surface. Callers and tests cross the same seam. If you want to testacrossthe interface, the module's shape may have a problem.
  • One adapter implies a hypothetical seam. Two adapters imply a real seam. Do not introduce a seam unless something actually varies at the seam.

Designing for testability

Good interfaces make testing natural:

  1. Accept dependencies, don't create dependencies.

    // 可测试
    function processOrder(order, paymentGateway) {}
    
    // 难以测试
    function processOrder(order) {
      const gateway = new StripeGateway();
    }
    
  2. Return results, don't produce side effects.

    // 可测试
    function calculateDiscount(cart): Discount {}
    
    // 难以测试
    function applyDiscount(cart): void {
      cart.total -= discount;
    }
    
  3. Small surface area. Fewer methods = fewer tests needed. Fewer parameters = simpler test setup.

Relationships

  • Module has exactly one Interface(the surface it presents to callers and tests).
  • Depth is a property of Module measured relative to its Interface .
  • Seam is where the Module of Interface is located.
  • Adapter is located at Seam , satisfying Interface。
  • Depth produces Leveragefor callers and Locality。

Rejected framings

  • Depth as the 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 — the interface here includes every fact a caller must know.
  • "Boundary": overloaded with DDD's bounded context. Please say seam or interface。

Further reading

  • Deepening a cluster given dependencies — see DEEPENING.md: dependency classification, seam discipline, and replacement rather than layered testing.
  • Exploring alternative interfaces — see DESIGN-IT-TWICE.md: launching parallel sub-agents to design the interface in several very different ways, then comparing them in terms of depth, locality, and seam placement.