软件架构度量实战:从ArchUnit到SonarQube构建质量门禁

发布时间:2026/9/7 10:26:50
软件架构度量实战:从ArchUnit到SonarQube构建质量门禁 软件架构这个领域有一个特别容易被忽略的问题团队每天都写代码、评审代码却很少有人回答一个问题——当前系统的架构到底健不健康耦合是不是在失控、循环依赖是不是越来越多、核心模块是不是已经被改得面目全非。这些问题靠“感觉”没用必须用数据说话。软件架构度量就是一套把架构状态转成数字、指标、门禁的方法论加工具链。这篇文章不是讲某个抽象理论而是直接给出一套可以落地的架构度量方案。我会从指标维度、工具选型、环境搭建、代码示例、CI 集成、质量门禁、性能观察到排查方法完整走一遍。适合正在做系统重构、架构治理、或者想给自己项目建立“架构健康基线”的团队。看完你至少能判断两件事你的项目该量哪些指标怎么把这些指标嵌到日常研发流程里。1. 架构度量能力速览先快速拉一张能力总览方便你对照自己的场景判断该从哪里切入。能力项说明度量对象模块依赖、包依赖、类级别依赖、循环依赖、耦合度、内聚度、复杂度、稳定性核心输出架构健康报告、依赖关系图、违规列表、质量门禁判定结果常用工具ArchUnit、JDepend、NDepend.NET、SonarQube、Structure101、jQAssistant集成方式单元测试断言、Maven/Gradle 插件、静态分析平台、CI/CD 流水线门禁能力依赖方向违规、循环依赖、包数量限制、复杂度阈值、覆盖率红线适用规模从单体应用微服务拆分前的依赖梳理到大型多模块仓库的持续治理落地成本低可以先从 ArchUnit 的 35 条规则开始再接平台化工具协作要求需要架构师定规则、开发同学执行、CI 负责卡点三者分工明确需要说明的是不同工具的启动方式和资源占用差异很大比如 SonarQube 需要跑服务端和分析任务ArchUnit 则直接跑在单测里。下面会分别展开。2. 架构度量的核心指标体系架构度量不是“指标越多越好”而是要抓住几个能揭示系统结构健康度的关键维度。我按大类拆开每个指标都会说清楚“量的是什么”和“用在哪”。2.1 规模类指标规模是最基础的度量但它的价值不是看“代码多不多”而是看“模块大不大、该不该拆”。代码行数LOC看模块规模的绝对值适合发现超大类、超长方法。类数量与接口数量衡量面向对象设计的抽象程度接口过少的系统往往扩展性差。方法数量判断类是否职责过多方法数量超过合理范围的类大概率违反单一职责原则。模块 / 包数量看系统拆分粒度包数量太少说明分层缺失太多则可能是碎片化。规模指标适合做“趋势观察”不要拿来做跨语言、跨团队排名。不同业务复杂度不一样规模数字离了业务上下文没有意义。2.2 耦合类指标耦合是架构治理里最受关注的一类指标因为它直接决定系统能不能低成本演进。扇入Fan-in一个模块被多少个其他模块调用。扇入高说明这个模块被依赖很多修改前需要重点评估影响面。扇出Fan-out一个模块依赖了多少其他模块。扇出过高说明模块自身职责过重或者正在变成“上帝对象”。efferent couplingCE向外依赖数量体现模块对外的耦合程度。afferent couplingCA被外部依赖数量体现模块被复用的程度。依赖深度模块处于依赖链的第几层依赖链越深越容易出现变更传导问题。耦合指标的用途是识别“高危模块”。比如一个底层工具类被几百个类引用改它的 API 就要慎之又慎。2.3 内聚类指标内聚度和耦合正好互补耦合看模块之间的关系内聚看模块内部的紧密程度。LCOMLack of Cohesion of Methods方法之间缺少共享字段的程度。LCOM 越高类内聚越低说明这个类可能把不相关的事放在了一起。LCOM4基于依赖图计算的内聚度能帮助发现“一个类里其实藏着两个类”的情况。职责数量通过类的公开方法和字段数量推算职责越单一越容易维护和测试。LCOM 不是越高越糟糕的绝对值它更适合用来筛出“疑似问题类”再结合代码评审判断是否真的要拆。2.4 复杂度类指标复杂度高的代码不等于有 bug但它一定是修改风险高的代码。圈复杂度Cyclomatic Complexity基于控制流图计算独立路径数。单个方法圈复杂度超过 10 就该考虑拆分超过 20 属于高危区。认知复杂度Cognitive Complexity比圈复杂度更贴合人类阅读习惯它关注嵌套深度、逻辑跳转适合衡量“这段代码难不难懂”。方法长度和参数数量和复杂度配合使用参数超过 5 个的方法容易出问题。复杂度指标最好和代码审查联动新 MR 不能显著拉高项目平均复杂度这条可以直接写进质量门禁。2.5 稳定性与抽象度指标这部分来自 Robert Martin 的面向对象设计度量理论适合用来判断模块处于架构的哪一层。Instability不稳定性I CE / (CA CE)。I 越接近 1模块越不稳定因为它对外依赖很多修改时容易影响别人也容易被别人影响。Abstractness抽象度A 抽象类与接口数量 / 类总数量。A 越接近 1说明模块更多依赖抽象而不是实现。Distance偏离度D |A I - 1|。模块处于“抽象且稳定”或“实现且不稳定”时 D 接近 0如果出现“抽象且不稳定”或“实现且稳定”就说明设计有问题。稳定性和抽象度更适合在模块级、包级计算不要在类级别过度套用。应用后能比较清楚地看出哪些底层包应该稳定却没有抽象。3. 工具选型与对比架构度量的工具很多选型关键是看团队的技术栈和治理目标。下面列出几类有代表性的工具覆盖 Java、.NET 和通用场景。工具语言/平台工作方式适用场景ArchUnitJava / KotlinJUnit 单元测试断言架构规则自动守护依赖方向、包层级、循环依赖检查JDependJava命令行 / Ant / Maven 插件包级依赖质量分析输出 CA、CE、A、I、D 指标SonarQube多语言独立服务端 分析器持续代码质量平台复杂度、重复率、耦合度、质量门禁Structure101Java / C# / C 等独立桌面端/服务架构可视化、依赖图分析、违规修改跟踪jQAssistantJavaNeo4j 图数据库自定义架构查询适合复杂场景的定制化分析NDepend.NETVisual Studio 扩展 命令行.NET 项目的依赖分析、CQLinq 架构规则查询工具没有“最好”只有“最快见效”。我建议分两步走第一步先用 ArchUnit 把规则写进单测里成本最低、见效最快适合没有独立分析平台的情况第二步再上 SonarQube 做平台化的持续度量把指标和门禁展示出来适合多人协作的仓库。NDepend 在 .NET 环境下是依赖分析和架构规则的主流选择不过它需要购买授权采用前要确认团队预算。以下 Demo 我会重点用 ArchUnit、JDepend 和 SonarQube 来说明这些是开源或带有社区版、上手成本相对低的工具。4. 架构度量环境准备与前置条件4.1 环境检查清单进入实操前确认本机环境满足以下条件操作系统Windows 10/11、macOS、主流 Linux 发行版都可以以下命令基本通用。JDKJDK 11 或 17ArchUnit 0.23 以上对 JDK 17 的支持已经比较成熟。构建工具Maven 3.8 或 Gradle 7演示以 Maven 为主。Docker如果需要本地跑 SonarQube 服务端建议准备 Docker 和 docker-compose。端口资源SonarQube 默认占用 9000ArchUnit 不单独占用端口。注意如果你的项目是 JDK 8选 ArchUnit 版本时要找对应支持 JDK 8 的旧版本高版本 ArchUnit 的 class 解析库对 JDK 版本有要求。4.2 准备一个多模块示例工程我用一个 Spring Boot 多模块 Maven 工程来演示结构如下architecture-demo ├── pom.xml ├── application │ ├── src/main/java/com/example/app │ └── pom.xml └── infrastructure ├── src/main/java/com/example/infra └── pom.xml假设我们约定架构分层application层依赖domain层但infrastructure层不能反向依赖application层。这个约定就是后面要用 ArchUnit 守护的规则。模块安排好后在根pom.xml里统一管理依赖版本子模块之间显式声明依赖。这样既方便分析依赖关系也方便出问题时定位模块边界。5. ArchUnit 架构规则接入ArchUnit 的核心思路是“把架构规则写进单测”。规则一旦被违反单测直接失败开发者在提交前就能发现问题而不是等 code review 时被架构师指出。5.1 引入依赖在模块的pom.xml中添加 ArchUnit 测试依赖dependency groupIdcom.tngtech.archunit/groupId artifactIdarchunit-junit5/artifactId version1.2.1/version scopetest/scope /dependency如果项目使用 JUnit 4对应的 artifact 是archunit-junit4。ArchUnit 的 JUnit 5 集成支持AnalyzeClasses注解可以减少样板代码。5.2 第一组规则分层依赖检查创建ArchitectureRuleTest.javapackage com.example.architecture; import com.tngtech.archunit.core.domain.JavaClasses; import com.tngtech.archunit.core.importer.ClassFileImporter; import com.tngtech.archunit.lang.ArchRule; import com.tngtech.archunit.library.Architectures; import org.junit.jupiter.api.Test; import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.*; public class ArchitectureRuleTest { private final JavaClasses classes new ClassFileImporter() .importPackages(com.example); Test void applicationLayerShouldNotDependOnInfrastructureLayer() { ArchRule rule noClasses() .that().resideInAPackage(..application..) .should().dependOnClassesThat() .resideInAPackage(..infrastructure..); rule.check(classes); } Test void infrastructureLayerShouldNotDependOnApplicationLayer() { ArchRule rule noClasses() .that().resideInAPackage(..infrastructure..) .should().dependOnClassesThat() .resideInAPackage(..application..); rule.check(classes); } }上面两条规则检查了分层依赖方向应用层不能跳层依赖基础设施层基础设施层也不能反向依赖应用层。这个案例非常简单但已经能挡住常见的分层混乱。还可以检查包依赖关系比如限制controller包只能被service包依赖Test void controllerPackageShouldOnlyBeAccessedByServicePackage() { ArchRule rule classes() .that().resideInAPackage(..controller..) .should().onlyBeAccessed() .byClassesThat().resideInAPackage(..service..); rule.check(classes); }5.3 循环依赖检查循环依赖是最常见的架构问题之一尤其在多模块工程中。ArchUnit 提供了内置支持package com.example.architecture; import com.tngtech.archunit.core.domain.JavaClasses; import com.tngtech.archunit.core.importer.ClassFileImporter; import com.tngtech.archunit.library.dependencies.SlicesRuleDefinition; import org.junit.jupiter.api.Test; public class CycleRuleTest { private final JavaClasses classes new ClassFileImporter() .importPackages(com.example); Test void noCyclesBetweenSlices() { SlicesRuleDefinition.slices() .matching(com.example.(*)..) .should().beFreeOfCycles() .check(classes); } }matching(com.example.(*)..)表示按照一级子包切分切片然后验证这些切片之间不存在循环依赖。这个测试跑一次就能把整个项目的包循环关系扫干净。5.4 类和通用命名规则架构规则不只管包依赖也管类设计边界。比如禁止使用System.out输出日志、禁止在 controller 层操作HttpSessionTest void noSystemOutUsage() { ArchRule rule noClasses() .should().callMethod(System.class, out); rule.check(classes); } Test void controllersShouldNotAccessHttpSessionDirectly() { ArchRule rule noClasses() .that().resideInAPackage(..controller..) .should().accessClassesThat() .areAssignableTo(javax.servlet.http.HttpSession.class); rule.check(classes); }规则不需要一开始就写几十条。先定最重要的 5 到 10 条比如分层依赖、循环依赖、禁止直接连数据库、禁止 Controller 里写业务逻辑就足够建立一个基本的架构守卫。5.5 运行验证执行单元测试mvn test如果架构规则通过控制台输出类似[INFO] Tests run: 4, Failures: 0, Errors: 0, Skipped: 0如果规则被违反测试会输出具体违规类名、所在包、违反的是哪一条规则。下面我单独用一个小节说明违规场景的验证方法。5.6 故意引入违规场景验证为了确认规则真的是“活”的可以在工程里故意写一个违规类package com.example.application; import com.example.infrastructure.OrderRepository; public class OrderService { private final OrderRepository orderRepository; public OrderService(OrderRepository orderRepository) { this.orderRepository orderRepository; } }如果上面applicationLayerShouldNotDependOnInfrastructureLayer规则生效运行mvn test时就会看到类似错误Architecture Violation [Priority: MEDIUM] - Rule no classes that reside in a package ..application.. should depend on classes that reside in a package ..infrastructure.. was violated: Method com.example.application.OrderService.init(com.example.infrastructure.OrderRepository) calls constructor ...看到这个输出就说明门禁已经生效。此时修复方式是调整依赖方向或重构模块边界而不是删除规则。规则一旦可以被人随意绕过度量就失去意义。6. JDepend 依赖质量分析与指标解读ArchUnit 适合做“规则门禁”JDepend 则更适合产出一份包级别的依赖质量报告。它直接计算 CA、CE、A、I、D 这些指标方便你看到每个包的宏观状态。6.1 运行 JDependJDepend 是命令行工具。下载 jar 包后在项目根目录运行java -jar jdepend-2.9.1.jar -file report/architecture_report.xml target/classes如果希望每次构建时自动生成报告可以配置 Maven 插件plugin groupIdorg.codehaus.mojo/groupId artifactIdjdepend-maven-plugin/artifactId version2.0/version executions execution goals goalgenerate/goal /goals /execution /executions /plugin执行mvn jdepend:generate默认会在target/jdepend-report.xml生成报告。6.2 解读关键指标一份 JDepend 报告会输出每个包的 CA、CE、A、I、D 值。CA高的包说明被大量依赖属于系统的“稳定核心”修改要非常谨慎。CE高的包属于“易受外部影响”对外依赖太多改动成本集中。D值越接近 1说明该包的“抽象程度”和“稳定程度”偏离平衡状态越远。举例来说一个infrastructure实现包如果I接近 1 而A接近 0说明它是一个非常具体且不稳定的实现包这符合分层设计直觉但如果一个domain核心包I也很高就要警惕领域逻辑是不是反向依赖了技术细节。6.3 把 JDepend 指标输出到 Markdown 报告JDepend 的 XML 可以用简单脚本转成 Markdown 表格。下面是一个 Python 脚本示例实际使用时按报告路径和字段调整import xml.etree.ElementTree as ET tree ET.parse(report/architecture_report.xml) root tree.getroot() with open(architecture_report.md, w, encodingutf-8) as f: f.write(| Package | CC | CA | CE | A | I | D |\n) f.write(| --- | --- | --- | --- | --- | --- | --- |\n) for pkg in root.findall(.//Package): name pkg.get(name) stats pkg.find(Stats) if stats is None: continue f.write( f| {name} | {stats.get(CC)} | {stats.get(CA)} | f{stats.get(CE)} | {stats.get(A)} | {stats.get(I)} | f{stats.get(D)} |\n )生成 Markdown 后可以直接作为架构周报的一部分或者放进项目 Wiki。架构度量要形成固定产出报告越容易生成越可能坚持跑下去。7. SonarQube 平台化度量与质量门禁ArchUnit 解决“规则快查”JDepend 解决“依赖指标报告”SonarQube 解决“持续平台化度量”。它把复杂度、重复率、覆盖率、坏味道统一到一张报表里并且可以配置 Quality Gate直接在 CI 里卡住不合格的提交。7.1 本地启动 SonarQube用 Docker Compose 快速拉起一套 SonarQubeversion: 3 services: sonarqube: image: sonarqube:lts-community ports: - 9000:9000 environment: - SONAR_ES_BOOTSTRAP_CHECKS_DISABLEtrue volumes: - sonarqube_data:/opt/sonarqube/data - sonarqube_extensions:/opt/sonarqube/extensions volumes: sonarqube_data: sonarqube_extensions:启动docker-compose up -d启动后访问http://localhost:9000默认账号密码是admin/admin首次登录会要求改密。注意 SonarQube 首次启动需要等待一到两分钟日志里出现SonarQube is up才算就绪。低配置机器上 SonarQube 会比较吃内存官方建议至少有 2GB 可用内存。如果做演示建议给它单独预留资源。7.2 配置 sonar-project.properties在项目根目录新建sonar-project.propertiessonar.projectKeyarchitecture-demo sonar.projectNamearchitecture-demo sonar.projectVersion1.0 sonar.sourcessrc/main/java sonar.testssrc/test/java sonar.java.binariestarget/classes sonar.sourceEncodingUTF-8 sonar.exclusions**/generated/**/*.java字段说明sonar.projectKeySonarQube 中项目的唯一标识。sonar.sources需要分析的源码目录。sonar.java.binaries编译后的 class 目录Java 分析必须配置。sonar.exclusions排除生成的代码避免误报。7.3 执行分析在 Maven 工程中执行mvn clean verify sonar:sonar -Dsonar.host.urlhttp://localhost:9000 \ -Dsonar.loginyour_generated_token也可以使用本地安装的 SonarQube Scannersonar-scanner -Dsonar.host.urlhttp://localhost:9000 -Dsonar.loginyour_token分析完成后打开http://localhost:9000就能看到项目概览页。包括代码行数、圈复杂度、重复率、坏味道数量、覆盖率、安全漏洞等信息。7.4 质量门禁配置SonarQube 的 Quality Gate 是一个“通过/不通过”的判定规则集。你可以在项目的 Quality Gate 中配置新增代码覆盖率低于80%判失败。新增代码圈复杂度高于15判失败。新增坏味道超过0判失败。重复率超过3%判失败。门禁的目的不是“卡死开发”而是让架构环境不继续恶化。建议先观察两周基线再把门禁阈值逐步收紧。7.5 通过 API 获取审批报告SonarQube 提供 REST API方便把指标拉进自己的报表或机器人通知。比如获取项目所有组件指标curl -u admin:your_password \ http://localhost:9000/api/measures/component?componentarchitecture-demometricKeyscomplexity,coverage,duplicated_lines_density返回 JSON 包含各项指标当前值。团队可以把这些指标接到企业微信群、钉钉群实现每日架构健康巡检。API 的详细字段在不同版本略有差异实际调用以你当前版本为准。8. 在 CI/CD 流水线中落地架构度量如果架构度量只在本地跑它很快会变成“只有架构师偶尔看一眼”的摆设。要让它真正发挥作用必须接入 CI 流水线。8.1 GitLab CI 集成示例在项目根目录添加.gitlab-ci.ymlstages: - verify - sonar architecture-tests: stage: verify script: - mvn test only: - merge_requests sonar-analysis: stage: sonar script: - mvn clean verify sonar:sonar -Dsonar.host.urlhttp://sonarqube.example.com -Dsonar.login$SONAR_TOKEN -Dsonar.qualitygate.waittrue only: - main配置要点mvn test阶段会执行 ArchUnit 规则测试。sonar.qualitygate.waittrue会让流水线等待 SonarQube 门禁判定结果而不是“分析完就认为成功”。$SONAR_TOKEN用 CI 变量存放不要明文写死。8.2 Jenkins 流水线示例Jenkinsfile 中把 Maven 测试和 SonarQube 分析串起来pipeline { agent any stages { stage(Build Arquitecture Tests) { steps { sh mvn clean test } } stage(SonarQube Analysis) { steps { withSonarQubeEnv(sonarqube) { sh mvn sonar:sonar } } } } }如果门禁没过可以在流水线里用timeout和waitForQualityGate等待判定结果并失败退出stage(Quality Gate) { steps { timeout(time: 5, unit: MINUTES) { waitForQualityGate abortPipeline: true } } }8.3 门禁判定之后怎么办门禁失败只是“结果”不是“目标”。团队真正要做的是处理门禁暴露的问题规则违规立即修不要“记录下来以后再处理”。如果规则本身不适合业务场景走架构评审流程调整规则而不是绕过门禁。每周从 SonarQube 导出一次趋势数据观察复杂度、重复率是否持续下降。架构度量的最终目标不是跑一个漂亮的报告而是让系统的可维护性可以量化、可以看到新增代码是否在逆向恶化。9. 资源占用与性能观察工具跑起来之后资源占用是最容易被低估的问题。这里给出这套方案的通用观察方法具体数值要按你本机的项目规模来测。9.1 ArchUnit 的资源占用ArchUnit 作为单元测试运行分析速度取决于项目类数量和导入方式。中等规模的单模块项目几百个类通常能在几十秒内完成类特别多的大型仓库建议在 CI 定期任务中运行而不是每次本地开发都全量跑。如果扫描速度过慢可以只导入需要检查的包private final JavaClasses classes new ClassFileImporter() .importPackages(com.example.core, com.example.application);缩小扫描范围后分析耗时显著下降。9.2 SonarQube 的资源占用SonarQube 服务端常见内存占用在 1GB 到 2GB 之间分析任务执行时会再占用几百 MB。所以本地演示时至少预留 3GB 内存会比较安心。分析耗时受项目规模影响明显。第一次全量分析通常是最慢的后续分析可以通过增量扫描加快。若项目非常大可以跳过测试代码分析或只分析变更目录不过这样会牺牲覆盖率指标准确性。9.3 优化关注的三个方向增量分析优先把完整全量分析放在夜间任务MR 阶段只跑“当前变更范围”。限制输出报告JDepend 的 XML 报告在超大项目中会很大建议按顶层包拆分。监控服务端端口SonarQube 默认 9000 端口容易与其他服务冲突启动前先检查端口占用。观察资源占用时用top或系统监视器看 SonarQube Java 进程命令如下top -p $(pgrep -f sonarqube)如果内存持续接近上限可以在docker-compose.yml中限制容器内存避免拖垮开发机。10. 常见问题与排查方法问题现象可能原因排查方式解决方案ArchUnit 测试导入时报 ClassNotFound工程里用了高版本 JDK 或复杂字节码当前 ArchUnit 版本解析失败看测试堆栈确认是哪个包/类加载失败升级 ArchUnit 到匹配 JDK 的版本或排除无关包运行时提示 package 规则不匹配resideInAPackage(..application..)与实际包名不匹配检查包命名路径确认..通配符匹配的是任意前缀根据真实包路径调整匹配表达式JDepend 报告包数量很少指定了错误的 class 目录确认target/classes是否存在是否已经编译先执行mvn compile再跑 JDependSonarQube 启动后 9000 端口不通容器还没就绪或端口被占用查看容器日志确认端口是否被占用换端口或等待启动完成sonar:sonar报 401 Unauthorized使用了过期 token 或账号密码错误检查-Dsonar.login参数重新生成 token在 SonarQube 用户设置中生成新 tokenQuality Gate 一直不显示等待结果没有配置sonar.qualitygate.waittrue查看 CI 日志判断分析是否已提交完成加上-Dsonar.qualitygate.waittrue参数循环依赖测试误报切片粒度太大或太小调整SlicesRuleDefinition.matching()的切分粒度先按单个模块切分再逐步细化复杂度阈值频繁触发阈值定得比项目现状更严先算项目现状的 P90 值再设置阈值以现状为基线逐步收紧不要一步到位排查问题时不要只看错误表象。多数架构度量工具的问题都集中在路径配置、版本兼容、扫描范围三个源头上这三类问题占实际排障的八成以上。11. 架构度量最佳实践11.1 从 5 条规则开始架构治理最大的坑是“一开始就想治理一切”。不要第一周就写 50 条 ArchUnit 规则规则太多会大量误报团队逐渐不信任门禁每修一个违规都要牵动大片代码MR 阻塞严重维护规则本身变成新的成本。建议只写 5 条左右分层依赖方向、禁止循环依赖、禁止 Controller 直接访问数据库仓库、禁止使用System.out、禁止基础设施反向依赖应用层。跑通后再逐步补充。11.2 基线先行、循序渐进在门禁阈值上最好采用“基线原则”先跑一个月度全量报告计算当前坑位。把当前 P90 作为第一版阈值。每两周收紧一次直到达到合理目标。不要第一天就设置“复杂度必须小于 10”这种硬指标除非项目很新、代码量很小。11.3 规则建进评审与 MR 流程架构规则只有在开发提交前触发才有意义。最好的状态是本地mvn test已经把违规卡住CI 流水线再次验证CODE REVIEW 只审查规则没有覆盖到的“真实设计问题”。规则覆盖 80% 的常规问题即可剩下 20% 留给人工评审效率和安全性都能兼顾。11.4 报告要固定输出建议每周生成一份架构度量摘要内容包括新增违规数循环依赖变化平均圈复杂度变化覆盖率变化高危模块清单。哪怕只是一份 Markdown 表格发到群里也比“完全不看”强。没有固定报告流程的度量体系很难撑过三个月。11.5 合规与安全边界架构度量工具会扫描项目全部源码。使用开源工具时先确认许可证与团队合规要求SonarQube 分析数据建议只保留在内部服务器不要上传到不可信的第三方平台。涉及商业闭源代码更要确认工具链的数据留存策略。团队在架构治理过程中可以借助 iOS 或安卓设备进行真机验证但要注意遵守自己组织的设备管理和代码安全规定。这类检查类工具只用于合法的项目质量管理和代码审查。如果团队计划将这些工具作为雇主内部标准流程的一部分还需要与安全合规团队确认确保数据的控制与留存符合公司政策。11.6 从“治理”到“设计”一旦架构度量成为日常工作你会发现团队的关注点从“救火”转向“预防”新模块设计时就会考虑依赖方向、稳定性和抽象度而不是等系统乱了再回头拆。这才是架构度量的真正价值——把架构质量从“事后验证”转成“事中守护”和“事前设计”。12. 总结与下一步架构度量不是一次性任务而是一套可持续的工程实践。最值得从 ArchUnit 的几条分层规则开始因为它代价最低、反馈最快能直接在单测里看到违规。接着用 JDepend 输出包依赖指标再用 SonarQube 建立平台化质量门禁。三件事的先后顺序就是一条非常务实的落地路径。最容易踩的坑是三个一是阈值定得太硬导致团队反感二是规则写太多导致误报成灾三是报告只停在本地没有进入 CI 流程。先避开这三个坑架构度量就能真正跑起来。如果看完本文想立刻动手建议先挑目录里的两个包写一条“禁止反向依赖”规则跑一次mvn test感受一下架构守卫的实际效果再决定要不要把这套方案推广到整个项目仓库。