Skip to content

Commit

Permalink
add component type dependencies to self
Browse files Browse the repository at this point in the history
Instead of manually adding component type reverse dependencies, we can simply reuse all dependencies from self for the reverse lookup. This does not only speed up the reverse lookup by about factor 2 on my machine, it also makes it trivial in the future to add reverse dependencies for any further new types of dependencies from self.

Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>
  • Loading branch information
codecholeric committed Dec 15, 2020
1 parent b7d929b commit 4b6c645
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 81 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.tngtech.archunit.example.layers.controller.two.UseCaseTwoController;
import com.tngtech.archunit.example.layers.security.Secured;

@SuppressWarnings("unused")
@MyService
@ComplexServiceAnnotation(
controllerAnnotation = @ComplexControllerAnnotation(simpleControllerAnnotation = @SimpleControllerAnnotation),
Expand All @@ -17,9 +18,6 @@
serviceType = ServiceType.STANDARD
)
public class ServiceViolatingLayerRules {
public static final String illegalAccessToController = "illegalAccessToController";
public static final String doSomething = "doSomething";
public static final String dependentMethod = "dependentMethod";

void illegalAccessToController() {
System.out.println(UseCaseOneTwoController.someString);
Expand All @@ -34,7 +32,16 @@ public SomeGuiController dependentMethod(UseCaseTwoController otherController) {
return null;
}

public SomeGuiController[][] dependentOnComponentTypeMethod(UseCaseTwoController[] otherController) {
return null;
}

@Secured
public void properlySecured() {
}

public static final String illegalAccessToController = "illegalAccessToController";
public static final String doSomething = "doSomething";
public static final String dependentMethod = "dependentMethod";
public static final String dependentOnComponentTypeMethod = "dependentOnComponentTypeMethod";
}
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@
import static com.tngtech.archunit.example.layers.core.VeryCentralCore.DO_CORE_STUFF_METHOD_NAME;
import static com.tngtech.archunit.example.layers.persistence.layerviolation.DaoCallingService.violateLayerRules;
import static com.tngtech.archunit.example.layers.service.ServiceViolatingLayerRules.dependentMethod;
import static com.tngtech.archunit.example.layers.service.ServiceViolatingLayerRules.dependentOnComponentTypeMethod;
import static com.tngtech.archunit.example.layers.service.ServiceViolatingLayerRules.illegalAccessToController;
import static com.tngtech.archunit.testutils.CyclicErrorMatcher.cycle;
import static com.tngtech.archunit.testutils.ExpectedAccess.callFromConstructor;
Expand Down Expand Up @@ -251,7 +252,7 @@ private static void expectAccessToStandardStreams(ExpectedTestFailures expectFai
.inLine(14))
.by(callFromMethod(ServiceViolatingLayerRules.class, "illegalAccessToController")
.getting().field(System.class, "out")
.inLine(25));
.inLine(23));
}

private static void expectThrownGenericExceptions(ExpectedTestFailures expectFailures) {
Expand Down Expand Up @@ -686,13 +687,13 @@ Stream<DynamicTest> LayerDependencyRulesTest() {
"should access classes that reside in a package '..controller..'")
.by(callFromMethod(ServiceViolatingLayerRules.class, illegalAccessToController)
.getting().field(UseCaseOneTwoController.class, someString)
.inLine(25))
.inLine(23))
.by(callFromMethod(ServiceViolatingLayerRules.class, illegalAccessToController)
.toConstructor(UseCaseTwoController.class)
.inLine(26))
.inLine(24))
.by(callFromMethod(ServiceViolatingLayerRules.class, illegalAccessToController)
.toMethod(UseCaseTwoController.class, doSomethingTwo)
.inLine(27))
.inLine(25))

.ofRule("no classes that reside in a package '..persistence..' should " +
"access classes that reside in a package '..service..'")
Expand All @@ -719,27 +720,32 @@ Stream<DynamicTest> LayerDependencyRulesTest() {
+ "only access classes that reside in any package ['..service..', '..persistence..', 'java..']")
.by(callFromMethod(ServiceViolatingLayerRules.class, illegalAccessToController)
.getting().field(UseCaseOneTwoController.class, UseCaseOneTwoController.someString)
.inLine(25))
.inLine(23))
.by(callFromMethod(ServiceViolatingLayerRules.class, illegalAccessToController)
.toConstructor(UseCaseTwoController.class)
.inLine(26))
.inLine(24))
.by(callFromMethod(ServiceViolatingLayerRules.class, illegalAccessToController)
.toMethod(UseCaseTwoController.class, UseCaseTwoController.doSomethingTwo)
.inLine(27))
.inLine(25))

