Contribute to help us improve!

Are there edge cases or problems that we didn't consider? Is there a technical pitfall that we should add? Did we miss a comma in a sentence?

If you have any input for us, we would love to hear from you and appreciate every contribution. Our goal is to learn from projects for projects such that nobody has to reinvent the wheel.

Let's collect our experiences together to make room to explore the novel!

To contribute click on Contribute to this page on the toolbar.

Architecture Tests

The verification of architecture guidelines requires that basic naming, package structure and dependencies are checked. This should also be fully automated like the unit tests mentioned above. ArchUnit is a testing framework that is based on JUnit 5 and enables naming, dependencies and other coding styles to be checked.

The following code example shows a test that checks the naming of the domain entities. The biolerplate code can be reduced to a minimum with appropriate annotations such as @AnalyzeClasses and @ArchTest.

Naming convention test
@AnalyzeClasses(packages = "com.myapp.component")
public class NamingRuleTest {
    @ArchTest
    static ArchRule entities_named_correctly =
            classes()
                    .that().resideInAPackage("..domain.model..")
                    .and().areNotInterfaces()
                    .should().haveSimpleNameEndingWith("Entity");
}

ArchUnit also offers support for well-known high-level architectures such as layered architecture or onion architecture (see also hexagonal architecture).

Here, only the packages of the layers and the dependencies of the layers have to be defined. The following example shows this as an example.

Layered Architecture Test
@AnalyzeClasses(packages = "com.myapp.component")
public class DependencyRuleTest {
    @ArchTest
    static ArchRule layered_architecture_check =
            layeredArchitecture().consideringAllDependencies()
                    .layer("Service").definedBy("..service..")
                    .layer("Logic").definedBy("..logic..")
                    .layer("Domain").definedBy("..domain..")
                    .whereLayer("Service").mayNotBeAccessedByAnyLayer()
                    .whereLayer("Logic").mayOnlyBeAccessedByLayers("Service")
                    .whereLayer("Domain").mayOnlyBeAccessedByLayers("Logic");
}

You can find much more examples for your need here.

It should be noted that ArchUnit provides a good check of architectural guidelines within a module. Especially with larger applications, it makes sense to use Maven or Gradle modules to control dependencies and to structure the application. In this case, alternative means such as Sonargraph should be considered.