No circular module dependencies
Why it matters
Circular module dependencies cause subtle initialization-order bugs that appear only in specific import sequences — the kind that works on the developer's machine and fails in a bundled production build or a Jest environment with a different module evaluation order. ISO 25010:2011 §6.5.1 classifies this as a structural maintainability defect. Circular dependencies also prevent effective tree-shaking: bundlers cannot safely eliminate one half of a cycle, so both modules ship to the client even when only one is needed.
Severity rationale
High because circular imports introduce initialization-order bugs that are environment-specific and notoriously hard to diagnose, and they prevent the bundler from tree-shaking either module.
Remediation
Detect cycles with dpdm or madge, then break them by extracting the shared dependency into a third module:
npx dpdm --circular --tree false src/**/*.ts
# or
npx madge --circular src/
Breaking the cycle:
Before:
utils/format.ts → features/user.ts → utils/format.ts (circular)
After:
types/user.types.ts (new shared module)
utils/format.ts → types/user.types.ts
features/user.ts → types/user.types.ts
Add to CI to prevent regressions:
npx madge --circular --extensions ts src/ && echo "No circular deps"
DetectionPro
The detection method for this pattern is part of AuditBuffet Pro.
The full method (what to look for, pass and fail conditions, and how results get reported) ships inside the Code Quality Essentials Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- iso-25010:2011 · maintainability.modularity — Maintainability — Modularity
Taxons
History
- 2026-04-18·v1.0.0·Initial import from code-quality-essentials·automated