deep-import-chain¶
Category: Module Structure
Severity: Info
Triggered by: pyscn analyze, pyscn check --select deps
What it does¶
Reports the longest acyclic import chain in the project when its depth exceeds the expected depth for a project of its size. pyscn uses log₂(module_count) + 1 as the reference — a 64-module project is expected to have chains no longer than 7.
A chain is a path through the module dependency graph: a → b → c → …, where each arrow is an import.
Why is this a problem?¶
Deep chains indicate poor layering. Every additional link is a module that must be loaded, parsed, and initialised before the bottom of the chain is usable, and every link is a place where an unrelated change can ripple downward.
Symptoms of a too-deep chain:
- Slow startup. Importing the leaf module triggers a cascade of top-level side effects.
- Fragile tests. A unit test for the leaf pulls in the full chain and breaks when anything upstream changes.
- Hidden coupling. Modules in the middle of the chain often exist only as pass-throughs, masking the real dependency.
- Hard to reason about. There is no single "level" at which the code lives.
Example¶
myapp.cli
→ myapp.commands
→ myapp.services
→ myapp.orchestrator
→ myapp.workers
→ myapp.adapters
→ myapp.drivers
Seven levels to reach the driver. In practice the CLI layer doesn't need to know that workers exist, and workers don't need to know about the CLI — but a change to drivers can force re-testing every layer above it.
Use instead¶
Introduce a facade at the boundary so upper layers talk to one module, not a chain:
myapp.cli
→ myapp.commands
→ myapp.services # single entry point
(internally wires orchestrator / workers / adapters / drivers)
Or flatten: if services, orchestrator, and workers are all doing coordination, merge them into one layer and let it depend directly on adapters.
Options¶
| Option | Default | Description |
|---|---|---|
dependencies.find_long_chains |
true |
Set to false to disable this rule. |
dependencies.enabled |
false |
Opt-in for pyscn check; always on for pyscn analyze. |
There is no explicit depth threshold — pyscn compares the longest chain against log₂(module_count) + 1 and reports when it is exceeded.
References¶
- Longest-path search over the module DAG (
internal/analyzer/module_analyzer.go,internal/analyzer/coupling_metrics.go). - Rule catalog · circular-import