Cyclic Namespace Dependencies
ID |
csharp.cyclic_namespace_dependencies |
Severity |
low |
Remediation Complexity |
medium |
Remediation Risk |
low |
Remediation Effort |
medium |
Resource |
Code Smell |
Language |
CSharp |
Tags |
code_smell, namespaces |
Description
Reports namespaces that participate in a dependency cycle with other namespaces of the
same project. A dependency edge nsA → nsB exists when a compilation unit declaring
nsA imports nsB with a using directive and nsB is also declared in the scanned
project. The analysis is project-wide: edges from every file are combined into one
directed graph and strongly connected components of size greater than one are reported,
enumerating the cycle path.
Rationale
Mutually dependent namespaces cannot be layered, understood or extracted independently:
a developer investigating namespace X cannot move or test it without dragging Y
along, and modifications to either side may have to touch both to keep the cycle
compiling. One-directional references — including the routine parent-namespace
using Child.Sub; — are healthy layering and are never reported.
// AlphaService.cs
using App.Beta;
namespace App.Alpha // FLAW — cycle: App.Alpha -> App.Beta -> App.Alpha
{
public class AlphaService { public BetaService Beta { get; set; } }
}
// BetaService.cs
using App.Alpha;
namespace App.Beta // FLAW — cycle: App.Beta -> App.Alpha -> App.Beta
{
public class BetaService { public AlphaService Alpha { get; set; } }
}
Remediation
Break the cycle by extracting the shared abstractions into a namespace both sides can depend on, or by inverting one of the dependencies (interfaces declared on the consumer side). The reported cycle path shows the namespaces involved; any single edge removed from the cycle resolves the finding for the whole group.