1

在我们的架构指南中,我们应该只从域模型或存储库实现(位于基础设施层)中实例化业务异常

我们通常使用工厂方法创建异常。

所以我想为此制定一个 ArchUnit 规则。应该遵循以下原则:只有位于domain或实现的Repositories类才能大声调用带有注释的类的静态方法@BusinessException

我们所有的业务异常都使用@BusinessException 进行注释。所以很容易找到它们。

我尝试了它的变体:

 noClasses().that().resideOutsideOfPackages(DOMAIN).or(areImplementing(Repository.class))
                .should().callMethodWhere(
                target(owner(isAnnotatedWith(BusinessException.class)))
                        .and(target(modifier(JavaModifier.STATIC))));

areImplementing()是一个自定义谓词,用于确定一个类是否是存储库的实现。

此代码无法编译。isAnnotatedWith不能这样使用。

我也尝试过

methods().that().areStatic()
              .and().areDeclaredInClassesThat().areAnnotatedWith(BusinessException.class)
              .should().onlyBeCalled().byClassesThat(areImplementing(Repository.class))

再次,这不编译,onlyBeCalled不存在。

有人有想法吗?

4

1 回答 1

1

我不完全确定是否有更短的形式来表达你想要的,但我相信以下使用自定义谓词的片段可以完成这项工作。

noClasses().that()
            // Restriction applies to all classes outside DOMAIN package that are not Repository classes
            .resideOutsideOfPackages(DOMAIN)
            .and()
            .areNotAssignableFrom(Repository.class)
            .should()
            .callMethodWhere(describe("static methods in BusinessExceptions",
                              // Target method may not reside in class annotated with BusinessException
                methodCall -> methodCall.getTarget().getOwner().isAnnotatedWith(BusinessException.class) 
                       // And target method may not have the static modifier
                    && methodCall.getTarget()
                        .resolve()
                        .stream()
                        .anyMatch(m -> m.getModifiers().contains(JavaModifier.STATIC))));

我唯一不确定的是它methodCall.getTarget().resolve()返回一组 JavaMethod 类。

于 2021-06-04T13:17:05.397 回答