架构约束检查是什么
把架构图上的依赖方向变成可执行的断言:分层之间只允许单向依赖、禁止循环依赖、模块边界外不可访问内部实现。dependency-cruiser 面向 JS/TS,ArchUnit 面向 JVM,import-linter 面向 Python。它们把架构决策从文档搬进 CI,让违规在合并前就被拦下。
基本信息
| 检查目标 | 分层依赖方向 / 循环依赖 / 模块边界 / 命名与注解约束 |
|---|---|
| 常用工具 | dependency-cruiser、ArchUnit、import-linter |
| 执行时机 | CI 与本地并行执行,违规即失败 |
| 规则来源 | 架构决策记录(ADR)中的图形约定 |
值得固化的检查项
- 分层方向:api 只能依赖 service,service 只能依赖 repository
- 禁止循环依赖:任意两个模块之间不得互相引用
- 边界封闭:模块的外部接口之外不得访问内部包
- 禁止特定依赖:领域层不得直接引用 Web 框架或 ORM 类型
- 命名与放置约束:持久化实现必须落在指定包下
- 公共出口唯一:跨模块引用必须走约定入口,禁止深入内部路径
示例(import-linter)
示例(import-linter)
[importlinter]
root_package = myapp
[importlinter:contract:layers]
name = layered
# 上层只可依赖下层,反之禁止
type = layers
layers =
api
service
repository
[importlinter:contract:no-cycles]
name = no-cycles
type = forbidden
source_modules =
myapp.service
forbidden_modules =
myapp.api工具对照
| 工具 | 生态 | 特点 |
|---|---|---|
| dependency-cruiser | JS / TS | 按规则校验依赖,可输出图与违规清单 |
| ArchUnit | JVM(Java、Kotlin) | JUnit 风格断言,可在测试里跑架构规则 |
| import-linter | Python | 契约式配置,分层与禁止依赖两类规则常用 |
规则从 ADR 来:先写下「哪些依赖方向是允许的、为什么」,再翻译成断言。这样违规报告能对上当初的决策,评审有客观依据,也避免规则本身随时间失去解释力。
工具 API 会演进:ArchUnit 1.0 起分层规则的入口方法已迁到 Architectures 下,旧写法需要迁移。升级依赖时把架构规则当成测试一起跑一遍,比事后逐个修违规更省事。