-
Notifications
You must be signed in to change notification settings - Fork 299
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve ArchCondition that checks for transitive dependencies #878
Improve ArchCondition that checks for transitive dependencies #878
Conversation
bfe8370
to
747c277
Compare
Hi @codecholeric. Do you have time for some feedback on the PR? And maybe you could approve the execution of workflows? Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot, looks really nice and solves the issue with overboarding transitive violations very nicely 😄
Hope you're not regretting asking for feedback, because I usually have a lot of comments and questions 😂
My biggest pain point in general is the semantics of the name transitivelyDependOnAnyClassesThat
vs transitivelyDependOnClassesThat
is super vague to me 🤔 Because I would argue that "depend on any classes that" and "depend on classes that" means exactly the same?
I'm starting to wonder if we even need both versions. Are there really use cases where I would want to use the old version transitivelyDependOnClassesThat
? What do you think @hankem? Because if we can't think of any scenarios for the existing version vs the new version, maybe we should just replace it?
...nit/src/main/java/com/tngtech/archunit/lang/conditions/AnyTransitiveDependencyCondition.java
Outdated
Show resolved
Hide resolved
...nit/src/main/java/com/tngtech/archunit/lang/conditions/AnyTransitiveDependencyCondition.java
Outdated
Show resolved
Hide resolved
...nit/src/main/java/com/tngtech/archunit/lang/conditions/AnyTransitiveDependencyCondition.java
Outdated
Show resolved
Hide resolved
...nit/src/main/java/com/tngtech/archunit/lang/conditions/AnyTransitiveDependencyCondition.java
Outdated
Show resolved
Hide resolved
...nit/src/main/java/com/tngtech/archunit/lang/conditions/AnyTransitiveDependencyCondition.java
Outdated
Show resolved
Hide resolved
...nit/src/main/java/com/tngtech/archunit/lang/conditions/AnyTransitiveDependencyCondition.java
Outdated
Show resolved
Hide resolved
archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/ShouldClassesThatTest.java
Outdated
Show resolved
Hide resolved
archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/ShouldClassesThatTest.java
Outdated
Show resolved
Hide resolved
archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/ShouldClassesThatTest.java
Outdated
Show resolved
Hide resolved
archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/ShouldClassesThatTest.java
Show resolved
Hide resolved
archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/ClassesShould.java
Show resolved
Hide resolved
Hi, no regrets here, i really appreciate comprehensive feedback :) ! I was able to correct most of your comments right away, see my comments with the rest I was struggling with the namings around |
0c042b3
to
77831df
Compare
I don't mind replacing the old |
@codecholeric should I then remove the "old" implementation, keep the original fluent API |
Yes, I think this makes sense! Because it will make the API easier to understand and if we can't think of any use case where the other implementation is more appropriate, then we should just remove it. It will be a breaking change though, so perfect opportunity now for ArchUnit 1.0 😉 |
...nit/src/main/java/com/tngtech/archunit/lang/conditions/AnyTransitiveDependencyCondition.java
Outdated
Show resolved
Hide resolved
...nit/src/main/java/com/tngtech/archunit/lang/conditions/AnyTransitiveDependencyCondition.java
Outdated
Show resolved
Hide resolved
e08d73f
to
eba0543
Compare
Okay I removed the existing implementation and solved the rest of your comments. From my point of view the PR is now ready to merge? |
This convenience method also helps users to create standard ArchUnit violation messages, so we offer it as public API. Since we meanwhile have a Java 8 source level we can even put this method into `ConditionEvent` where it fits better. Signed-off-by: Peter Gafert <[email protected]>
The original implementation had the problem that it reported every single transitive dependency that matched the predicate. This would mean, even if a transitive dependency got reported as violation, all further transitive dependencies of that dependency would still be analyzed and potentially also reported as violation. For rules like ``` noClasses() .that().resideInAPackage("..example..") .should().transitivelyDependOnClassesThat().resideInAPackage("..some.framework..") ``` this would mean thousands of violations, even for classes that are only reached through other framework classes. We now do a depth first search approach for all dependency paths that are outgoing from the analyzed classes until we find a matching target. Then we stop and report the path. This way all further dependencies will be omitted and the analysis will complete a lot faster. Issue: TNG#780 Signed-off-by: e.solutions <[email protected]> on-behalf-of: @e-esolutions-GmbH <[email protected]>
Yes, looks good now 🥳 I did some minor changes, e.g. there was a commit in the other PR to more conveniently create condition messages that I cherry-picked in here to merge with this one instead. Other than that very nice and ready to merge 😄 |
Ah, but I just saw that I can't push my changes, |
done! |
eba0543
to
499020a
Compare
@codecholeric thx for your support! Looking forward to see this in ArchUnit 1.0 ❤️ |
Well, thanks for your contribution 😄 Without it I would certainly not have gotten around to improve this now... |
This adds an ArchCondition to the fluent API to check whether there is any matching transitive dependency. This is a much more efficient variant of
#transitivelyDependOnClassesThat
that can be used to detect transitive dependencies in a huge codebase or to classes in large 3rd-party libraries like the Android SDK. It focuses on detecting all direct dependencies of the selected classes that are themselves matched or have any transitive dependencies on matched classes. Thus, it doesn't discover all possible dependency paths but stops at the first match to be fast and resource-friendly.Sample usage:
Then this Architecture
would output the following violations:
Resolves: #780
Resolves: #826