Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

  • A has dependencies on B
  • B has dependencies on C
  • C has dependencies on A

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.

like image 625
Shehan Dhaleesha Avatar asked Oct 01 '19 05:10

Shehan Dhaleesha


People also ask

How do you resolve circular dependencies?

To resolve circular dependencies: Then there are three strategies you can use: Look for small pieces of code that can be moved from one project to the other. Look for code that both libraries depend on and move that code into a new shared library. Combine projectA and projectB into one library.

How do I resolve Gradle dependencies?

Given a required dependency, with a version, Gradle attempts to resolve the dependency by searching for the module the dependency points at. Each repository is inspected in order. Depending on the type of repository, Gradle looks for metadata files describing the module ( .

Does Gradle allow circular dependency?

Gradle won't let you have a circular dependency by showing this error: FAILURE: Build failed with an exception.

What causes circular dependency?

A circular dependency occurs when two classes depend on each other. For example, class A needs class B, and class B also needs class A. Circular dependencies can arise in Nest between modules and between providers. While circular dependencies should be avoided where possible, you can't always do so.


1 Answers

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.

like image 70
jannis Avatar answered Oct 17 '22 08:10

jannis