How to Manage Java Package Dependencies Using JDepend

Written by

in

JDepend is an open-source static analysis tool used to measure design quality by analyzing dependencies between Java packages. It evaluates your code’s package structure to calculate metrics like coupling and stability, enabling you to enforce automated architectural rules via unit tests. Core Metrics Calculated by JDepend

JDepend traverses Java class files to calculate Robert C. Martin’s clean architecture metrics: Afferent Coupling (

): The number of external packages that depend on classes inside the analyzed package. This measures how dependent others are on this package. Efferent Coupling (

): The number of unique external packages that classes inside the analyzed package depend upon. This measures how outgoing its dependencies are. Abstractness (

): The ratio of abstract classes and interfaces to the total number of classes in the package. A package with only interfaces has an abstractness of Instability ( ): Calculated as . A value of

means a package is completely stable (highly depended upon, depends on nothing). A value of means it is completely unstable. Distance from the Main Sequence ( ): Calculated as

. This measures the ideal balance between stability and abstractness. A value close to How to Enforce Rules via Unit Tests

You can plug JDepend directly into a JUnit test to programmatically enforce that your architectural boundaries are not breached. 1. Setup Dependency

Add the JDepend framework to your project build files (e.g., Maven or Gradle):

jdepend jdepend 2.9.1 test Use code with caution. 2. Writing an Architectural Rule Test

The most common way to enforce architecture rules is using DependencyConstraint. Below is an example verifying that a Domain Layer does not accidentally depend on an Infrastructure Layer (a classic Clean Architecture violation):

import jdepend.framework.JDepend; import jdepend.framework.JavaPackage; import jdepend.framework.DependencyConstraint; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; public class ArchitectureRulesTest { @Test public void testLayerDependencies() throws IOException { JDepend jdepend = new JDepend(); // Point to your compiled class directory jdepend.addDirectory(“target/classes/com/myapp”); // Define your architectural constraint DependencyConstraint constraint = new DependencyConstraint(); JavaPackage webLayer = constraint.addPackage(“com.myapp.web”); JavaPackage domainLayer = constraint.addPackage(“com.myapp.domain”); JavaPackage infraLayer = constraint.addPackage(“com.myapp.infrastructure”); // Explicitly define allowed directions webLayer.dependsUpon(domainLayer); infraLayer.dependsUpon(domainLayer); // Note: Because domainLayer does not declare any dependsUpon, // any outgoing dependency from domain to infra will cause the test to fail. // Analyze the actual packages jdepend.analyze(); // Check if the actual codebase complies with the rules assertTrue(constraint.match(jdepend.getPackages()), “Architectural layers rule violated!”); } } Use code with caution. Key Architectural Rules You Can Enforce

No Cyclic Dependencies: Ensure package A depends on B, and B depends on C, but C never points back to A. JDepend detects this immediately via jdepend.containsCycles().

Strict Layered Access: Ensure that lower layers (like repositories or database entities) never import upper layers (like UI controllers or DTOs).

Stable Abstractions Principle: Enforce that packages which are highly stable ( close to 0) must also be highly abstract ( close to 1) so they remain easily extensible. The Modern Alternative: ArchUnit

While JDepend is a pioneering tool, the original library clarkware/jdepend has been mostly unmaintained for years. Modern Java development teams heavily prefer ArchUnit.

ArchUnit in practice: Keep your Architecture Clean – codecentric AG

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *