Dependencies Must Point One Way, and a Cycle Is a Design Defect
Draw the components of a system and put an arrow from each one to everything it needs in order to work. That picture is the dependency graph, and two of its properties decide how the system can be changed, tested, released and understood. The first is direction. Dependencies should point from what changes often toward what changes rarely, so a volatile part can be replaced without disturbing a stable one. A rule that has held for decades is that policy, the part expressing what the system is for, should not depend on mechanism, the part expressing how it currently stores or transports things. The second property is the absence of cycles. If A needs B and B needs A, neither can be understood alone, tested alone, released alone, or replaced alone; they are one component wearing two names, and the diagram is lying about the boundary. A cycle is broken by inverting one arrow: the side that would have called the other instead declares what it needs as a contract, and the other side supplies something that satisfies it. This is why a dependency you dislike is very often a contract you have not written yet. You will be able to draw the dependency arrows for a design, find the cycles and the arrows running from stable parts toward volatile ones, and propose which arrow to invert and what contract that inversion requires.
Dependency Direction and Acyclic Dependencies in Systems Architecture
Dependencies between system components have a direction, arising from optionality on one side of a relationship (syntactic or semantic), and when all underlying dependencies of an interface share a d…