TNG/ArchUnit项目Lang API深度解析:架构规则的优雅表达

TNG/ArchUnit项目Lang API深度解析:架构规则的优雅表达

ArchUnit A Java architecture test library, to specify and assert architecture rules in plain Java ArchUnit 项目地址: https://gitcode.com/gh_mirrors/ar/ArchUnit

引言

在现代软件开发中,架构规则验证是确保代码质量的重要手段。TNG/ArchUnit项目提供了一套强大的API,其中Lang API作为其高级抽象层,让开发者能够用接近自然语言的语法来表达复杂的架构约束。本文将深入解析Lang API的核心概念和使用方法。

基础规则构建

从原始代码到声明式规则

传统方式下,验证架构规则需要编写冗长的过程式代码,例如检查"service包中的类不应访问controller包中的类"这样的规则。这种代码不仅难以编写,更难以阅读和维护。

Lang API通过流畅接口(Fluent Interface)提供了声明式的规则构建方式:

ArchRule rule = ArchRuleDefinition.noClasses()
    .that().resideInAPackage("..service..")
    .should().accessClassesThat().resideInAPackage("..controller..");

这里的".."是通配符,表示任意层级的子包。这种写法几乎与自然语言描述完全一致,大大提升了代码的可读性。

规则组合

Lang API支持通过逻辑运算符组合多个条件:

noClasses()
    .that().resideInAPackage("..service..")
    .or().resideInAPackage("..persistence..")
    .should().accessClassesThat().resideInAPackage("..controller..")
    .orShould().accessClassesThat().resideInAPackage("..ui..");

成员级别规则

除了类级别的规则,Lang API还支持对类成员(方法、字段等)定义规则:

ArchRule rule = ArchRuleDefinition.methods()
    .that().arePublic()
    .and().areDeclaredInClassesThat().resideInAPackage("..controller..")
    .should().beAnnotatedWith(Secured.class);

API提供了多种入口方法:methods(), fields(), constructors()等,以及它们的否定形式。

自定义规则构建

核心概念:谓词与条件

Lang API的核心抽象是DescribedPredicate(谓词)和ArchCondition(条件)。大多数架构规则都可以表示为:

classes that ${PREDICATE} should ${CONDITION}

例如,自定义一个检查带有@Payload注解字段的规则:

DescribedPredicate<JavaClass> haveAFieldAnnotatedWithPayload = ...;
ArchCondition<JavaClass> onlyBeAccessedBySecuredMethods = ...;

classes().that(haveAFieldAnnotatedWithPayload).should(onlyBeAccessedBySecuredMethods);

预定义谓词与条件

ArchUnit提供了大量预定义的谓词和条件,通常位于目标类型的Predicates内部类中。例如:

JavaClass.Predicates.simpleName("Foo")
    .and(JavaClass.Predicates.assignableTo(Serializable.class));

条件也可以组合:

ArchCondition<JavaClass> callEqualsOrHashCode = 
    ArchConditions.callMethod(Object.class, "equals", Object.class)
        .or(ArchConditions.callMethod(Object.class, "hashCode"));

高级特性

自定义概念规则

Lang API不仅限于类和成员,可以通过ClassesTransformer定义任何自定义概念的规则:

ClassesTransformer<BusinessModule> businessModules = ...;
DescribedPredicate<BusinessModule> dealWithOrders = ...;
ArchCondition<BusinessModule> beIndependentOfPayment = ...;

all(businessModules).that(dealWithOrders).should(beIndependentOfPayment);

规则文本控制

可以通过because()方法添加规则说明,或使用as()完全自定义规则文本:

classes().that(...).should(...)
    .because("这是出于安全考虑的重要约束");

违规忽略

对于遗留系统中的已知问题,可以通过archunit_ignore_patterns.txt文件忽略特定违规:

# 忽略LegacyService相关的所有违规
.*some\.pkg\.LegacyService.*

最佳实践

  1. 语义清晰:尽量使规则文本能够准确表达架构意图
  2. 适度抽象:合理使用预定义谓词和条件,避免过度自定义
  3. 文档完善:为复杂规则添加充分的说明
  4. 渐进式验证:对遗留系统使用忽略机制,逐步修复问题

结语

TNG/ArchUnit的Lang API通过高度抽象的DSL,将架构规则从繁琐的实现细节中解放出来,让开发者能够专注于架构意图的表达。掌握这套API不仅能提高开发效率,更能使架构约束成为团队共享的明确规范,而非隐藏在代码中的隐式知识。

ArchUnit A Java architecture test library, to specify and assert architecture rules in plain Java ArchUnit 项目地址: https://gitcode.com/gh_mirrors/ar/ArchUnit

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

葛易曙Linda

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值