-
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
Usability: Java confuses the static and non-static versions of DescribedPredicate.and() when using the API the wrong way. #1260
Comments
I've already seen this unfortunate confusion in #1152 (comment). Sorry for the inconvenience!
Moving the static method somewhere else would be a breaking change, also for the legit usages, but the method could log a warning when used with a single argument; maybe that would help already? |
Regarding the Problem at hand: I can also see that Factory methods like the static and() are useful. However, do they really need to be in the same class so that the Java Typesystem can confuse one for the other? Or could they be moved to a different class (maybe one whose name ends in "Factory" to make its purpose clear?) Regarding Breaking Changes: Regarding the proposed warning: |
It's not that obvious to me: A usage like
There is no doubt that compile-time safety is more desirable. What if we changed the signature like this? - public static <T> DescribedPredicate<T> and(DescribedPredicate<? super T>... predicates)
+ public static <T> DescribedPredicate<T> and(DescribedPredicate<? super T> predicate1, DescribedPredicate<? super T> predicate2, DescribedPredicate<? super T>... morePredicates) I think that this would prevent the confusion without breaking legit use cases that spell out individual predicates as method arguments. It would only break use cases of the factory method that pass an array of
|
I spottet a strange phaenomenon when using accessTargetWhere():
when using it like this:
then IntelliJ IDEA gives me the following rather cryptic warning
Static member 'com.tngtech.archunit.base.DescribedPredicate<com.tngtech.archunit.core.domain.properties.HasOwner<com.tngtech.archunit.core.domain.JavaClass>>.and(com.tngtech.archunit.base.DescribedPredicate<? super com.tngtech.archunit.core.domain.JavaAccess<?>>...)' accessed via instance reference
However, when ignoring this warning, the rule above flags all method calls to method named "get" as violations instead of only those to Optional.get().
After some trial-and-error I found out that rewriting the rule like this:
solves both the warning and the problem.
The key to understanding this issue is that in the first version, the method call to and() in above rule calls the static method and() in line 160 of DescribedPredicate.java
As one can see, this method builds and AndPredicate, but passed only the predicates (right-hand side) and not this (left-hand side) into it. The left-hand side of the and() is hence lost and the rule becomes
'no classes should access target where name matching 'get', because We want to use Optional.orElseThrow() instead of Optional.get().'
In the second version of the rule, the call to and() calls the non-static method and() in line 59 of DescribedPredicate.java:
which builds the AndPredicate correctly.
Now my questions are:
NOTE: a similar problem seems to exist for the method or() in the same class as well.
The text was updated successfully, but these errors were encountered: