Skip to content

Commit

Permalink
add mandatory dependency settings to layeredArchitecture()
Browse files Browse the repository at this point in the history
In particular, since adding the possibility to define forward rules within the layered architecture (e.g. `whereLayer(..).mayOnlyAccessLayers(..)`) there has been quite some confusions about how to deal with false positives, like dependencies to `java.lang.Object`. While it is generally easy to exclude those via `.ignoreDependency(..)` this does not seem to be very intuitive for users as there have been multiple GitHub issues about how to deal with those dependencies.
We now "force" users to make a (well-documented) decision how to deal with dependencies right when defining the layered architecture. The three predefined choices should cover the vast majority of user use cases (similar to `PlantUmlArchCondition`). For special cases where these options do not suffice it is always possible to simply pick `consideringAllDependencies()` and do fine grained `ignoreDependency(..)` calls later on.

Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>
  • Loading branch information
codecholeric committed Jun 18, 2022
1 parent 29c8b11 commit afa4c95
Show file tree
Hide file tree
Showing 17 changed files with 351 additions and 64 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 afa4c95

Please sign in to comment.