ArchUnit icon indicating copy to clipboard operation
ArchUnit copied to clipboard

no obvious negation for slices and modules.

Open xenoterracide opened this issue 5 months ago • 1 comments

So, I've been using a design that is essentially isolated slices except for a shared "commons" which contains things like ids, Country, Address, etc, which need to be available for more than one aggregate. Problem is neither slices no modules have a way to essentially say "these packages in domain.model" are not allowed to depend on each other except via "domain.model.comons". Now there is a similar method to what I just said, but it still results in a dependency cycle as it's not an exclusion of domain.model.commons

domain.model.user must not depend on domain.model.account or vice versa both may depend on domain.model.commons

as of right now commons is my only exception... my other dependencies are enforced via layers.

xenoterracide avatar Aug 06 '25 16:08 xenoterracide

From my own point of view, I never added negation / forbidding, because in general I think it's less error-prone to describe the allowed structure instead of forbidding parts of a structure (which could also lead to circumvention then).

I'm not sure I fully understand what your target state is, but if you have a very custom scenario you could outline the dependencies explicitly, e.g.:

import static com.tngtech.archunit.library.modules.syntax.AllowedModuleDependencies.allow;
import static com.tngtech.archunit.library.modules.syntax.ModuleDependencyScope.consideringAllDependencies;
import static com.tngtech.archunit.library.modules.syntax.ModuleRuleDefinition.modules;
// ...
modules().definedByPackages("domain.model.(*)..")
  .should().respectTheirAllowedDependencies(
    allow()
      .fromModule("user").toModules("common")
      .fromModule("account").toModules("common"),
    consideringAllDependencies()
  )

Alternatively, if you want the modules more generically without spelling them out explicitly, you could also use the slices API and just ignore dependencies to common? E.g.

slices().matching("domain.model.(*)..")
  .should().notDependOnEachOther()
    .ignoreDependency(
      DescribedPredicate.alwaysTrue(),
      JavaClass.Predicates.resideInAnyPackage("domain.model.commons..")
    )

codecholeric avatar Sep 01 '25 21:09 codecholeric