The sample app provided in this github repository is using a layered architecture. However, if you use hexagonal architecture instead, you can use onion instead. An example can be found in the official ArchUnit example repository.
The layered architecture used in this sample app is based on the template of devonfw Java architecture.
It uses a classic three-layered architecture as descibed in the documentation linked above.
ArchUnit provides the method layeredArchitecture()
to easily construct rules to enforce a layered architecture.
An example from this repository can be found here.
The class ArchRuleDefinition
provides methods like classes()
,noClasses()
, methods()
to construct an ArchRule
. Examples can be found in in this repository or in the official example repository of ArchUnit.
To implement a custom ArchRule
DescribedPredicate
and ArchCondition
can be used like this:
classes that ${PREDICATE} should ${CONDITION}
The predicate filters a set of classes to verify some condition. An example can be found in this repository.
The ArchCondition checks whether the filtered set satisfies a given condition. An example can be found in this repository.
Further information is available in the official user guide.
Sometimes rules need custom error messages. because()
and as()
can be used to modify the output of error messages. Further information can be found in the official user guide.
because("message")
concatenates the fluent API messages utilized by ArchUnit.
For example:
noClasses()
.that(DescribedPredicate("message1"))
.should(ArchCondition("message2"))
.because("message3")
would result in 'no classes that "message1" should "message2", because "message3"'.
Using as("message")
enforces printing only the message
string.
For example:
noClasses()
.that(DescribedPredicate("message1"))
.should(ArchCondition("message2"))
.as("message3")
would result in '"message3"'.
If a rule failed unexpectedly, it might failed to check any classes, as that either means that no classes have been passed to the rule at all or that no classes passed the rule matching the that()
clause. To allow rules being evaluated without checking any classes you can either use ArchRule.allowEmptyShould(true)
on a single rule or set the configuration property archRule.failOnEmptyShould = false
to change the behavior globally.
Further information can be found in the official user guide.