Description
This smell arises when two or more abstractions depend on each other directly or indirectly (creating a tight coupling between the abstractions). A cyclic chain of calls between abstractions exists.
Context
Derived from: “Cyclic Dependency” or “Circular Dependency”
A special form of Cyclic Dependency is sometimes exhibited with specializations. A subtype has an obvious dependency on its supertype. However, when the supertype also depends on the subtype (for instance, by having an explicit reference to the subtype), it results in a cyclic dependency.
Cause
Hard to visualize indirect dependencies.
Consequences
Abstractions involved in a cyclic dependency can be harder to maintain or reuse, as they are more strongly coupled.
Detection
Abstractions depend on each other in a cyclic interaction pattern, e.g. A depends on B, B depends on C, and C depends back on A. So check all reachable elements for the original element to detect cycles. We set ten as the default maximum value for filtering cyclic paths. That is, the query looks for a cyclic path with at most ten edges between nodes. The relation length is set as a query parameter and enterprise architects can modify the default value based on their model size. However, setting a very large value as hop degree may impact the query performance.
Solution
Resolve the cycles by e.g. relocating functionality (merging) or use an intermediary element.
Example
A depends on B, B on C and C on A
Cypher query
MATCH (m) WITH collect(m) as nodes CALL apoc.nodes.cycles(nodes, {maxDepth: $maxDepth}) YIELD path RETURN path as pDiagram

Aliases
Circular Dependency
Tags
soa, microservices, business, application, technology, The Couplers, between elements, automatic detection
Query parameters
[
{
"name": "maxDepth",
"type": "number",
"default": 10,
"description": "The max length of cyclic path between elements."
}
]Related smells
- Chatty Service (relates)
- Nanoservices (relates)
- Message Chain (relates)