Implementation

Publish at:

We began with a droplet in vacuum and followed the shape wherever it led: from physics to geometry, to software design. The last steps are practical — a way to bring the idea of sphericity into everyday engineering.

How to think about the tool #

  • V (internal volume) — internal logic and hidden complexity.
  • A (public surface) — exports, public methods, external dependencies.
  • S = V / A^α — sphericity score.
  • Cohesion — proportion of calls that stay inside the module.

Interpretation cues:

  • Low S + low cohesion - likely leaky responsibility, consider refactor.
  • Low S + high cohesion - internally dense; may be a monolith but self‑contained.
  • High S - good balance, still inspect if V is extremely high.

Run locally #

npm install
npm run build
npm start

Generates:

  • sphere-report.json
  • sphere-report.md

Minimal config #

{
  "include": ["../your-project/src/**/*.ts"],
  "exclude": ["../your-project/test/**/*.ts"],
  "weights": {
    "exportedSymbol": 3,
    "externalImport": 2,
    "outgoingCall": 2
  },
  "alpha": 1.8
}

Triage loop #

  1. Take 3–10 modules with lowest S.
  2. Check extras:
    • Too many exports? - hide behind internal helpers or a facade.
    • Too many external calls? - extract adapter.
    • Low cohesion? - localize related logic.
  3. Make small reversible changes.
  4. Re-run analyzer, observe S and cohesion.
  5. Commit with a note referencing analyzer improvement.

Integrations #

CI / PR #

Run the analyzer per pull request:

Example GitHub Action steps:

  • npm ci
  • npm run build
  • npm start
  • Upload sphere-report.json as artifact
  • Comment summary to PR

Visualization #

Feed JSON into:

  • Cytoscape
  • Graphviz
  • D3

Use node size = volume, color = S, edge = call graph.

Limitations #

  • Dynamic calls and runtime indirection may resolve to external conservatively.
  • Path aliases and monorepos require resolver config.
  • S is configurable — tune weights and alpha to your design style.

Final thoughts #

Spherical design is not a mandate for structure, but a discipline of bounded surface, internal cohesion, and minimal leakage. The tool is a mirror. You still make the decisions.

Small shaping actions compound:

  • hide a surface
  • localize a responsibility
  • wrap an external dependency
  • group related behavior

Over time, systems get quieter, less tangled, and more understandable.

Source code #

This is where the tool lives:

Reference implementation (opens in a new tab)

And this is how it works:

I pointed the tool to an old application I built may years ago: typeioc (opens in a new tab)

 *module `../typeioc/src/registration/instance.ts` — S=4.670 — **WARNING**
  - V: 26, A: 31
- *module* `../typeioc/src/interceptors/interceptor.ts` — S=5.029 — **WARNING**
  - V: 28, A: 31
- *module `../typeioc/src/registration/types/base.ts` — S=5.196 — **WARNING**
  - V: 9, A: 3
- *module* `../typeioc/src/interceptors/substitute-storage.ts` — S=5.506 — **WARNING**
  - V: 24, A: 19
- **module* `../typeioc/src/build/container-api.ts` — S=5.581 — **WARNING**
  - V: 29, A: 27
- *module `../typeioc/src/decorators/registration-api.ts` — S=6.600 — **WARNING**
  - V: 33, A: 25
- **module `../typeioc/src/build/internal-container.ts` — S=6.636 — **WARNING**
  - V: 68, A: 105
- **module `../typeioc/src/build/types/common.ts` — S=8.014 — **GOOD**
  - V: 34, A: 18
- *module `../typeioc/src/scaffold/index.ts` — S=9.347 — **GOOD**
  - V: 31, A: 11
- **module `../typeioc/src/registration/base.ts` — S=11.156 — **GOOD**
  - V: 37, A: 11

## Summary
- Good: 3
- Warning: 14
- Collapse: 47