Skip to content

Commit 7d21655

Browse files
committed
refactoring + detailed LayerDependencyRulesTest
1 parent c647d35 commit 7d21655

2 files changed

Lines changed: 114 additions & 26 deletions

File tree

src/test/java/com/devonfw/sample/archunit/ArchitectureTest.java

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -16,44 +16,35 @@ public class ArchitectureTest {
1616
@ArchTest
1717
private static final ArchRule shouldOnlyAccessValidLayers = //
1818
layeredArchitecture().consideringAllDependencies() //
19-
.layer("common").definedBy("..common..") //
20-
.layer("logic").definedBy("..logic..") //
21-
.layer("dataaccess").definedBy("..dataaccess..") //
22-
.layer("service").definedBy("..service..") //
23-
.layer("batch").definedBy("..batch..") //
24-
.layer("ui").definedBy("..ui..")
25-
.layer("java").definedBy("..java..") //
26-
.layer("javax").definedBy("..javax..")
27-
.layer("mapper").definedBy("..mapstruct..")
28-
.layer("logger").definedBy("..org.slf4j..")
29-
.layer("database").definedBy("..com.querydsl..")
30-
.layer("spring").definedBy("..org.springframework..")
31-
.layer("client").definedBy("..client")
32-
33-
// TODO
34-
//.whereLayer("ui").mayNotBeAccessedByAnyLayer()
35-
.whereLayer("common").mayOnlyAccessLayers("java", "javax")
36-
// L01: Common Layer doesnt depend on any other layer (except obv. java classes)
37-
.whereLayer("client").mayOnlyBeAccessedByLayers("client", "java")
19+
.layer("common").definedBy("com.devonfw.sample.archunit.common..") //
20+
.layer("logic").definedBy("com.devonfw.sample.archunit.logic..") //
21+
.layer("dataaccess").definedBy("com.devonfw.sample.archunit.dataaccess..") //
22+
.layer("service").definedBy("com.devonfw.sample.archunit.service..") //
23+
.layer("client").definedBy("com.devonfw.sample.archunit.client..")
24+
25+
.whereLayer("common").mayOnlyAccessLayers("common")
26+
// L01: Common Layer doesnt depend on any other layer
27+
.whereLayer("client").mayOnlyBeAccessedByLayers("client")
3828
// L02: verifying that only client layer code may depend on client layer.
39-
.whereLayer("client").mayOnlyAccessLayers("client", "java")
29+
.whereLayer("client").mayOnlyAccessLayers("client")
4030
// L03: verifying that client layer does not depend on logic layer.
4131
// L04: verifying that client layer does not depend on dataaccess layer.
4232
// L05: verifying that client layer does not depend on batch layer.
43-
.whereLayer("service").mayOnlyBeAccessedByLayers("ui", "client")
44-
.whereLayer("service").mayOnlyAccessLayers("logic", "java", "javax", "common")
33+
.whereLayer("service").mayOnlyBeAccessedByLayers("client")
34+
.whereLayer("service").mayOnlyAccessLayers("logic", "common")
4535
// L08: verifying that code from service layer does not depend on dataaccess layer.
4636
// L06: verifying that service layer does not on depend batch layer.
47-
.whereLayer("batch").mayOnlyAccessLayers("java")
37+
//.whereLayer("batch").mayOnlyAccessLayers("java")
4838
// L07: verifying that batch layer does not depend on service layer.
4939
// L11: verifying that batch layer does not depend on dataaccess layer.
50-
.whereLayer("logic").mayOnlyBeAccessedByLayers("service")
51-
.whereLayer("logic").mayOnlyAccessLayers("dataaccess", "java", "javax", "mapper", "common", "logger")
40+
.whereLayer("logic").mayOnlyBeAccessedByLayers("service")
41+
.whereLayer("logic").mayOnlyAccessLayers("dataaccess", "common")
5242
// L09: verifying that code from logic layer does not depend on service layer (of same app).
5343
.whereLayer("dataaccess").mayOnlyBeAccessedByLayers("logic")
54-
.whereLayer("dataaccess").mayOnlyAccessLayers("dataaccess", "java", "javax", "common", "spring", "database")
44+
.whereLayer("dataaccess").mayOnlyAccessLayers("dataaccess", "common")
5545
// L10: verifying that dataaccess layer does not depend on service layer.
5646
// L12: verifying that dataaccess layer does not depend on logic layer.
47+
.withOptionalLayers(true)
5748
.because("Dependency of technical layers violates architecture rules.");
5849
// ...
5950

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package com.devonfw.sample.archunit;
2+
3+
import com.tngtech.archunit.core.importer.ImportOption;
4+
import com.tngtech.archunit.junit.AnalyzeClasses;
5+
import com.tngtech.archunit.junit.ArchTest;
6+
import com.tngtech.archunit.lang.ArchRule;
7+
8+
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;
9+
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
10+
11+
@AnalyzeClasses(packages = "com.devonfw.sample.archunit", importOptions = ImportOption.DoNotIncludeTests.class)
12+
public class LayerDependencyRulesTest {
13+
14+
// 'access' catches only violations by real accesses, i.e. accessing a field, calling a method; compare 'dependOn' further down
15+
16+
// L09: verifying that code from logic layer does not access service layer (of same app).
17+
@ArchTest
18+
static final ArchRule logic_should_not_access_services =
19+
noClasses().that().resideInAPackage("..logic..")
20+
.should().accessClassesThat().resideInAPackage("..service..");
21+
22+
// L10: verifying that dataaccess layer does not access service layer.
23+
// L12: verifying that dataaccess layer does not access logic layer.
24+
@ArchTest
25+
static final ArchRule persistence_should_not_access_services_or_logic =
26+
noClasses().that().resideInAPackage("..dataaccess..")
27+
.should().accessClassesThat().resideInAnyPackage("..service..", "..logic..");
28+
29+
@ArchTest
30+
static final ArchRule services_should_only_be_accessed_by_clients_or_other_services =
31+
classes().that().resideInAPackage("..service..")
32+
.should().onlyBeAccessed().byAnyPackage("..client..", "..service..");
33+
34+
@ArchTest
35+
static final ArchRule services_should_only_access_logic_common_or_other_services =
36+
classes().that().resideInAPackage("..service..")
37+
.should().onlyAccessClassesThat().resideInAnyPackage("..service..", "..common..", "..logic..", "java..", "javax..");
38+
39+
// 'dependOn' catches a wider variety of violations, e.g. having fields of type, having method parameters of type, extending type ...
40+
41+
// L09: verifying that code from logic layer does not depend on service layer (of same app).
42+
@ArchTest
43+
static final ArchRule logic_should_not_depend_on_services =
44+
noClasses().that().resideInAPackage("..logic..")
45+
.should().dependOnClassesThat().resideInAPackage("..service..");
46+
47+
// L06: verifying that service layer does not depend on batch layer.
48+
// L08: verifying that service layer does not depend on dataaccess layer.
49+
@ArchTest
50+
static final ArchRule services_should_not_depend_on_batch_or_persistence =
51+
noClasses().that().resideInAPackage("..service..")
52+
.should().dependOnClassesThat().resideInAnyPackage("..batch..", "..dataaccess..");
53+
54+
// L10: verifying that dataaccess layer does not depend on service layer.
55+
// L12: verifying that dataaccess layer does not depend on logic layer.
56+
@ArchTest
57+
static final ArchRule persistence_should_not_depend_on_services_or_logic =
58+
noClasses().that().resideInAPackage("..dataaccess..")
59+
.should().dependOnClassesThat().resideInAnyPackage("..service..", "..logic..");
60+
61+
@ArchTest
62+
static final ArchRule services_should_only_be_depended_on_by_controllers_or_other_services =
63+
classes().that().resideInAPackage("..service..")
64+
.should().onlyHaveDependentClassesThat().resideInAnyPackage("..controller..", "..service..");
65+
66+
@ArchTest
67+
static final ArchRule services_should_only_depend_on_logic_common_or_other_services =
68+
classes().that().resideInAPackage("..service..")
69+
.should().onlyDependOnClassesThat().resideInAnyPackage("..service..", "..logic..", "..common..", "java..", "javax..");
70+
71+
// L01: Common Layer does not depend on any other layer
72+
@ArchTest
73+
static final ArchRule common_should_only_depend_on_common =
74+
classes().that().resideInAPackage("..common..")
75+
.should().onlyDependOnClassesThat().resideInAnyPackage("..common..", "java..", "javax..");
76+
77+
// L02: verifying that only client layer code may depend on client layer.
78+
@ArchTest
79+
static final ArchRule client_should_only_depend_on_client =
80+
classes().that().resideInAPackage("..client..")
81+
.should().onlyDependOnClassesThat().resideInAnyPackage("..client..", "java..", "javax..").allowEmptyShould(true);
82+
83+
// L03: verifying that client layer does not depend on logic layer.
84+
// L04: verifying that client layer does not depend on dataaccess layer.
85+
// L05: verifying that client layer does not depend on batch layer.
86+
@ArchTest
87+
static final ArchRule client_should_not_depend_on_logic_persistence_or_batch_layer =
88+
noClasses().that().resideInAPackage("..client..")
89+
.should().dependOnClassesThat().resideInAnyPackage("..logic..", "..dataaccess..", "..batch..").allowEmptyShould(true);
90+
91+
// L07: verifying that batch layer does not depend on service layer.
92+
// L11: verifying that batch layer does not depend on dataaccess layer.
93+
@ArchTest
94+
static final ArchRule batch_should_not_depend_on_service_or_persistence =
95+
noClasses().that().resideInAPackage("..batch..")
96+
.should().dependOnClassesThat().resideInAnyPackage("..service..", "..dataaccess..").allowEmptyShould(true);
97+
}

0 commit comments

Comments
 (0)