design-deep-modules

v2026.09.24

Judge interface depth — deep modules hide complexity behind small interfaces. Use when designing a module/API, reviewing a class boundary, or reducing complexity.

GitHub
安装命令
npx skhub add laurigates/design-deep-modules
Markdown
SKILL.md

Design: Deep Modules

From A Philosophy of Software Design (Ousterhout): the best modules are deep — a small, simple interface hiding a large, complex implementation. A shallow module is the opposite: an interface nearly as complicated as the implementation it wraps, so it adds cognitive cost without removing much. This skill assesses a module or interface for depth and points at the cheapest way to deepen it.

The unit of design is complexity at the boundary: every method, parameter, and exception a caller must understand is interface cost; everything the module handles for them is the benefit. Depth is the ratio.

When to Use This Skill

Use this skill when...Use something else instead when...
Designing a new module/class/API surface and choosing what to exposeHunting correctness bugs → code-quality-plugin:code-review
A class boundary "feels" thin — pass-through methods, leaky configCyclomatic/cognitive metrics on a function → code-quality-plugin:code-complexity
Deciding whether to split or merge two modulesRemoving duplication specifically → code-quality-plugin:dry-consolidation
Reviewing whether an abstraction earns its keepRestructuring toward pure functions → code-quality-plugin:code-refactor

Core Principle

Signal of a deep moduleSignal of a shallow module
Few public methods, many privatePublic surface ≈ implementation size
Caller passes intent, not mechanismCaller must orchestrate internal steps
Defaults handle the common caseEvery caller re-specifies the same config
Errors handled or masked internallyExceptions leak the implementation's internals
Name describes what, not howName encodes the mechanism (HashMapUserCache)

Two recurring deepening moves: pull complexity downward (the module, not its callers, absorbs the hard case — a class with N callers pays once, they pay N times) and design it twice (sketch two genuinely different interfaces before committing; the second exposes the first's accidental complexity).

Parameters

Parse $ARGUMENTS:

  • Target (optional, first positional) — a file, module, directory, or diff to assess. If absent, default to the current change (git diff HEAD + staged) and say so.

Execution

Execute this depth assessment:

Step 1: Map the interface vs the implementation

For the target, list the public surface (methods, params, required config, thrown exceptions, ordering constraints a caller must obey) and estimate the implementation weight behind it. State the depth verdict in one line: deep, shallow, or mixed.

Step 2: Locate the shallowness

For each shallow point, name the specific cost the caller pays and why it leaks:

  • Pass-through methods that only forward to another layer (collapse the layer)
  • Config a caller must always set the same way (push a default downward)
  • Internal exceptions surfacing as the public contract (mask or translate)
  • Ordering / temporal coupling ("call init() before run()") (encapsulate)
  • Information leakage — the same design decision known in two modules

Step 3: Recommend the cheapest deepening

Per finding, give the move (pull complexity down / merge the shallow layer / add a default / design-it-twice the interface) and the resulting smaller interface. Prefer one deeper module over two shallow ones only when they share a secret; do not merge modules that are genuinely independent (that is the opposite failure — a god module).

Step 4: Report

Emit: target, depth verdict, the shallow points (ordered by caller cost), and the recommended interface change for each. Keep recommendations behaviour- preserving — this is an interface-shape review, not a rewrite.

Anti-patterns

MistakeCorrect approach
Treating "more, smaller classes" as always betterClassitis makes shallow modules; depth, not count, is the goal
Merging two modules that share no secretThat builds a god module — merge only on shared information
Adding a config knob "for flexibility"Each knob is interface cost paid by every caller; default it
Exposing an exception because it was easyDefine away or mask errors the caller cannot act on

Quick Reference

SymptomDeepening move
Pass-through / wrapper methodCollapse the layer
Repeated caller configPush a default downward
Leaky exceptionsMask or translate at the boundary
"Call A before B"Encapsulate the sequence
Two interfaces both plausibleDesign it twice, pick the smaller surface

Related

  • code-quality-plugin:code-complexity — function-level cyclomatic/cognitive metrics (this skill works at the interface level above that)
  • code-quality-plugin:code-refactor — the mechanical moves that execute a deepening once it's chosen
  • code-quality-plugin:dry-consolidation — information leakage is often duplication; dedupe is one deepening move
  • software-design-plugin:design-by-contract — what the deepened interface should promise its callers
发现
标签

此技能尚未发布标签。

版本
最新版本元数据

版本

v2026.09.24

发布时间

Sep 24, 2026

分类

未分类

许可证

MIT

源路径

software-design-plugin/skills/design-deep-modules

默认分支

main

最新提交

1668324

Tree SHA

b2d4cc3