.ofRule("no classes that reside in a package '..service..' " +
"should depend on classes that reside in a package '..controller..'")
.by(callFromMethod(ServiceViolatingLayerRules.class, illegalAccessToController)
.getting().field(UseCaseOneTwoController.class, someString)
.inLine(25).asDependency())
.inLine(23).asDependency())
.by(callFromMethod(ServiceViolatingLayerRules.class, illegalAccessToController)
.toConstructor(UseCaseTwoController.class)
.inLine(26).asDependency())
.inLine(24).asDependency())
.by(callFromMethod(ServiceViolatingLayerRules.class, illegalAccessToController)
.toMethod(UseCaseTwoController.class, doSomethingTwo)
.inLine(27).asDependency())
.inLine(25).asDependency())
.by(method(ServiceViolatingLayerRules.class, dependentMethod).withParameter(UseCaseTwoController.class))
.by(method(ServiceViolatingLayerRules.class, dependentMethod).withReturnType(SomeGuiController.class))
.by(method(ServiceViolatingLayerRules.class, dependentOnComponentTypeMethod).withParameter(UseCaseTwoController[].class))
.by(method(ServiceViolatingLayerRules.class, dependentOnComponentTypeMethod).dependingOnComponentType(UseCaseTwoController.class))
.by(method(ServiceViolatingLayerRules.class, dependentOnComponentTypeMethod).withReturnType(SomeGuiController[][].class))
.by(method(ServiceViolatingLayerRules.class, dependentOnComponentTypeMethod).dependingOnComponentType(SomeGuiController[].class))
.by(method(ServiceViolatingLayerRules.class, dependentOnComponentTypeMethod).dependingOnComponentType(SomeGuiController.class))
.by(annotatedClass(ServiceViolatingLayerRules.class).withAnnotationParameterType(ComplexControllerAnnotation.class))
.by(annotatedClass(ServiceViolatingLayerRules.class).withAnnotationParameterType(SimpleControllerAnnotation.class))
.by(annotatedClass(ServiceViolatingLayerRules.class).withAnnotationParameterType(SomeEnum.class))
Expand Down Expand Up @@ -783,23 +789,23 @@ Stream<DynamicTest> LayerDependencyRulesTest() {
+ "only depend on classes that reside in any package ['..service..', '..persistence..', 'java..', 'javax..']")
.by(callFromMethod(ServiceViolatingLayerRules.class, illegalAccessToController)
.getting().field(UseCaseOneTwoController.class, someString)
.inLine(25).asDependency())
.inLine(23).asDependency())
.by(callFromMethod(ServiceViolatingLayerRules.class, illegalAccessToController)
.toConstructor(UseCaseTwoController.class)
.inLine(26).asDependency())
.inLine(24).asDependency())
.by(callFromMethod(ServiceViolatingLayerRules.class, illegalAccessToController)
.toMethod(UseCaseTwoController.class, doSomethingTwo)
.inLine(27).asDependency())
.by(method(ServiceViolatingLayerRules.class, dependentMethod)
.withParameter(UseCaseTwoController.class))
.by(method(ServiceViolatingLayerRules.class, dependentMethod)
.withReturnType(SomeGuiController.class))
.by(field(ServiceHelper.class, "properlySecured")
.withAnnotationType(Secured.class))
.by(method(ServiceViolatingLayerRules.class, "properlySecured")
.withAnnotationType(Secured.class))
.by(constructor(ServiceHelper.class)
.withAnnotationType(Secured.class))
.inLine(25).asDependency())
.by(method(ServiceViolatingLayerRules.class, dependentMethod).withParameter(UseCaseTwoController.class))
.by(method(ServiceViolatingLayerRules.class, dependentMethod).withReturnType(SomeGuiController.class))
.by(method(ServiceViolatingLayerRules.class, dependentOnComponentTypeMethod).withParameter(UseCaseTwoController[].class))
.by(method(ServiceViolatingLayerRules.class, dependentOnComponentTypeMethod).dependingOnComponentType(UseCaseTwoController.class))
.by(method(ServiceViolatingLayerRules.class, dependentOnComponentTypeMethod).withReturnType(SomeGuiController[][].class))
.by(method(ServiceViolatingLayerRules.class, dependentOnComponentTypeMethod).dependingOnComponentType(SomeGuiController[].class))
.by(method(ServiceViolatingLayerRules.class, dependentOnComponentTypeMethod).dependingOnComponentType(SomeGuiController.class))
.by(field(ServiceHelper.class, "properlySecured").withAnnotationType(Secured.class))
.by(method(ServiceViolatingLayerRules.class, "properlySecured").withAnnotationType(Secured.class))
.by(constructor(ServiceHelper.class).withAnnotationType(Secured.class))
.by(annotatedClass(ServiceViolatingDaoRules.class).annotatedWith(MyService.class))
.by(annotatedClass(ServiceViolatingLayerRules.class).annotatedWith(MyService.class))
.by(annotatedClass(ServiceImplementation.class).annotatedWith(MyService.class))
Expand Down Expand Up @@ -839,17 +845,17 @@ Stream<DynamicTest> LayeredArchitectureTest() {

.by(callFromMethod(ServiceViolatingLayerRules.class, "illegalAccessToController")
.toConstructor(UseCaseTwoController.class)
.inLine(26)
.inLine(24)
.asDependency())

.by(callFromMethod(ServiceViolatingLayerRules.class, "illegalAccessToController")
.toMethod(UseCaseTwoController.class, "doSomethingTwo")
.inLine(27)
.inLine(25)
.asDependency())

.by(callFromMethod(ServiceViolatingLayerRules.class, "illegalAccessToController")
.getting().field(UseCaseOneTwoController.class, "someString")
.inLine(25)
.inLine(23)
.asDependency())

.by(callFromMethod(OtherJpa.class, "testConnection")
Expand All @@ -858,8 +864,11 @@ Stream<DynamicTest> LayeredArchitectureTest() {
.asDependency())

.by(method(ServiceViolatingLayerRules.class, dependentMethod).withParameter(UseCaseTwoController.class))

.by(method(ServiceViolatingLayerRules.class, dependentMethod).withReturnType(SomeGuiController.class))
.by(method(ServiceViolatingLayerRules.class, dependentOnComponentTypeMethod)
.dependingOnComponentType(UseCaseTwoController.class))
.by(method(ServiceViolatingLayerRules.class, dependentOnComponentTypeMethod)
.dependingOnComponentType(SomeGuiController.class))

.by(annotatedClass(ServiceViolatingLayerRules.class).withAnnotationParameterType(ComplexControllerAnnotation.class))
.by(annotatedClass(ServiceViolatingLayerRules.class).withAnnotationParameterType(SimpleControllerAnnotation.class))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@ public ExpectedDependency withReturnType(Class<?> returnType) {
return new ExpectedDependency(owner, returnType, dependencyPattern);
}

public ExpectedDependency dependingOnComponentType(Class<?> componentType) {
String dependencyPattern = getDependencyPattern(getOriginName(), "depends on component type", componentType.getName(), 0);
return new ExpectedDependency(owner, componentType, dependencyPattern);
}

public ExpectedDependency withAnnotationType(Class<?> annotationType) {
return new ExpectedDependency(owner, annotationType, getDependencyPattern(getOriginName(), "is annotated with", annotationType.getName(), 0));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1285,12 +1285,13 @@ void completeAnnotations(final ImportContext context) {
}
}

void completeFrom(ImportContext context) {
JavaClassDependencies completeFrom(ImportContext context) {
completeComponentType(context);
for (JavaCodeUnit codeUnit : codeUnits) {
codeUnit.completeFrom(context);
}
javaClassDependencies = new JavaClassDependencies(this);
return javaClassDependencies;
}

private void completeComponentType(ImportContext context) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,8 @@ static JavaClasses of(
JavaPackage defaultPackage = JavaPackage.from(allClasses);
for (JavaClass clazz : allClasses) {
setPackage(clazz, defaultPackage);
clazz.completeFrom(importContext);
reverseDependenciesCreation.registerDependenciesOf(clazz);
JavaClassDependencies classDependencies = clazz.completeFrom(importContext);
reverseDependenciesCreation.registerDependenciesOf(clazz, classDependencies);
}
reverseDependenciesCreation.finish(allClasses);
return new JavaClasses(defaultPackage, selectedClasses);
Expand Down
Loading

0 comments on commit 4b6c645

Please sign in to comment.