ArchUnits layeredArchitecture 规则不包含字段

ArchUnits layeredArchitecture rule doesn't include fields

我们通过一些 ArchUnit 规则检查我们的软件架构。

其中之一是对我们的分层架构的测试。

这适用于方法。 如果我们从 layer1 访问 layer3 的方法,我们将得到一个异常。

但是如果从 layer1 访问在 layer3 中声明的字段,则不会抛出异常。

   .layer("layer1").definedBy("com.acme.layer1")
   .layer("layer2").definedBy("com.acme.layer2")
   .layer("layer3").definedBy("com.acme.layer3")
   .whereLayer("layer3").mayNotBeAccessedByAnyLayer()
   .whereLayer("layer2").mayOnlyAccessedByLayers("layer3")
   .as("Respect the layered architecture");

如果我们将字段从 layer3 导入到 layer1,这不会抛出异常 class:

package com.acme.layer1

import static com.acme.layer3.SOME_LABEL

public class x {
   ...
}

我们的期望是,从任何其他层中的 layer3 访问字段也应该抛出异常。 或者有其他方法可以检查吗?

我的回答基于以下假设:com.acme.layer3.SOME_LABELconstant expression,类似于 public static final String SOME_LABEL = "..."

Compile-time 常量在编译期间内联。如果你的代码看起来像

String label = SharedConstants.SOME_LABEL;

然后编译后的字节码包含 SharedConstants.SOME_LABEL 的精确值。字节码中仍然没有对该字段的引用。 (The Static Final Inline Trap)

ArchUnit 通过分析字节码收集所有信息,另见 ArchUnit User Guide。因为字节码中没有关于SharedConstants.SOME_LABEL的信息,所以ArchUnit不知道这个访问。

总结:这是 ArchUnit 和所有其他仅依赖于字节码的库的限制。