Skip to content

Latest commit

 

History

History
70 lines (49 loc) · 3.82 KB

best-practices.adoc

File metadata and controls

70 lines (49 loc) · 3.82 KB

Hexagonal Architecture

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.

Layered Architecture

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.

ArchRule

General

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.

Custom Rules

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.

Error Message

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"'.

Error Handling

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.