How to properly deal with class dependencies to utilize incremental compilation in Java/Android with Gradle?

痞子三分冷 提交于 2019-12-20 06:31:01

问题


I improved our build system and activated incremental builds and compilation as described in this question. To my disappointment, incremental compilation didn't improve build times as much as I expected from reading Gradles blog post.

After some investigation, I realized that the issue is that even though I only add a comment to a small class somewhere deep in the app apparently almost the whole codebase is rebuilt. In fact, it doesn't really matter which class I touch, Gradles --debug output reveals that it basically always recompiles 476 classes.

Incremental compilation of 476 classes completed in 12.51 secs.

While I understand that public static constants in the changed file trigger a full recompilation (which is only slightly slower), I don't understand how to properly break up class dependencies so that incremental compilation actually works. What are the exact rules to determine class dependencies that affect incremental compilation? I could read about some examples here, but it doesn't appear to apply to our (fairly standard) project at all.

Some of my own testings yielded the following:

// One of my main classes that has lots of class dependencies
public class A{
   public void foo() {
       // This line produces a dependency between A and B. So changing just
       // a comment in B triggers recompilation of all classes attached to A
       B b1 = new B(); 


   }
}

// A small helper class that I want to change
public class B {
   public void bar() {
       // This line does not create a dependency, so B can still be compiled by
       // itself. But usually, that's not the "common" direction you have.
       A a1 = new A();
       // I make the change here and then trigger a new build
   }
}

Why does A need recompilation when an implementation detail, but not the interface of B changed?

I also tried "hiding" B behind an interface C. I thought that would be the proper (even though often times very cumbersome) way to break up the dependencies. But it turns out it didn't help at all.


public class A{
   public void foo() {
       C c1 = C.cFactory();
   }
}

public class B implements C {
   public void bar() {
       // I make the change here and then trigger a new build
   }
}

public interface C {
   void bar();

   public static C cFactory() {
       return new B();
   }
}

It appears to me that we have this big dependency blob and I am uncertain this could reasonably be changed even though I would argue we have a reasonably designed codebase. Are there best practices, guidelines or design patterns that are common among Android developers that would effectively improve incremental compilations?

I do wonder whether others have the same problem as we do and if not what did you do?


回答1:


The problem is in fact that all our classes are part of a big dependency graph. This shows in the quote

Incremental compilation of 476 classes completed in 12.51 secs.

Basically, any class I touch causes a recompilation of 476 classes. In our particular case, this is caused by two patterns. We use Explicit Intents in Android, which I am not sure how to better handle. Additionally, we use Dagger in such a way, that we connected all classes in a circle.

Concerning the interface problematic I made a rather obvious mistake with implementing the cFactory(). As this creates a class dependency from C to B and thus transitively from A to C.

The following snippet breaks the dependency from A to B but creates one from B to A.

public class A{
   public static void foo(C input) {
       input.foo();
   }
}

public class B implements C {
   public void bar() {
       // I make the change here and then trigger a new build
       A.foo(this);
   }
}

public interface C {
   void bar();
}


来源:https://stackoverflow.com/questions/54600574/how-to-properly-deal-with-class-dependencies-to-utilize-incremental-compilation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!