ousterhout-build-deep

by Rob ZappNo install yetNo like yetUpdated September 21, 2026Category: Engineering

What it does

Use while writing or changing code, before calling the task done, whenever the change adds an exported or importable name, creates a module, class, component, helper, hook, service or wrapper, or centralizes repeated code. Author-time checklist for building deep modules: name the decision the boundary hides, pass the depth and invariant tests, fix problems instead of relocating them, never split on size alone, and end with a short design note. Compact companion to ousterhout-quality-program, which remains the full review lens.

Install opens this entry in your AgentsRoom desktop app. If the app is not installed yet, you will be sent to the download page.

SKILL.md

---
name: ousterhout-build-deep
description: Use while writing or changing code, before calling the task done, whenever the change adds an exported or importable name, creates a module, class, component, helper, hook, service or wrapper, or centralizes repeated code. Author-time checklist for building deep modules: name the decision the boundary hides, pass the depth and invariant tests, fix problems instead of relocating them, never split on size alone, and end with a short design note. Compact companion to ousterhout-quality-program, which remains the full review lens.
---

# Build it deep (Ousterhout, author-time)

You are writing code, not reviewing it. Run this on your own change before
you call the task done.

## 1. Gate

Does the change add an exported/importable name, create a module, class,
component, helper, hook, service or wrapper, or centralize repeated code?
If no, skip this skill. Renames, codemods, config/data edits and one-line
fixes are exempt.

## 2. Before you write the boundary

- Find how this repo already solves a problem of this shape and follow it
  unless you can state why not. Read the dependency's current docs and
  types: an API recalled from memory is a claim, not a source.
- Write the interface comment first: what it promises, what it hides. If
  you cannot name the hidden decision (a format, a policy, a rule, a
  schema choice), the boundary should not exist. Inline it.
- Name it in domain language. If the only honest name is `utils`,
  `helpers` or `manager`, the cut is in the wrong place.

## 3. Two tests

- **Depth.** The interface must hide substantially more than it exposes. A
  wrapper that forwards its arguments is a cost with no benefit; delete it.
- **Invariant.** Extract shared code only when it protects a shared rule.
  The evidence is co-change: the copies were fixed or changed together in
  history. Look-alikes that change independently stay duplicated.

## 4. A fix must remove the problem, not relocate it

- Six casts moved into one generic cast helper are still six casts. Write
  the typed mapper the casts were papering over.
- Do not add a parameter or flag that pushes a decision onto callers unless
  callers really know something you don't. Absorb the hard case inside.
- Prefer semantics where the error case cannot arise over making every
  caller handle it.
- Moving essential domain complexity to another file is not simplification.

## 5. Under "clean this up" or "this file is too big" pressure

Never split on size alone. One 400-line module hiding one decision beats
four 100-line modules leaking the same joins. Ask what decision each split
hides; if none, don't split.

## 6. Safety

Existing code: pin current behavior with a test before deepening it. New
code: write the test that defines the intended behavior.

## 7. Report

If the gate fired, end your final message with a 2-4 line design note: each
boundary you added and the decision it hides; duplication you left on
purpose and why; anything shallow you accepted and why.

For a contested call or a full review, load `ousterhout-quality-program`.

Tags

designarchitecturecodingousterhoutauthor-time