javagradlecyclic-dependency

Resolve circular dependency in gradle


I recently started developing a java project which has some sub projects within it. All of them are gradle. So let's say there are two projects A and B which is already implemented. And I'm going to introduce another graldle project C. And the dependencies are like this.

So I need to implement this project C without cyclic dependencies error as it is given when I tried to build the project with gradle. I saw some answers that Interface is a solution for this. But in my case project A and B are large projects and I can't event think how to introduce a Interface for them. Only thing I can do is introducing interfaces for project C. So is there a way to solve my problem with these cases? If there isn't what is the way to have such an one? And please note that these A,B,C projects are individual projects so those can't combine as one.


Solution

  • Foreword

    There is no magic that will let you compile your project when there's a cycle in your dependency graph. You'll need to do some refactoring to eliminate the cycle.

    The way you deal with circular dependencies is that you split the modules and repeat that until the cycle is gone (or use the alternative given below).

    Algorithm

    1. Starting point:

      A --> B --> C
      ^           |
      |           |
      +-----------+
      
    2. Start with extracting the parts of A that are used by C to a separate module (let's call it D):

      A --> B --> C
      |           |
      |           |
      +---> D <---+
      

      If D does not depend on any other module you're done. Otherwise continue cutting the cords.

    3. Let's say D stil has a B dependency:

      A --> B --> C
      |     ^     |
      |     |     |
      +---> D <---+
      

      You need to analogically extract common parts from B (to let's call it E):

      A --> B --> C
      |     |     |
      |     v     |
      |     E     |
      |     ^     |
      |     |     |
      +---> D <---+
      

      Just like before - repeat if E still has problematic dependencies.

    4. Let's say E stil depends on C:

      A --> B --> C --+
      |     |     ^   |
      |     v     |   |
      |     E ----+   |
      |     ^         |
      |     |         |
      +---> D <-------+
      

      What do we do? Obvioulsy split C (by extracting F):

      A --> B --> C --+
      |     |     |   |
      |     v     v   |
      |     E --> F   |
      |     ^         |
      |     |         |
      +---> D <-------+
      
    5. Continue the loop until a point is reached where the newly introduced module has no more dependecies in the module graph.

      For example in point 3) we're done if we assume that F is dependencyless. This means that the problematic part of A used by C has been extracted to the D ─► E ─► F subgraph.

    Alternative

    Note that it might not be that easy if at all doable within a sane budget. So in some contexts it might be better to fall back to the less preferable alternative: duplicating the code in A which C relies on.