ArchUnit 導入指引

導入效應

效應 說明
架構漂移防護 在 CI 中即時攔截 AI 或人類違反分層規則的程式碼,避免技術債累積
DDD Boundary 強制 確保 Domain Layer 不被 Infra 或 API Layer 直接存取
AI 產碼守門 AI 極易亂引 package,ArchUnit 可在 merge 前直接擋掉
可讀的架構文件 規則本身就是架構文件,新人一看就懂團隊的架構約束
零 Runtime 成本 測試期才跑,不影響 Production 效能

1. Maven 導入

<dependency>
    <groupId>com.tngtech.archunit</groupId>
    <artifactId>archunit-junit5</artifactId>
    <version>1.3.0</version>
    <scope>test</scope>
</dependency>

2. Gradle 導入

testImplementation 'com.tngtech.archunit:archunit-junit5:1.3.0'

3. 基本規則範例

3.1 分層規則(Layered Architecture)

@AnalyzeClasses(packages = "com.example")
public class LayeredArchitectureTest {

    @ArchTest
    static final ArchRule layered_architecture = layeredArchitecture()
        .consideringAllDependencies()
        .layer("Controller").definedBy("..controller..")
        .layer("Service").definedBy("..service..")
        .layer("Repository").definedBy("..repository..")
        .whereLayer("Controller").mayNotAccessAnyLayer()
        .whereLayer("Service").mayOnlyAccessLayers("Repository")
        .whereLayer("Repository").mayNotAccessAnyLayer();
}

3.2 禁止跨模組依賴

@ArchTest
static final ArchRule no_cycle_dependencies = slices()
    .matching("com.example.(*)..")
    .should().beFreeOfCycles();

3.3 DDD Boundary 驗證

@ArchTest
static final ArchRule domain_isolation = noClasses()
    .that().resideInAPackage("..domain..")
    .should().dependOnClassesThat()
    .resideInAPackage("..infrastructure..");

3.4 Hexagonal Architecture

@ArchTest
static final ArchRule hexagonal_ports_and_adapters = slices()
    .matching("com.example.hexagonal.(*)..")
    .should().notDependOnEachOther();

3.5 Controller 僅允許被 API package 存取

@ArchTest
static final ArchRule controllers_only_by_api = classes()
    .that().resideInAPackage("..controller..")
    .should().onlyBeAccessed()
    .byAnyPackage("..api..", "..controller..");

4. AI Guardrails 整合

4.1 在 CI Pipeline 加入 ArchUnit

# azure-pipelines.yml
- stage: ArchitectureCheck
  jobs:
    - job: ArchUnit
      steps:
        - task: Maven@4
          inputs:
            goals: 'test'
            options: '-Dtest=*ArchitectureTest'
            publishJUnitResults: true

4.2 AI PR 自動驗證

Developer
  ↓
Claude Code / Copilot 產生程式碼
  ↓
git push
  ↓
ArchUnit Rules (CI Stage 1)
  ↓ ✅ PASS → Stage 2 (Semgrep / SonarQube)
  ↓ ❌ FAIL → PR blocked, 要求修正

5. 常見 AI 違規場景

AI 違規行為 ArchUnit 攔截規則
Controller 直接呼叫 Repository Layered Architecture Rule
Domain 依賴 Infra Domain Isolation Rule
Service 互相呼叫造成循環 Cycle Detection Rule
新增跨模組 package 引用 No Incoming Dependencies Rule

6. Best Practices

  • 規則放在 src/test/java 對應 package 下
  • 每個 module 建立獨立的 ArchitectureTest.java
  • 規則命名用 should 開頭,讓錯誤訊息可讀
  • 定期 review 規則是否需要更新(架構演進時)
  • 將規則納入 PR template 的 checklist

7. 參考資源