gpt4 book ai didi

java - Archunit 包 A 不能访问包 B,除了子包 A.X 可以访问 B.Y

转载 作者:行者123 更新时间:2023-12-05 05:32:45 24 4
gpt4 key购买 nike

我们正在将代码重构为六边形架构,代码中的每个域都是一个单独的 gradle 模块。目前所有的代码都是一个模块,每个领域都有一个包,模块之间可以自由交互。在将每个域包提取到域模块之前,我们希望首先在包级别上获得正确的体系结构边界。为此,我们希望使用 archunit 来实现架构。

在每个域包中,我使用层重构了我们新架构的规则:

    @ParameterizedTest(name = "The hex architecture should be respected in module {0}.")
@MethodSource("provideDomains")
void hexArchRespectedInEveryModule(String pkg) {
layeredArchitecture()
.consideringOnlyDependenciesInAnyPackage(ROOT_DOTDOT)
.withOptionalLayers(true)
.layer("api").definedBy(ROOT_DOT + pkg + ".api..")
.layer("usecases").definedBy(ROOT_DOT + pkg + ".usecases..")
.layer("domain").definedBy(ROOT_DOT + pkg + ".domain..")
.layer("incoming infra").definedBy(ROOT_DOT + pkg + ".infrastructure.incoming..")
.layer("outgoing infra").definedBy(ROOT_DOT + pkg + ".infrastructure.outgoing..")
.layer("vocabulary").definedBy(ROOT_DOT + pkg + ".vocabulary..")
.whereLayer("incoming infra").mayOnlyAccessLayers("api", "vocabulary")
.whereLayer("usecases").mayOnlyAccessLayers("api", "domain", "vocabulary")
.whereLayer("domain").mayOnlyAccessLayers("domain", "vocabulary")
.whereLayer("outgoing infra").mayOnlyAccessLayers("domain", "vocabulary")
.check(new ClassFileImporter().importPackages(toPackage(pkg)));
}

但是,我未能编写检查,以确保一个域只能通过使用另一个域提供的 API 从传出的基础设施适配器调用它来访问另一个域。对于那种情况,我必须写一些这样的东西:“域 A 中的任何包都不能调用域 B,除了 A 的传出基础设施中的包可以调用 B 中的 API 子包。

我尝试了几种不同的变体,最终认为这是正确的,但似乎仍然没有发现违规行为:

    @ParameterizedTest(name = "Module {0} should only depend on itself, except outgoing infra on other apis")
@MethodSource("provideDomains")
void domainModuleBoundariesAreRespected(String module) {
noClasses()
.that().resideInAPackage(includeSubPackages(toPackage(module)))
.should().dependOnClassesThat().resideInAnyPackage(includeSubPackages(getPackagesOtherThan(module)))
.allowEmptyShould(true)
.check(allButOutgoingInfra);
classes()
.that().resideInAPackage(outGoingInfra(toPackage(module)))
.should().dependOnClassesThat().resideInAnyPackage(toApi(getPackagesOtherThan(module)))
.allowEmptyShould(true)
.check(allClasses);
}

我添加了一些辅助静态方法,添加“..”以获取子包,或向包添加后缀以指示子包。 “getPackagesOtherThan(module)”返回其他域包的列表。

我找到了 this问题,但我的问题似乎有所不同,因为我有两个相互关联的子包,而不仅仅是一个。

最佳答案

对于这个用例,我实际上会使用“切片”API(参见 https://www.archunit.org/userguide/html/000_Index.html#_slices)。 IE。同样的事情还允许您(“垂直”)按域对您的应用程序进行切片,并断言这些切片是无循环的。最简单的方法是如果你有一个非常一致的代码结构,你可以用一个简单的包模式匹配你的域包,比如 com.myapp.(*).. 你的域是什么如 com.myapp.customer..com.myapp.shop.. 等。否则,您始终可以使用 SliceAssignment 高度自定义它>(比较上面的用户指南链接)。

在任何情况下,一旦您按域创建切片,您就可以在它们上定义自定义 ArchCondition:

slices()
.matching("com.myapp.(*)..")
.as("Domain Modules")
.namingSlices("Module[$1]")
.should(only_depend_on_each_other_through_allowed_adapters())

// ...

ArchCondition<Slice> only_depend_on_each_other_through_allowed_adapters() {
return new ArchCondition<Slice>("only depend on each other through allowed adapters") {
final PackageMatcher validOutgoingAdapter = PackageMatcher.of("..outgoing..");
final PackageMatcher validIncomingAdapter = PackageMatcher.of("..incoming..");
final Map<JavaClass, Slice> classesToModules = new HashMap<>();

@Override
public void init(Collection<Slice> allModules) {
// create some reverse lookup so we can easily find the module of each class
allModules.forEach(module -> module.forEach(clazz -> classesToModules.put(clazz, module)));
}

@Override
public void check(Slice module, ConditionEvents events) {
module.getDependenciesFromSelf().stream()
// The following are dependencies to other modules
.filter(it -> classesToModules.containsKey(it.getTargetClass()))
// The following violate either the outgoing or incoming adapter rule
.filter(it ->
!validOutgoingAdapter.matches(it.getOriginClass().getPackageName()) ||
!validIncomingAdapter.matches(it.getTargetClass().getPackageName())
)
.forEach(dependency -> events.add(SimpleConditionEvent.violated(dependency,
String.format("%s depends on %s in an illegal way: %s",
module, classesToModules.get(dependency.getTargetClass()), dependency.getDescription()))));
}
};

这可能不完全符合您的需求(例如,您可能需要更精确地检查传入/传出适配器的外观),但我希望它能帮助您入门。

关于java - Archunit 包 A 不能访问包 B,除了子包 A.X 可以访问 B.Y,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74011863/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com