Acyclic Dependency Principle (ADP)

Last updated Sep 15th, 2019

About this...

One of several component design principles that states that the "dependency graph of components should have no cycles"

In the header image, component A relies on component B which relies on component C.

The problem is that component C also relies on A.

That creates a cycle.

We don't want dependency cycles because they:

  • Make the code hard to understand, thus reducing maintainability
  • Reduce the quality of the code and improve the likelihood of errors by making it harder to change one component without affecting another
  • Make it impossible to test each individual component because they can't be separated
  • Have the ability to violate The Dependency Rule

The following example demonstrates a violation of ADP. A cycle exists where UsernameGenerator relies on UserRepo, which relies on User, which relies on UsernameGenerator.

Dependency graph with a Cycle

How to fix it?

Two ways:

  1. Dependency Inversion. Stick an interface inbetween one of the relationships to break the cycle.
  2. Rethink your layers. If you've run into cycles like this, it might be a good signal that you're not following The Dependency Rule. You can fix that by aiming to understand and separate the concerns of your application into layers. See The Clean Architecture.

Dependency Inversion Principle

This is how we might be able to break a dependency cycle.

Check out this article, "Dependency Injection & Inversion Explained | Node.js w/ TypeScript".

The Dependency Rule

The direction of dependencies should form an acyclic graph where the lower-level components always rely on/point towards the higher-level policy.

For example, given the following generic application architecture, notice that all of the outer layer details point towards the inner-layer ones (Domain layer + Application layer)?

That's how you follow the dependency rule.