Skip to content

Commit

Permalink
Add mandatory dependency settings to layeredArchitecture() #892
Browse files Browse the repository at this point in the history
Ever since `layeredArchitecture()` supports rules on "forward dependencies" (i.e. `whereLayer(..).mayOnlyAccessLayers(..)`) there has been confusion about how to exclude false positives like `java.lang.Object`. While excluding these dependencies can be achieved by `ignoreDependency(..)` this does not seem to be an API that is easily discoverable.

We now make it mandatory to choose how to treat dependencies right in the beginning. This way users will be guided to those considerations and be made aware of pitfalls as well as have an easy predefined option how to ignore false positives.

This will be a breaking change, since existing `layeredArchitecture()` definitions will not compile anymore without adding the choice of how to treat dependencies.
  • Loading branch information
codecholeric authored Jun 22, 2022
2 parents 0489934 + 7529901 commit 69d4398
Show file tree
Hide file tree
Showing 19 changed files with 615 additions and 307 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
@AnalyzeClasses(packages = "com.tngtech.archunit.example.layers")
public class LayeredArchitectureTest {
@ArchTest
public static final ArchRule layer_dependencies_are_respected = layeredArchitecture()
public static final ArchRule layer_dependencies_are_respected = layeredArchitecture().consideringAllDependencies()

.layer("Controllers").definedBy("com.tngtech.archunit.example.layers.controller..")
.layer("Services").definedBy("com.tngtech.archunit.example.layers.service..")
Expand All @@ -27,7 +27,7 @@ public class LayeredArchitectureTest {
.whereLayer("Persistence").mayOnlyBeAccessedByLayers("Services");

@ArchTest
public static final ArchRule layer_dependencies_are_respected_with_exception = layeredArchitecture()
public static final ArchRule layer_dependencies_are_respected_with_exception = layeredArchitecture().consideringAllDependencies()

.layer("Controllers").definedBy("com.tngtech.archunit.example.layers.controller..")
.layer("Services").definedBy("com.tngtech.archunit.example.layers.service..")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
@AnalyzeClasses(packages = "com.tngtech.archunit.example.layers")
public class LayeredArchitectureTest {
@ArchTest
static final ArchRule layer_dependencies_are_respected = layeredArchitecture()
static final ArchRule layer_dependencies_are_respected = layeredArchitecture().consideringAllDependencies()

.layer("Controllers").definedBy("com.tngtech.archunit.example.layers.controller..")
.layer("Services").definedBy("com.tngtech.archunit.example.layers.service..")
Expand All @@ -24,7 +24,7 @@ public class LayeredArchitectureTest {
.whereLayer("Persistence").mayOnlyBeAccessedByLayers("Services");

@ArchTest
static final ArchRule layer_dependencies_are_respected_with_exception = layeredArchitecture()
static final ArchRule layer_dependencies_are_respected_with_exception = layeredArchitecture().consideringAllDependencies()

.layer("Controllers").definedBy("com.tngtech.archunit.example.layers.controller..")
.layer("Services").definedBy("com.tngtech.archunit.example.layers.service..")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class LayeredArchitectureTest {

@Test
public void layer_dependencies_are_respected() {
layeredArchitecture()
layeredArchitecture().consideringAllDependencies()

.layer("Controllers").definedBy("com.tngtech.archunit.example.layers.controller..")
.layer("Services").definedBy("com.tngtech.archunit.example.layers.service..")
Expand All @@ -30,7 +30,7 @@ public void layer_dependencies_are_respected() {

@Test
public void layer_dependencies_are_respected_with_exception() {
layeredArchitecture()
layeredArchitecture().consideringAllDependencies()

.layer("Controllers").definedBy("com.tngtech.archunit.example.layers.controller..")
.layer("Services").definedBy("com.tngtech.archunit.example.layers.service..")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public class ArchUnitArchitectureTest {
static final String THIRDPARTY_PACKAGE_IDENTIFIER = "..thirdparty..";

@ArchTest
public static final ArchRule layers_are_respected = layeredArchitecture()
public static final ArchRule layers_are_respected = layeredArchitecture().consideringAllDependencies()
.layer("Root").definedBy("com.tngtech.archunit")
.layer("Base").definedBy("com.tngtech.archunit.base..")
.layer("Core").definedBy("com.tngtech.archunit.core..")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -935,7 +935,7 @@ Stream<DynamicTest> LayeredArchitectureTest() {
(memberName, expectedTestFailures) ->
expectedTestFailures
.ofRule(memberName,
"Layered architecture consisting of" + lineSeparator() +
"Layered architecture considering all dependencies, consisting of" + lineSeparator() +
"layer 'Controllers' ('com.tngtech.archunit.example.layers.controller..')" + lineSeparator() +
"layer 'Services' ('com.tngtech.archunit.example.layers.service..')" + lineSeparator() +
"layer 'Persistence' ('com.tngtech.archunit.example.layers.persistence..')" + lineSeparator() +
Expand Down
169 changes: 154 additions & 15 deletions archunit/src/main/java/com/tngtech/archunit/library/Architectures.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noFields;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noMembers;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noMethods;
import static com.tngtech.archunit.testutil.TestUtils.union;
import static com.tngtech.java.junit.dataprovider.DataProviders.$;
import static com.tngtech.java.junit.dataprovider.DataProviders.$$;
import static java.util.Collections.emptySet;
Expand Down Expand Up @@ -447,15 +448,6 @@ public void check(JavaMember item, ConditionEvents events) {
};
}

@SafeVarargs
private static <T> Set<T> union(Set<T>... sets) {
ImmutableSet.Builder<T> result = ImmutableSet.builder();
for (Set<T> set : sets) {
result = result.addAll(set);
}
return result.build();
}

static DescribedPredicate<JavaMember> areNoFieldsWithType(final Class<?> type) {
return new DescribedPredicate<JavaMember>("are no fields with type " + type.getSimpleName()) {
@Override
Expand Down
Loading

0 comments on commit 69d4398

Please sign in to comment.