If your code references a class—for example, by invoking a method in that class—declare a dependency that includes that class in your pom.xml, build.gradle, or equivalent. In Bazel this practice is called “strict deps”.
Code should not call methods, reference fields, or instantiate classes from indirect dependencies. These are dependencies of the declared dependencies. Projects that rely on indirect dependencies tend to break in unexpected ways when direct dependencies are upgraded.
For example, your project might declare a dependency on the
Google HTTP Java Client which
itself depends on the Apache HTTP Components. If so, it is possible to use the org.apache.http.client.utils.URLEncodedUtils
class in your own project without
explicitly declaring a dependency on Apache HTTP Components. However, you should
add the dependency anyway so that if a future version of the
Google HTTP Java Client no longer depends on Apache HTTP Components, your code
still compiles. Strict dependencies also help static analysis tools better understand a project.
Code breakages due to indirect dependencies don’t just happen when a library is upgraded. They can also occur when dependency mediation selects a different version of a library’s dependency that does not include the necessary indirect dependency. Relying on indirect dependencies cause problems for clients with different dependency trees that don’t appear in your own code.
IDE autocomplete suggestions are a common way projects come to depend on indirect dependencies. When importing a new class, most IDEs only look to see if it’s present in the classpath, not whether it comes from a direct or indirect dependency.
The mvn dependency:analyze
command lists dependencies a Maven project uses
but hasn’t declared:
[WARNING] Used undeclared dependencies found:
[WARNING] org.apache.maven.resolver:maven-resolver-impl:jar:1.4.1:compile
[WARNING] org.apache.maven.resolver:maven-resolver-api:jar:1.6.1:compile
[WARNING] org.apache.maven:maven-core:jar:3.6.3:compile
[WARNING] org.apache.maven:maven-model-builder:jar:3.6.3:compile
These should be added to your pom.xml file.
The tool also lists dependencies the project declares but doesn’t use:
[WARNING] Unused declared dependencies found:
[WARNING] com.google.cloud.tools:dependencies:jar:1.5.5-SNAPSHOT:compile
[WARNING] com.google.truth:truth:jar:1.0.1:test
[WARNING] junit:junit:jar:4.13.1:test
[WARNING] org.mockito:mockito-core:jar:3.5.15:test
However its analysis of which dependencies aren’t used is not as accurate as its analysis of which dependencies are used. In particular, it reports dependencies used through reflection as unused, so be cautious when removing any allegedly unused dependencies.