Skip to content
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

Didn't find rule 'classes should not be final' #1363

Open
ghusta opened this issue Oct 12, 2024 · 4 comments
Open

Didn't find rule 'classes should not be final' #1363

ghusta opened this issue Oct 12, 2024 · 4 comments

Comments

@ghusta
Copy link

ghusta commented Oct 12, 2024

I didn't find a rule to assert that classes should (or not) be final.

For example I'd like to do this :

        ArchRule rule = classes()
                .that().areAnnotatedWith(Entity.class)
                .should().notBeFinal();

I was just able to add a custom ArchCondition like :

    static ArchCondition<JavaClass> beFinal = new ArchCondition<>("be final") {
        @Override
        public void check(JavaClass javaClass, ConditionEvents events) {
            boolean isFinal = javaClass.getModifiers().contains(JavaModifier.FINAL);
            if (!isFinal) {
                String message = String.format("%s is not final", javaClass.getName());
                events.add(SimpleConditionEvent.violated(javaClass, message));
            }
        }
    };

    static ArchCondition<JavaClass> notBeFinal = new ArchCondition<>("not be final") {
        @Override
        public void check(JavaClass javaClass, ConditionEvents events) {
            boolean isFinal = javaClass.getModifiers().contains(JavaModifier.FINAL);
            if (isFinal) {
                String message = String.format("%s is final", javaClass.getName());
                events.add(SimpleConditionEvent.violated(javaClass, message));
            }
        }
    };
@hankem
Copy link
Member

hankem commented Oct 12, 2024

You can use .should().notHaveModifier(JavaModifier modifier):

    ArchRule rule = classes()
            .that().areAnnotatedWith(Entity.class)
            .should().notHaveModifier(JavaModifier.FINAL);

@ghusta
Copy link
Author

ghusta commented Oct 12, 2024

Thank you !
Good to know there is something shorter to write.

At first I was looking for methods similar to bePublic() or bePrivate(), but was suprised to not find beFinal()...

@hankem
Copy link
Member

hankem commented Oct 13, 2024

bePublic() and bePrivate() had been added more than 7 years ago (f03e630); I guess the focus back then was more on supporting the most relevant architectural use cases. I think that beFinal() is more for a coding convention or implementation use case. But I agree, it could be added to the fluent API.

Just one more remark on shorter implementations:

For ArchConditions that essentially check a predicate, you can use ArchConditions.be or ArchConditions.have.

If there was no predefined method in the fluent API, you could still simplify your conditions using

import static com.tngtech.archunit.base.DescribedPredicate.describe;
import static com.tngtech.archunit.lang.conditions.ArchConditions.be;
import static com.tngtech.archunit.lang.conditions.ArchConditions.not;

to

ArchCondition<JavaClass> beFinal = be(describe("final", javaClass ->
        javaClass.getModifiers().contains(JavaModifier.FINAL))
);

ArchCondition<JavaClass> notBeFinal = not(beFinal);

@ghusta
Copy link
Author

ghusta commented Oct 14, 2024

Thank you for your clarifications.

Using a predicate is indeed shorter and more elegant 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants