-
Notifications
You must be signed in to change notification settings - Fork 306
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
How to test for access only by subclass #255
Comments
I can write a less specific test, but it allows any subclass of any base class to access any base class rather than just the one they extend: |
|
The above class should fail on exactly three lines 53, 62, 69. |
I agree that the predicate in
does not allow to capture the context of the access – which is also why
cannot easily be implemented, as So similarly to #254, I'd suggest to implement a custom condition. @ArchTest
public static final ArchRule baseClassesShouldOnlyBeAccessedByTheirSubclasses = classes()
.that().resideInAPackage(Issue255.class.getPackage().getName())
.should(onlyBeAccessedBySubclasses());
private static ArchCondition<JavaClass> onlyBeAccessedBySubclasses() {
return new ArchCondition<JavaClass>("only be accessed by subclasses") {
@Override
public void check(JavaClass clazz, ConditionEvents events) {
int nAccessesByOtherClasses = 0;
StringBuilder violations = new StringBuilder();
for (JavaAccess<?> javaAccess : clazz.getAccessesToSelf()) {
boolean originOwnerIsSubclass = javaAccess.getOriginOwner().isAssignableTo(clazz.getName());
if (!originOwnerIsSubclass) {
nAccessesByOtherClasses++;
violations.append(javaAccess.getDescription()).append("\n");
}
}
boolean satisfied = nAccessesByOtherClasses == 0;
String message = clazz.getName() + " is accessed by " + nAccessesByOtherClasses + " classes that are no subclasses";
if (!satisfied) {
message += ":\n" + violations;
}
events.add(new SimpleConditionEvent(clazz, satisfied, message));
}
};
} This catches the illegal access in your line 62
but not your lines 52 and 69:
(which are IMO valid accesses from subclasses, so I still need to understand your use case). P.S. For the formatting, you can use Markdown with triple backticks for code blocks (cf. Creating and highlighting code blocks):
|
Thanks I've reformatted the post above. |
You are correct 52 is an unusual requirement. It turns out that it was believed to be a rule in our codebase, but when I looked at our actual codebase it is violated a lot, and in ways that make no sense to change. |
Thanks @hankem I think I can achieve this requirement with two separate rules, your one, plus a rule around naming. |
Modified message:
|
Second Rule:
|
Thanks for the help. Is there a forum for these sorts of questions? I feel bad creating 'issues' for them. |
Sorry, we don't have a specific forum. You could use StackOverflow? There are already questions up there. Other than that, don't feel bad, we can just tag these issues as question 😃 |
This will apply recursively for multi-dimensional arrays, e.g. for a class `Bar` depending on `Foo[][][]` we would consider `Bar` to have dependencies to `Foo[][][]`, `Foo[][]`, `Foo[]` and `Foo`. Issue: TNG#255 Signed-off-by: Johannes Wengert <johannes.wengert@googlemail.com> Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>
This will apply recursively for multi-dimensional arrays, e.g. for a class `Bar` depending on `Foo[][][]` we would consider `Bar` to have dependencies to `Foo[][][]`, `Foo[][]`, `Foo[]` and `Foo`. Issue: TNG#255 Signed-off-by: Johannes Wengert <johannes.wengert@googlemail.com> Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>
This will apply recursively for multi-dimensional arrays, e.g. for a class `Bar` depending on `Foo[][][]` we would consider `Bar` to have dependencies to `Foo[][][]`, `Foo[][]`, `Foo[]` and `Foo`. Issue: #255 Signed-off-by: Johannes Wengert <johannes.wengert@googlemail.com> Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>
I want to make a rule where classes in a particular package can only be accessed by their subclasses, but I can't figure out how.
Is it possible at the moment?
I thought I could use a DescribedPredicate, but that doesn't provide access to the class that is triggering the check. (i.e. extendThem() only makes sense after the should(), but not before)
Would the following fluent style .byClassesThat().extendThem() be possible to add?
//Not the actual rule
@archtest
public static final ArchRule baseClassesShouldOnlyBeAccessedByTheirSubclasses = classes()
.that().resideInAPackage(BASE)
.should().onlyBeAccessed().byClassesThat().extendThem();
The text was updated successfully, but these errors were encountered: