dependencies {
- testImplementation 'com.tngtech.archunit:archunit-junit4:1.1.0'
+ testImplementation 'com.tngtech.archunit:archunit-junit4:1.2.0'
}
<dependency>
<groupId>com.tngtech.archunit</groupId>
<artifactId>archunit-junit4</artifactId>
- <version>1.1.0</version>
+ <version>1.2.0</version>
<scope>test</scope>
</dependency>
dependencies {
- testImplementation 'com.tngtech.archunit:archunit-junit4:1.1.0'
+ testImplementation 'com.tngtech.archunit:archunit-junit4:1.2.0'
}
<dependency>
<groupId>com.tngtech.archunit</groupId>
<artifactId>archunit-junit5</artifactId>
- <version>1.1.0</version>
+ <version>1.2.0</version>
<scope>test</scope>
</dependency>
@@ -656,7 +657,7 @@ dependencies {
- testImplementation 'com.tngtech.archunit:archunit-junit5:1.1.0'
+ testImplementation 'com.tngtech.archunit:archunit-junit5:1.2.0'
}
<dependency>
<groupId>com.tngtech.archunit</groupId>
<artifactId>archunit</artifactId>
- <version>1.1.0</version>
+ <version>1.2.0</version>
<scope>test</scope>
</dependency>
@@ -682,7 +683,7 @@ dependencies {
- testImplementation 'com.tngtech.archunit:archunit:1.1.0'
+ testImplementation 'com.tngtech.archunit:archunit:1.2.0'
}
Currently there are two "slice" rules offered by the Library API. These are basically rules +
Currently, there are two "slice" rules offered by the Library API. These are basically rules that slice the code by packages, and contain assertions on those slices. The entrance point is:
The underlying infrastructure for cycle detection that the slices()
rule makes use of can also be accessed
+without any rule syntax around it. This allows to use the pure cycle detection algorithm in custom
+checks or libraries. The core class of the cycle detection is
com.tngtech.archunit.library.cycle_detection.CycleDetector
+It can be used on a set of a generic type NODE
in combination with a generic Set<EDGE>
+(where EDGE implements Edge<NODE>
) representing the edges of the graph:
Set<MyNode> nodes = // ...
+Set<Edge<MyNode>> edges = // ...
+Cycles<Edge<MyNode>> foundCycles = CycleDetector.detectCycles(nodes, edges);
+Edges are parameterized by a generic type EDGE
to allow custom edge types that can
+then transport additional meta-information if needed.
+ + | ++Note: ArchUnit doesn’t strive to be a "competition" for module systems like the +Java Platform Module System. Such systems have advantages like checks at compile time +versus test time as ArchUnit does. So, if another module system works well in your +environment, there is no need to switch over. But ArchUnit can bring JPMS-like features +to older code bases, e.g. Java 8 projects, or environments where the JPMS is for some +reason no option. It also can accompany a module system by adding additional rules e.g. +on the API of a module. + | +
To express the concept of modularization ArchUnit offers ArchModule
s. The entrypoint into
+the API is ModuleRuleDefinition
, e.g.
ModuleRuleDefinition.modules().definedByPackages("..example.(*)..").should().beFreeOfCycles();
+As the example shows, it shares some concepts with the Slices API. For example definedByPackages(..)
+follows the same semantics as slices().matching(..)
.
+Also, the configuration options for cycle detection mentioned in the last section are shared by these APIs.
+But, it also offers several powerful concepts beyond that API to express many different modularization scenarios.
One example would be to express modules via annotation. We can introduce a custom annotation
+like @AppModule
and follow a convention to annotate the top-level package-info
file
+of each package we consider the root of a module. E.g.
@AppModule(
+ name = "Module One",
+ allowedDependencies = {"Module Two", "Module Three"},
+ exposedPackages = {"..module_one.api.."}
+)
+package com.myapp.example.module_one;
+We can then define a rule using this annotation:
+modules()
+ .definedByAnnotation(AppModule.class)
+ .should().respectTheirAllowedDependenciesDeclaredIn("allowedDependencies",
+ consideringOnlyDependenciesInAnyPackage("..example.."))
+ .andShould().onlyDependOnEachOtherThroughPackagesDeclaredIn("exposedPackages")
+As the example shows, the syntax carries on meta-information (like the annotation of the annotated
+package-info
) into the created ArchModule
objects where it can
+be used to define the rule. In this example, the allowed dependencies are taken from the @AppModule
+annotation on the respective package-info
and compared to the actual module dependencies. Any
+dependency not listed is reported as violation.
+Likewise, the exposed packages are taken from the @AppModule
annotation and any dependency
+where the target class’s package doesn’t match any declared package identifier is reported
+as violation.
Note that the modules()
API can be adjusted in many ways to model custom requirements.
+For further details, please take a look at the examples provided
+here.
The infrastructure to create modules and inspect their dependencies can also be used outside +the rule syntax, e.g. for custom checks or utility code:
+ArchModules<?> modules = ArchModules.defineByPackages("..example.(*)..").modularize(javaClasses);
+ArchModule<?> coreModule = modules.getByIdentifier("core");
+Set<? extends ModuleDependency<?>> coreDependencies = coreModule.getModuleDependenciesFromSelf();
+coreDependencies.forEach(...);
+The Library API also offers a small set of coding rules that might be useful in various projects. Those can be found within
@@ -1888,7 +2011,7 @@The Library API offers a feature that supports PlantUML diagrams. This feature is located in
@@ -1989,7 +2112,7 @@When rules are introduced in grown projects, there are often hundreds or even thousands of violations, way too many to fix immediately. The only way to tackle such extensive violations is to establish an @@ -2073,7 +2196,7 @@
FreezingArchRule
provides two extension points to adjust the behavior to custom needs.
The first one is the ViolationStore
, i.e. the store violations will be recorded to. The second one
@@ -2215,7 +2338,7 @@
Similar to code quality metrics, like cyclomatic complexity or method length, software architecture metrics strive to measure the structure and design of software. @@ -2240,7 +2363,7 @@
These software architecture metrics were defined by Robert C. Martin in various sources, for example in his book "Clean architecture : a craftsman’s guide to software structure and design".
@@ -2391,7 +2514,7 @@