Implementation
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 ifVis extremely high.
Run locally #
npm install
npm run build
npm start
Generates:
sphere-report.jsonsphere-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 #
- Take 3–10 modules with lowest S.
- Check
extras:- Too many exports? - hide behind internal helpers or a facade.
- Too many external calls? - extract adapter.
- Low cohesion? - localize related logic.
- Make small reversible changes.
- Re-run analyzer, observe S and cohesion.
- Commit with a note referencing analyzer improvement.
Integrations #
CI / PR #
Run the analyzer per pull request:
Example GitHub Action steps:
npm cinpm run buildnpm start- Upload
sphere-report.jsonas 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.
Sis 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