架构设计不是凭空想象,而是需要工具辅助的系统性工程。从最初的白板画图到如今的代码化架构描述(Architecture as Code),架构师手中的工具箱经历了深刻的变革。一个成熟的架构团队,至少需要在三个维度上配备趁手的工具:建模与描述——将头脑中的架构意图精确表达出来;可视化与沟通——让不同角色的干系人都能理解架构决策;决策辅助与治理——用自动化手段守护架构规则,防止架构腐化(Architecture Erosion)。
本文将围绕架构师日常工作中最常用的工具展开,重点介绍 C4 模型(C4 Model)与 Structurizr 的代码化架构描述方式,依赖分析工具 Lattix 和 Sonargraph 的使用场景,架构决策记录(Architecture Decision Records,ADR)的落地实践,以及架构适应度函数(Architecture Fitness Functions)与 ArchUnit 等工具的配合。最终,我们会通过一个完整的工程案例,演示如何将这些工具组合成一套可持续运转的架构治理流水线。
一、架构师为什么需要专门的工具
很多团队习惯用 PPT 或 Confluence 页面画几张架构图就算完事。这种做法在项目初期问题不大,但随着系统规模增长,会暴露出严重的问题:
- 图与代码脱节——架构图画完之后很少更新,半年后就变成了过时的文档,新人看了反而被误导。
- 粒度不统一——同一张图里既有系统级的交互,又有类级别的细节,读者不知道该关注什么。
- 缺少版本控制——架构图通常以二进制格式存储,无法像代码一样做 diff、review 和 merge。
- 治理无抓手——架构规则停留在口头约定,没有自动化检查,违反规则的代码照样合并。
- 决策记录缺失——当初为什么选了 Kafka 而不是 RabbitMQ?三个月后没人能说清楚。
为了解决这些痛点,业界逐步发展出一整套架构工具生态。我们可以将其划分为以下几个类别:
| 类别 | 典型工具 | 核心价值 |
|---|---|---|
| 架构建模与描述 | Structurizr、PlantUML、Mermaid | 用代码描述架构,纳入版本控制 |
| 依赖分析 | Lattix、Sonargraph、JDepend | 自动提取代码依赖,检测违规 |
| 架构决策记录 | ADR Tools、Log4brains | 结构化记录架构决策及其上下文 |
| 架构守护 | ArchUnit、Fitness Functions、NetArchTest | 通过自动化测试守护架构规则 |
| 架构可视化 | D2、Graphviz、Excalidraw | 生成和渲染架构图 |
| 全景观察 | Backstage、Port、Compass | 服务目录与技术雷达 |
下面我们逐一深入。
二、C4 模型:分层描述架构的标准方法
C4 模型(C4 Model)由 Simon Brown 提出,是目前最广泛使用的软件架构可视化方法之一。它的核心思想非常简单:用四个层次、逐步放大(Zoom In)的方式来描述一个软件系统。
2.1 四个层次
C4 代表四个层次的缩写:
- Context(上下文)——展示系统与外部用户、外部系统之间的关系,回答「系统在更大环境中的位置是什么」。
- Container(容器)——展示系统内部的高层技术构建块(Web 应用、数据库、消息队列等),回答「系统由哪些技术组件组成」。
- Component(组件)——展示单个容器内部的逻辑组件(控制器、服务、仓储等),回答「容器内部是怎么组织的」。
- Code(代码)——展示组件内部的类、接口等代码级细节,通常由 IDE 自动生成,回答「代码结构是什么样的」。
graph TD
A["Level 1: System Context<br/>系统上下文"] --> B["Level 2: Container<br/>容器"]
B --> C["Level 3: Component<br/>组件"]
C --> D["Level 4: Code<br/>代码"]
style A fill:#1168bd,stroke:#0b4884,color:#ffffff
style B fill:#438dd5,stroke:#2e6295,color:#ffffff
style C fill:#85bbf0,stroke:#5d82a8,color:#000000
style D fill:#d4e6f1,stroke:#85929e,color:#000000
2.2 C4 模型的关键原则
C4 模型有几个值得注意的设计原则:
- 每一层只关注一个抽象级别——不要在同一张图里混合不同粒度的元素。
- 图的数量取决于需要——不是每个系统都需要画到第四层,大多数情况下前三层就够了。
- 图是有受众的——Context 图给业务干系人看,Container 图给技术负责人看,Component 图给开发人员看。
- 补充图(Supplementary Diagrams)——C4 模型允许在四层之外使用部署图(Deployment Diagram)、动态图(Dynamic Diagram)等补充视图。
2.3 C4 与其他方法的对比
| 特性 | C4 模型 | UML | 4+1 视图模型 | ArchiMate |
|---|---|---|---|---|
| 学习成本 | 低 | 高 | 中 | 高 |
| 适用场景 | 软件架构沟通 | 详细设计 | 全面架构文档 | 企业架构 |
| 工具依赖 | 弱 | 强 | 中 | 强 |
| 代码化支持 | Structurizr DSL | PlantUML 等 | 无标准工具 | Archi 等 |
| 社区活跃度 | 高 | 中(下降趋势) | 低 | 中 |
| 与敏捷兼容 | 好 | 一般 | 一般 | 一般 |
C4 模型最大的优势在于「刚好够用」——它不像 UML 那样定义了十几种图类型和上百种符号,也不像随手画图那样缺乏统一规范。
三、Structurizr:代码化架构描述的利器
Structurizr 是 C4 模型的官方工具实现,由 Simon Brown 本人创建。它最大的特点是支持用 DSL(Domain Specific Language,领域特定语言)来描述架构,然后自动生成 C4 各层次的图。
3.1 Structurizr DSL 基础语法
下面是一个典型的电商系统的 Structurizr DSL 描述:
workspace "电商平台" "电商平台架构描述" {
model {
// 外部用户
customer = person "顾客" "通过浏览器或手机 App 下单购物"
admin = person "运营管理员" "管理商品、订单和促销活动"
// 外部系统
paymentGateway = softwareSystem "支付网关" "第三方支付服务(支付宝/微信支付)" "External"
logisticsSystem = softwareSystem "物流系统" "第三方物流追踪服务" "External"
// 核心系统
ecommerce = softwareSystem "电商平台" "提供在线购物、订单管理、库存管理等功能" {
// 容器层
webApp = container "Web 前端" "提供购物界面" "React + TypeScript" "WebBrowser"
mobileApp = container "移动端 App" "iOS/Android 购物应用" "Flutter" "MobileApp"
apiGateway = container "API 网关" "统一入口,路由与限流" "Kong"
orderService = container "订单服务" "处理订单创建、支付、取消" "Java + Spring Boot"
productService = container "商品服务" "商品信息管理与搜索" "Java + Spring Boot"
inventoryService = container "库存服务" "库存扣减与查询" "Go"
userService = container "用户服务" "用户注册、登录、权限" "Java + Spring Boot"
notificationService = container "通知服务" "短信、邮件、站内信推送" "Python + Celery"
orderDb = container "订单数据库" "存储订单数据" "PostgreSQL" "Database"
productDb = container "商品数据库" "存储商品数据" "MySQL" "Database"
inventoryDb = container "库存数据库" "存储库存数据" "Redis + MySQL" "Database"
userDb = container "用户数据库" "存储用户数据" "PostgreSQL" "Database"
messageQueue = container "消息队列" "异步事件传递" "Apache Kafka" "Queue"
cache = container "缓存" "热点数据缓存" "Redis" "Cache"
}
// 关系定义
customer -> webApp "浏览商品、下单" "HTTPS"
customer -> mobileApp "浏览商品、下单" "HTTPS"
admin -> webApp "管理后台操作" "HTTPS"
webApp -> apiGateway "调用 API" "HTTPS/JSON"
mobileApp -> apiGateway "调用 API" "HTTPS/JSON"
apiGateway -> orderService "转发请求" "gRPC"
apiGateway -> productService "转发请求" "gRPC"
apiGateway -> userService "转发请求" "gRPC"
orderService -> orderDb "读写订单" "JDBC"
orderService -> inventoryService "扣减库存" "gRPC"
orderService -> messageQueue "发布订单事件" "Kafka Protocol"
orderService -> paymentGateway "发起支付" "HTTPS"
productService -> productDb "读写商品" "JDBC"
productService -> cache "缓存商品信息" "Redis Protocol"
inventoryService -> inventoryDb "读写库存" "Redis Protocol + JDBC"
userService -> userDb "读写用户" "JDBC"
notificationService -> messageQueue "消费订单事件" "Kafka Protocol"
notificationService -> customer "发送通知" "SMS/Email"
ecommerce -> logisticsSystem "查询物流状态" "HTTPS"
}
views {
systemContext ecommerce "SystemContext" {
include *
autoLayout
}
container ecommerce "Containers" {
include *
autoLayout
}
styles {
element "Software System" {
background #1168bd
color #ffffff
}
element "External" {
background #999999
color #ffffff
}
element "Person" {
shape Person
background #08427b
color #ffffff
}
element "Database" {
shape Cylinder
}
element "Queue" {
shape Pipe
}
element "WebBrowser" {
shape WebBrowser
}
element "MobileApp" {
shape MobileDeviceLandscape
}
}
}
}
3.2 Structurizr 的部署方式
Structurizr 提供多种部署方式:
# 方式一:使用 Structurizr Lite(本地 Docker 部署)
docker pull structurizr/lite
docker run -it --rm -p 8080:8080 \
-v $(pwd)/workspace:/usr/local/structurizr \
structurizr/lite
# 方式二:使用 Structurizr CLI 导出为静态图片
# 安装 CLI
curl -L https://github.com/structurizr/cli/releases/download/v2024.03.03/structurizr-cli.zip \
-o structurizr-cli.zip
unzip structurizr-cli.zip -d structurizr-cli
# 导出为 PlantUML 格式
./structurizr-cli/structurizr.sh export \
-workspace workspace.dsl \
-format plantuml/structurizr
# 导出为 Mermaid 格式
./structurizr-cli/structurizr.sh export \
-workspace workspace.dsl \
-format mermaid
# 导出为 JSON 格式(供其他工具消费)
./structurizr-cli/structurizr.sh export \
-workspace workspace.dsl \
-format json3.3 将 Structurizr DSL 纳入 CI/CD
架构描述文件应当像代码一样被管理:
# .github/workflows/architecture.yml
name: Architecture Diagrams
on:
push:
paths:
- 'docs/architecture/**'
pull_request:
paths:
- 'docs/architecture/**'
jobs:
validate-and-export:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Validate Structurizr DSL
run: |
docker run --rm \
-v ${{ github.workspace }}/docs/architecture:/usr/local/structurizr \
structurizr/cli \
validate -workspace /usr/local/structurizr/workspace.dsl
- name: Export diagrams
run: |
docker run --rm \
-v ${{ github.workspace }}/docs/architecture:/usr/local/structurizr \
structurizr/cli \
export -workspace /usr/local/structurizr/workspace.dsl \
-format plantuml/structurizr \
-output /usr/local/structurizr/diagrams
- name: Upload diagrams
uses: actions/upload-artifact@v4
with:
name: architecture-diagrams
path: docs/architecture/diagrams/这样,每次架构描述文件变更时,CI 流水线会自动校验语法并生成最新的架构图,确保图与描述始终一致。
四、架构决策记录(ADR)
架构决策记录(Architecture Decision Records,ADR)是一种轻量级的文档实践,用于记录重要的架构决策、决策的上下文以及决策的后果。
4.1 ADR 的标准格式
每条 ADR 是一个独立的 Markdown 文件,通常包含以下字段:
# ADR-0012: 选择 Apache Kafka 作为事件总线
## 状态
已接受(Accepted)
## 上下文
我们的电商平台需要一个事件驱动的消息中间件,用于在微服务之间传递领域事件
(如订单创建、库存变更、支付回调等)。当前候选方案有三个:
- Apache Kafka
- RabbitMQ
- Amazon SQS/SNS
关键需求:
1. 日均消息量预计 5000 万条以上
2. 需要支持消息回溯(Consumer 可以重新消费历史消息)
3. 需要支持消息的分区有序
4. 团队中有两位工程师有 Kafka 运维经验
## 决策
选择 Apache Kafka 作为事件总线。
## 理由
1. Kafka 天然支持消息持久化和回溯(基于 offset),RabbitMQ 和 SQS 不支持。
2. Kafka 的分区(Partition)机制可以保证同一分区内的消息有序,满足订单状态
变更的顺序性要求。
3. Kafka 在高吞吐场景下的性能远优于 RabbitMQ。
4. 团队已有 Kafka 运维经验,降低了学习成本和运维风险。
## 后果
- 需要部署和维护 Kafka 集群(或使用托管服务如 Confluent Cloud)。
- 需要引入 Schema Registry 来管理事件的 Avro/Protobuf 模式。
- 对于简单的请求-响应模式,Kafka 并非最优选择,需要配合 gRPC 使用。
- RabbitMQ 适合的延迟队列场景需要单独解决(考虑 Kafka 的延迟消息插件
或独立部署一个轻量级 RabbitMQ 实例)。
## 参与者
- 张三(架构师)
- 李四(后端负责人)
- 王五(基础设施负责人)
## 日期
2026-03-154.2 ADR 工具链
业界有多个工具可以辅助管理 ADR:
# 安装 adr-tools
brew install adr-tools
# 初始化 ADR 目录
adr init docs/adr
# 创建新的 ADR
adr new "选择 Apache Kafka 作为事件总线"
# 生成文件:docs/adr/0012-选择-apache-kafka-作为事件总线.md
# 查看 ADR 列表
adr list
# 生成 ADR 目录页
adr generate toc > docs/adr/README.md
# 将某条 ADR 标记为被取代
adr new -s 0012 "迁移到 Amazon MSK 托管 Kafka"使用 Log4brains 可以获得更好的浏览体验:
# 安装 Log4brains
npm install -g log4brains
# 初始化
log4brains init
# 创建新的 ADR
log4brains adr new "选择 Apache Kafka 作为事件总线"
# 启动本地预览服务器
log4brains preview
# 构建静态站点
log4brains build4.3 ADR 的最佳实践
- 每个重要决策一条 ADR——不要把多个决策合并到一条里。
- 不可变性——ADR 一旦接受,不应该修改其内容,如果决策被推翻,应该创建新的 ADR 并标记旧的为「已取代(Superseded)」。
- 纳入代码仓库——ADR 文件应该与代码放在同一个仓库中,随代码一起版本控制。
- 代码评审中引用 ADR——当 PR 涉及架构变更时,应在 PR 描述中引用相关的 ADR。
- 定期回顾——每个季度回顾一次现有的 ADR,检查是否有需要更新或取代的决策。
flowchart LR
A["识别架构决策点"] --> B["撰写 ADR 草稿"]
B --> C["团队评审"]
C --> D{"达成共识?"}
D -->|是| E["标记为 Accepted"]
D -->|否| F["修改或放弃"]
F --> C
E --> G["纳入代码仓库"]
G --> H["定期回顾"]
H --> I{"需要变更?"}
I -->|是| J["创建新 ADR<br/>取代旧 ADR"]
I -->|否| H
J --> C
style A fill:#2ecc71,stroke:#27ae60,color:#ffffff
style E fill:#3498db,stroke:#2980b9,color:#ffffff
style J fill:#e74c3c,stroke:#c0392b,color:#ffffff
五、依赖分析工具:Lattix 与 Sonargraph
当系统规模增长到数十个模块、数百个包时,仅靠人工审查代码来理解依赖关系已经不现实了。依赖分析工具可以自动提取代码中的依赖关系,并以矩阵或图的形式展示,帮助架构师发现违反分层规则的依赖、循环依赖等问题。
5.1 依赖结构矩阵(DSM)
依赖结构矩阵(Dependency Structure Matrix,DSM)是一种紧凑的依赖可视化方式。与传统的依赖图相比,DSM 在模块数量较多时仍然可读。
DSM 的基本原理: - 矩阵的行和列都是模块(包、类、服务)。 - 如果模块 A 依赖模块 B,则在 A 行 B 列的交叉处标记依赖数量。 - 理想的分层架构在 DSM 中表现为下三角矩阵(即上层只依赖下层)。 - 上三角出现的依赖说明存在反向依赖,需要重点关注。
5.2 Lattix 的使用
Lattix 是一款商业级的架构分析工具,支持 Java、C/C++、.NET 等多种语言。
Lattix 的核心功能: 1. 自动提取依赖——从编译产物或源代码中提取模块间的依赖关系。 2. DSM 可视化——以矩阵形式展示依赖关系。 3. 规则定义——架构师可以定义「允许的依赖」和「禁止的依赖」。 4. 违规检测——自动检测违反架构规则的依赖。 5. CI 集成——可以在构建流水线中运行检查。
# Lattix CLI 示例:分析 Java 项目
lattix-cli analyze \
--project ecommerce-platform \
--source ./src/main/java \
--classpath ./target/classes \
--output ./reports/dsm.html
# 检查架构规则违规
lattix-cli check \
--project ecommerce-platform \
--rules ./architecture-rules.lattix \
--fail-on-violation5.3 Sonargraph 的使用
Sonargraph 是另一款强大的架构分析工具,特别擅长检测循环依赖。它提供了一种基于脚本的规则定义方式:
// sonargraph-rules.groovy
// 定义分层架构规则
artifact("Application") {
// 表示层只能依赖业务逻辑层
layer("Presentation") {
include "**/controller/**"
include "**/web/**"
}
// 业务逻辑层只能依赖数据访问层和领域层
layer("Business") {
include "**/service/**"
include "**/usecase/**"
}
// 领域层不依赖任何其他层
layer("Domain") {
include "**/domain/**"
include "**/model/**"
}
// 数据访问层只能依赖领域层
layer("Persistence") {
include "**/repository/**"
include "**/dao/**"
}
// 定义层级依赖规则
"Presentation" -> "Business"
"Business" -> "Domain"
"Business" -> "Persistence"
"Persistence" -> "Domain"
// 禁止反向依赖
deny "Domain" -> "Persistence"
deny "Domain" -> "Business"
deny "Domain" -> "Presentation"
deny "Persistence" -> "Business"
deny "Persistence" -> "Presentation"
deny "Business" -> "Presentation"
}5.4 开源替代方案
对于预算有限的团队,也有不少开源的依赖分析工具可供选择:
| 工具 | 语言支持 | 核心功能 | 许可证 |
|---|---|---|---|
| JDepend | Java | 包级别依赖分析与度量 | BSD |
| Degraph | Java/Scala | 依赖图可视化与约束检查 | Apache 2.0 |
| deptry | Python | Python 依赖检查 | MIT |
| Madge | JavaScript/TypeScript | 模块依赖图可视化 | MIT |
| dependency-cruiser | JavaScript/TypeScript | 依赖规则验证 | MIT |
| go-arch-lint | Go | Go 项目架构约束检查 | MIT |
以 dependency-cruiser 为例:
# 安装
npm install --save-dev dependency-cruiser
# 初始化配置
npx depcruise --init
# 运行依赖分析
npx depcruise --config .dependency-cruiser.cjs src
# 生成依赖图(SVG 格式)
npx depcruise --config .dependency-cruiser.cjs \
--output-type dot src | dot -T svg > dependency-graph.svg
# 生成 Mermaid 格式的依赖图
npx depcruise --config .dependency-cruiser.cjs \
--output-type mermaid src > dependency-graph.mmddependency-cruiser 的规则配置:
// .dependency-cruiser.cjs
module.exports = {
forbidden: [
{
name: "no-circular",
severity: "error",
comment: "禁止循环依赖",
from: {},
to: {
circular: true,
},
},
{
name: "no-orphans",
severity: "warn",
comment: "检测孤立模块",
from: {
orphan: true,
pathNot: [
"(^|/)\\.[^/]+\\.(js|cjs|mjs|ts)$",
"\\.d\\.ts$",
"(^|/)tsconfig\\.json$",
],
},
to: {},
},
{
name: "controller-not-to-repository",
severity: "error",
comment: "Controller 层不能直接访问 Repository 层",
from: {
path: "^src/controller/",
},
to: {
path: "^src/repository/",
},
},
{
name: "domain-not-to-infrastructure",
severity: "error",
comment: "领域层不能依赖基础设施层",
from: {
path: "^src/domain/",
},
to: {
path: "^src/infrastructure/",
},
},
],
options: {
doNotFollow: {
path: "node_modules",
},
tsPreCompilationDeps: true,
tsConfig: {
fileName: "tsconfig.json",
},
enhancedResolveOptions: {
exportsFields: ["exports"],
conditionNames: ["import", "require", "node", "default"],
},
},
};六、架构适应度函数与 ArchUnit
架构适应度函数(Architecture Fitness Functions)是《演进式架构》(Building Evolutionary Architectures)一书中提出的概念。其核心思想是:用可自动执行的测试来守护架构特性。
6.1 什么是适应度函数
适应度函数借鉴了遗传算法中的概念——每个架构特性(如性能、安全性、模块化)都有对应的「适应度函数」来衡量系统在这个维度上的表现。当适应度函数的值低于阈值时,说明架构在该维度上发生了退化。
适应度函数的分类:
- 原子适应度函数(Atomic)——只衡量单一维度,如「循环依赖数量为零」。
- 整体适应度函数(Holistic)——衡量多个维度的综合表现,如「在负载测试中,P99 延迟低于 200ms 且错误率低于 0.1%」。
- 触发式适应度函数(Triggered)——由特定事件触发执行,如每次代码合并时运行。
- 持续式适应度函数(Continuous)——持续运行并监控,如生产环境的可用性监控。
6.2 ArchUnit:Java 生态的架构守护神
ArchUnit 是 Java 生态中最流行的架构测试框架,它允许开发者用 Java 代码编写架构规则,并以单元测试的形式执行。
// ArchitectureTest.java
package com.ecommerce.architecture;
import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.core.importer.ImportOption;
import com.tngtech.archunit.lang.ArchRule;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.*;
import static com.tngtech.archunit.library.Architectures.layeredArchitecture;
import static com.tngtech.archunit.library.dependencies.SlicesRuleDefinition.slices;
class ArchitectureTest {
private static JavaClasses classes;
@BeforeAll
static void setup() {
classes = new ClassFileImporter()
.withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS)
.importPackages("com.ecommerce");
}
@Test
void 分层架构规则() {
ArchRule rule = layeredArchitecture()
.consideringAllDependencies()
.layer("Controller").definedBy("..controller..")
.layer("Service").definedBy("..service..")
.layer("Domain").definedBy("..domain..")
.layer("Repository").definedBy("..repository..")
.layer("Infrastructure").definedBy("..infrastructure..")
.whereLayer("Controller").mayNotBeAccessedByAnyLayer()
.whereLayer("Controller").mayOnlyAccessLayers("Service", "Domain")
.whereLayer("Service").mayOnlyAccessLayers("Domain", "Repository")
.whereLayer("Repository").mayOnlyAccessLayers("Domain", "Infrastructure")
.whereLayer("Domain").mayOnlyAccessLayers(); // 领域层不依赖任何层
rule.check(classes);
}
@Test
void 禁止循环依赖() {
ArchRule rule = slices()
.matching("com.ecommerce.(*)..")
.should().beFreeOfCycles();
rule.check(classes);
}
@Test
void Controller类必须以Controller结尾() {
ArchRule rule = classes()
.that().resideInAPackage("..controller..")
.should().haveSimpleNameEndingWith("Controller");
rule.check(classes);
}
@Test
void Service类不能直接使用JPA的EntityManager() {
ArchRule rule = noClasses()
.that().resideInAPackage("..service..")
.should().accessClassesThat()
.haveFullyQualifiedName("jakarta.persistence.EntityManager");
rule.check(classes);
}
@Test
void 领域对象不能使用Spring注解() {
ArchRule rule = noClasses()
.that().resideInAPackage("..domain..")
.should().beAnnotatedWith("org.springframework.stereotype.Service")
.orShould().beAnnotatedWith("org.springframework.stereotype.Component")
.orShould().beAnnotatedWith("org.springframework.stereotype.Repository");
rule.check(classes);
}
@Test
void Repository接口必须在repository包中() {
ArchRule rule = classes()
.that().haveSimpleNameEndingWith("Repository")
.should().resideInAPackage("..repository..");
rule.check(classes);
}
}6.3 .NET 生态:NetArchTest
对于 .NET 项目,NetArchTest 提供了类似 ArchUnit 的能力:
// ArchitectureTests.cs
using NetArchTest.Rules;
using Xunit;
namespace ECommerce.Tests.Architecture
{
public class ArchitectureTests
{
[Fact]
public void Domain层不能依赖Infrastructure层()
{
var result = Types.InAssembly(typeof(Domain.Order).Assembly)
.ShouldNot()
.HaveDependencyOn("ECommerce.Infrastructure")
.GetResult();
Assert.True(result.IsSuccessful,
$"领域层违规依赖了基础设施层:{string.Join(", ",
result.FailingTypeNames ?? Array.Empty<string>())}");
}
[Fact]
public void Controller必须以Controller结尾()
{
var result = Types.InAssembly(typeof(API.Startup).Assembly)
.That()
.ResideInNamespace("ECommerce.API.Controllers")
.Should()
.HaveNameEndingWith("Controller")
.GetResult();
Assert.True(result.IsSuccessful);
}
}
}6.4 适应度函数的分层体系
在实际工程中,我们可以将适应度函数按检查频率和范围分为多个层次:
| 层次 | 检查频率 | 示例 | 工具 |
|---|---|---|---|
| 代码提交级 | 每次 commit | 分层依赖规则、命名规范 | ArchUnit、ESLint |
| 构建级 | 每次 CI 构建 | 循环依赖检测、代码覆盖率 | Sonargraph、JaCoCo |
| 部署级 | 每次部署 | 契约测试、API 兼容性 | Pact、OpenAPI diff |
| 运行时级 | 持续监控 | P99 延迟、错误率、可用性 | Prometheus、Datadog |
| 周期性 | 每周/每月 | 技术债务评估、安全扫描 | SonarQube、Snyk |
七、架构可视化的自动化
手动绘制架构图的最大问题是维护成本高。理想的做法是:从代码或运行时数据自动生成架构图。
7.1 静态分析生成架构图
从代码静态分析生成架构图的流程:
flowchart TB
subgraph "源代码"
A["Java/TypeScript/Go<br/>源代码"]
B["依赖配置<br/>pom.xml / package.json"]
C["基础设施即代码<br/>Terraform / K8s YAML"]
end
subgraph "分析引擎"
D["AST 解析器"]
E["依赖解析器"]
F["IaC 解析器"]
end
subgraph "中间表示"
G["依赖图<br/>(JSON/GraphML)"]
end
subgraph "可视化输出"
H["Mermaid 图"]
I["PlantUML 图"]
J["D2 图"]
K["交互式 Web 图"]
end
A --> D
B --> E
C --> F
D --> G
E --> G
F --> G
G --> H
G --> I
G --> J
G --> K
style G fill:#f39c12,stroke:#e67e22,color:#ffffff
7.2 使用 PlantUML 生成 C4 图
PlantUML 有一套专门的 C4 扩展库:
@startuml
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml
title 电商平台 - 容器图
Person(customer, "顾客", "通过浏览器或手机下单购物")
Person(admin, "运营管理员", "管理商品和订单")
System_Boundary(ecommerce, "电商平台") {
Container(webApp, "Web 前端", "React", "购物界面")
Container(apiGateway, "API 网关", "Kong", "路由与限流")
Container(orderService, "订单服务", "Spring Boot", "订单生命周期管理")
Container(productService, "商品服务", "Spring Boot", "商品信息管理")
Container(inventoryService, "库存服务", "Go", "库存扣减")
ContainerDb(orderDb, "订单数据库", "PostgreSQL", "订单数据")
ContainerDb(productDb, "商品数据库", "MySQL", "商品数据")
ContainerQueue(mq, "消息队列", "Kafka", "异步事件")
}
System_Ext(payment, "支付网关", "支付宝/微信支付")
Rel(customer, webApp, "浏览和下单", "HTTPS")
Rel(admin, webApp, "管理操作", "HTTPS")
Rel(webApp, apiGateway, "API 调用", "HTTPS")
Rel(apiGateway, orderService, "转发", "gRPC")
Rel(apiGateway, productService, "转发", "gRPC")
Rel(orderService, orderDb, "读写", "JDBC")
Rel(orderService, inventoryService, "扣减库存", "gRPC")
Rel(orderService, mq, "发布事件", "Kafka")
Rel(orderService, payment, "发起支付", "HTTPS")
Rel(productService, productDb, "读写", "JDBC")
@enduml
7.3 使用 D2 语言
D2 是一种较新的声明式图表语言,语法更为简洁:
# 电商平台容器图
direction: right
顾客 -> 电商平台.Web前端: 浏览下单 {
style.stroke: "#2ecc71"
}
电商平台: {
Web前端: React {
shape: rectangle
style.fill: "#3498db"
style.font-color: "#ffffff"
}
API网关: Kong {
shape: hexagon
}
订单服务: Spring Boot
商品服务: Spring Boot
库存服务: Go
订单数据库: PostgreSQL {
shape: cylinder
}
消息队列: Kafka {
shape: queue
}
Web前端 -> API网关: HTTPS
API网关 -> 订单服务: gRPC
API网关 -> 商品服务: gRPC
订单服务 -> 库存服务: gRPC
订单服务 -> 订单数据库: JDBC
订单服务 -> 消息队列: Publish
}
支付网关: "支付宝/微信支付" {
style.fill: "#95a5a6"
}
电商平台.订单服务 -> 支付网关: HTTPS
7.4 动态架构图:从运行时数据生成
除了静态分析,还可以从运行时数据(如分布式追踪、服务网格遥测数据)生成动态架构图:
#!/usr/bin/env python3
"""
从 Jaeger 追踪数据生成服务依赖图(Mermaid 格式)
"""
import requests
import json
from collections import defaultdict
def fetch_dependencies(jaeger_url: str) -> list[dict]:
"""从 Jaeger API 获取服务依赖关系"""
response = requests.get(
f"{jaeger_url}/api/dependencies",
params={"endTs": "now", "lookback": "86400000"} # 最近 24 小时
)
response.raise_for_status()
return response.json()["data"]
def generate_mermaid(dependencies: list[dict]) -> str:
"""将依赖关系转换为 Mermaid 图"""
lines = ["graph LR"]
services = set()
for dep in dependencies:
parent = dep["parent"]
child = dep["child"]
call_count = dep["callCount"]
services.add(parent)
services.add(child)
lines.append(
f' {_safe_id(parent)}["{parent}"] '
f'-->|"{call_count} calls"| '
f'{_safe_id(child)}["{child}"]'
)
return "\n".join(lines)
def _safe_id(name: str) -> str:
"""将服务名转换为合法的 Mermaid 节点 ID"""
return name.replace("-", "_").replace(".", "_")
if __name__ == "__main__":
jaeger_url = "http://localhost:16686"
deps = fetch_dependencies(jaeger_url)
mermaid_content = generate_mermaid(deps)
print(mermaid_content)
with open("service-dependencies.mmd", "w") as f:
f.write(mermaid_content)
print("依赖图已生成:service-dependencies.mmd")八、工程案例:电商平台的架构治理流水线
本节以一个中等规模的电商平台为例,演示如何将上述工具整合成一套完整的架构治理流水线。
8.1 项目背景
该电商平台的技术栈: - 后端:Java 21 + Spring Boot 3.x,采用模块化单体(Modular Monolith)架构 - 前端:React + TypeScript - 数据库:PostgreSQL + Redis - 消息队列:Apache Kafka - 部署:Kubernetes on AWS EKS - 团队规模:5 个后端开发组,共 30 人
架构治理面临的挑战: 1. 五个开发组各自维护不同的业务模块,跨模块依赖日益增多。 2. 原先的架构文档已经两年没有更新。 3. 多次出现底层模块意外依赖上层模块的情况,导致循环依赖。 4. 新的架构决策没有记录,新员工无法理解历史决策的背景。
8.2 治理方案设计
我们设计了一套分层的架构治理方案:
第一层:架构描述与可视化
将架构描述纳入代码仓库,使用 Structurizr DSL:
project-root/
├── docs/
│ ├── architecture/
│ │ ├── workspace.dsl # Structurizr 架构描述
│ │ ├── diagrams/ # 自动生成的架构图
│ │ └── supplementary/ # 补充说明文档
│ ├── adr/
│ │ ├── 0001-record-architecture-decisions.md
│ │ ├── 0002-modular-monolith.md
│ │ ├── 0003-choose-kafka.md
│ │ ├── 0004-cqrs-for-order.md
│ │ └── README.md # ADR 目录
│ └── runbook/ # 运维手册
├── src/
│ ├── main/java/com/ecommerce/
│ │ ├── order/ # 订单模块
│ │ ├── product/ # 商品模块
│ │ ├── inventory/ # 库存模块
│ │ ├── user/ # 用户模块
│ │ ├── payment/ # 支付模块
│ │ └── shared/ # 共享内核
│ └── test/java/com/ecommerce/
│ └── architecture/ # 架构测试
│ ├── LayerRuleTest.java
│ ├── ModuleBoundaryTest.java
│ └── NamingConventionTest.java
└── .github/
└── workflows/
└── architecture-check.yml
第二层:架构规则自动化检查
使用 ArchUnit 编写模块边界规则:
// ModuleBoundaryTest.java
package com.ecommerce.architecture;
import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.core.importer.ImportOption;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static com.tngtech.archunit.library.Architectures.layeredArchitecture;
import static com.tngtech.archunit.library.dependencies.SlicesRuleDefinition.slices;
class ModuleBoundaryTest {
private static JavaClasses classes;
@BeforeAll
static void setup() {
classes = new ClassFileImporter()
.withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS)
.importPackages("com.ecommerce");
}
@Test
void 模块之间不能存在循环依赖() {
slices()
.matching("com.ecommerce.(*)..")
.should().beFreeOfCycles()
.check(classes);
}
@Test
void 模块间只能通过公开API交互() {
// 各模块只暴露 api 子包中的接口
slices()
.matching("com.ecommerce.(*)..")
.should().notDependOnEachOther()
.ignoreDependency(
// 允许依赖其他模块的 api 子包
clazz -> true,
clazz -> clazz.getPackageName().contains(".api.")
|| clazz.getPackageName().contains(".shared.")
)
.check(classes);
}
@Test
void 每个模块内部遵循分层架构() {
layeredArchitecture()
.consideringAllDependencies()
.layer("API").definedBy("..api..")
.layer("Application").definedBy("..application..")
.layer("Domain").definedBy("..domain..")
.layer("Infrastructure").definedBy("..infrastructure..")
.whereLayer("API").mayNotBeAccessedByAnyLayer()
.whereLayer("API").mayOnlyAccessLayers("Application", "Domain")
.whereLayer("Application").mayOnlyAccessLayers("Domain", "Infrastructure")
.whereLayer("Infrastructure").mayOnlyAccessLayers("Domain")
.whereLayer("Domain").mayOnlyAccessLayers()
.check(classes);
}
}第三层:CI/CD 集成
# .github/workflows/architecture-check.yml
name: Architecture Governance
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
architecture-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
- name: Run architecture tests
run: |
./gradlew test --tests "com.ecommerce.architecture.*" \
--no-daemon --info
- name: Check for architecture violations
if: failure()
run: |
echo "::error::架构规则检查失败!请查看测试报告。"
echo "常见问题:"
echo "1. 模块间存在循环依赖"
echo "2. 违反了分层架构规则"
echo "3. 命名不符合规范"
architecture-diagrams:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Generate architecture diagrams
run: |
docker run --rm \
-v ${{ github.workspace }}/docs/architecture:/usr/local/structurizr \
structurizr/cli \
export -workspace /usr/local/structurizr/workspace.dsl \
-format plantuml/structurizr \
-output /usr/local/structurizr/diagrams
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs/architecture/diagrams
adr-site:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Build ADR site
run: |
npm install -g log4brains
log4brains build --out ./adr-site
- name: Deploy ADR site
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./adr-site
destination_dir: adr8.3 实施效果
经过三个月的实施,团队取得了以下效果:
- 依赖违规降至零——通过 ArchUnit 测试,所有模块间的循环依赖在两周内被清除,新的违规在 CI 阶段就会被拦截。
- 架构图始终最新——Structurizr DSL 与代码放在同一仓库中,每次合并到主分支都会自动生成最新的架构图。
- 决策可追溯——三个月内积累了 18 条 ADR,新员工入职时可以通过 ADR 站点快速了解历史架构决策。
- 代码评审效率提升——评审者可以直接引用 ADR 编号和架构规则来讨论设计问题,减少了口头争论。
8.4 关键度量指标
我们用以下指标来衡量架构治理的效果:
| 指标 | 实施前 | 实施后(三个月) | 目标 |
|---|---|---|---|
| 模块间循环依赖数 | 12 | 0 | 0 |
| 架构图更新频率 | 每半年一次 | 每次合并自动更新 | 实时 |
| ADR 覆盖率 | 0% | 85%(重要决策) | 100% |
| 新员工理解架构平均耗时 | 2 周 | 3 天 | 3 天 |
| 架构违规导致的生产事故 | 3 次/季度 | 0 次/季度 | 0 |
| 代码评审中架构讨论占比 | 5% | 25% | 30% |
九、工具选型的权衡与建议
面对众多的架构工具,团队需要根据自身情况做出选择。以下是一些选型建议:
9.1 架构建模工具对比
| 维度 | Structurizr DSL | PlantUML | Mermaid | D2 |
|---|---|---|---|---|
| 学习曲线 | 中 | 中 | 低 | 低 |
| C4 模型支持 | 原生 | 扩展库 | 手动 | 手动 |
| 版本控制友好度 | 优秀(纯文本) | 优秀(纯文本) | 优秀(纯文本) | 优秀(纯文本) |
| IDE 支持 | VS Code 插件 | 多 IDE 支持 | GitHub/GitLab 原生 | VS Code 插件 |
| 输出格式 | 多格式导出 | SVG/PNG | SVG(浏览器渲染) | SVG/PNG |
| 交互性 | 可交互(Lite) | 静态 | 静态 | 静态 |
| 适合场景 | 正式架构文档 | 技术设计文档 | 轻量嵌入式图 | 快速原型 |
9.2 按团队规模的推荐方案
小型团队(5-15 人): - 架构描述:Mermaid(嵌入 Markdown) + Structurizr Lite - 依赖分析:dependency-cruiser(前端)或 ArchUnit(Java) - 决策记录:ADR Tools + Markdown 文件 - 可视化:GitHub/GitLab 内置 Mermaid 渲染
中型团队(15-50 人): - 架构描述:Structurizr DSL + CI 自动导出 - 依赖分析:ArchUnit + Sonargraph Explorer(免费版) - 决策记录:Log4brains + 自动生成站点 - 可视化:Structurizr Lite + PlantUML
大型团队(50 人以上): - 架构描述:Structurizr On-Premises + 自定义扩展 - 依赖分析:Lattix / Sonargraph(商业版) + ArchUnit - 决策记录:Log4brains + Backstage 集成 - 可视化:定制化架构门户 + 运行时依赖图
9.3 常见的反模式
在引入架构工具时,需要避免以下反模式:
- 工具过载——一次性引入太多工具,团队来不及消化,反而增加了认知负担。建议从最核心的一两个工具开始,逐步扩展。
- 只有工具没有流程——工具本身不能代替流程。ArchUnit 测试写好了但不在 CI 中运行,等于没有。ADR 模板准备好了但没人写,也是白费。
- 追求完美的架构图——架构图的目的是沟通,不是艺术品。花太多时间在图的美观上,不如把时间花在内容的准确性上。
- 忽视运行时视角——静态分析只能告诉你代码中的依赖关系,但实际的调用链、数据流向需要运行时数据来补充。
- 架构治理变成架构官僚——架构规则应该服务于工程效率,而不是阻碍开发速度。如果开发者花大量时间绕过架构检查,说明规则本身可能需要调整。
十、架构可视化进阶:服务目录与技术雷达
在微服务或大型单体系统中,仅靠架构图是不够的。团队还需要一个「服务目录」来管理所有服务的元数据,以及一个「技术雷达」来跟踪技术选型的演进。
10.1 Backstage:统一的开发者门户
Backstage 是由 Spotify 开源的开发者门户平台,它提供了服务目录(Software Catalog)、技术文档(TechDocs)、模板(Software Templates)等功能。
在 Backstage 中注册一个服务的元数据:
# catalog-info.yaml
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: order-service
description: 订单服务:处理订单创建、支付、取消等生命周期管理
annotations:
backstage.io/techdocs-ref: dir:.
github.com/project-slug: ecommerce/order-service
pagerduty.com/service-id: P1234567
tags:
- java
- spring-boot
- grpc
links:
- url: https://grafana.internal/d/order-service
title: Grafana Dashboard
- url: https://docs.internal/adr
title: Architecture Decision Records
spec:
type: service
lifecycle: production
owner: team-order
system: ecommerce-platform
providesApis:
- order-api
consumesApis:
- inventory-api
- payment-gateway-api
dependsOn:
- resource:order-database
- resource:kafka-cluster10.2 技术雷达
技术雷达(Technology Radar)是 ThoughtWorks 发明的一种技术评估和沟通工具。团队可以建立自己的技术雷达,定期(如每季度)更新:
{
"title": "电商平台技术雷达 - 2026 Q2",
"rings": [
{"id": "adopt", "name": "采纳", "color": "#2ecc71"},
{"id": "trial", "name": "试用", "color": "#3498db"},
{"id": "assess", "name": "评估", "color": "#f39c12"},
{"id": "hold", "name": "暂缓", "color": "#e74c3c"}
],
"quadrants": [
{"id": "languages", "name": "语言与框架"},
{"id": "tools", "name": "工具"},
{"id": "platforms", "name": "平台"},
{"id": "techniques", "name": "技术实践"}
],
"entries": [
{
"label": "Java 21 Virtual Threads",
"quadrant": "languages",
"ring": "adopt",
"description": "已在订单服务中使用,显著降低了线程管理复杂度"
},
{
"label": "Structurizr DSL",
"quadrant": "tools",
"ring": "adopt",
"description": "已全面采用,所有架构描述均使用 DSL 定义"
},
{
"label": "ArchUnit",
"quadrant": "tools",
"ring": "adopt",
"description": "所有 Java 模块均已接入架构测试"
},
{
"label": "D2 语言",
"quadrant": "tools",
"ring": "trial",
"description": "在部分团队试用中,语法简洁,适合快速出图"
},
{
"label": "gRPC + Protobuf",
"quadrant": "languages",
"ring": "adopt",
"description": "内部服务间通信标准协议"
},
{
"label": "GraphQL",
"quadrant": "languages",
"ring": "assess",
"description": "评估是否用于 BFF 层的 API 聚合"
},
{
"label": "Backstage",
"quadrant": "platforms",
"ring": "trial",
"description": "正在试点部署,用于服务目录管理"
},
{
"label": "手动架构图(PPT/Visio)",
"quadrant": "tools",
"ring": "hold",
"description": "已全面迁移到代码化架构描述,不再使用手动绘图"
}
]
}10.3 整合架构可视化门户
将上述工具整合到一个统一的架构可视化门户中:
#!/usr/bin/env python3
"""
架构门户静态站点生成器
整合 Structurizr 图、ADR、技术雷达到一个站点
"""
import json
import subprocess
from pathlib import Path
def generate_architecture_portal(config_path: str) -> None:
"""生成架构门户静态站点"""
config = json.loads(Path(config_path).read_text())
output_dir = Path(config["output_dir"])
output_dir.mkdir(parents=True, exist_ok=True)
# 步骤一:导出 Structurizr 图
print("正在导出架构图...")
subprocess.run([
"structurizr-cli", "export",
"-workspace", config["structurizr_workspace"],
"-format", "plantuml/structurizr",
"-output", str(output_dir / "diagrams")
], check=True)
# 步骤二:构建 ADR 站点
print("正在构建 ADR 站点...")
subprocess.run([
"log4brains", "build",
"--out", str(output_dir / "adr")
], check=True)
# 步骤三:生成技术雷达页面
print("正在生成技术雷达...")
radar_data = json.loads(
Path(config["tech_radar_data"]).read_text()
)
generate_radar_page(radar_data, output_dir / "radar")
# 步骤四:生成首页
print("正在生成首页...")
generate_index_page(config, output_dir)
print(f"架构门户已生成到:{output_dir}")
def generate_radar_page(radar_data: dict, output_dir: Path) -> None:
"""生成技术雷达 HTML 页面"""
output_dir.mkdir(parents=True, exist_ok=True)
html_content = render_radar_template(radar_data)
(output_dir / "index.html").write_text(html_content)
def generate_index_page(config: dict, output_dir: Path) -> None:
"""生成门户首页"""
index_html = f"""<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>{config['title']}</title>
</head>
<body>
<h1>{config['title']}</h1>
<nav>
<ul>
<li><a href="diagrams/">架构图</a></li>
<li><a href="adr/">架构决策记录</a></li>
<li><a href="radar/">技术雷达</a></li>
</ul>
</nav>
</body>
</html>"""
(output_dir / "index.html").write_text(index_html)
def render_radar_template(data: dict) -> str:
"""渲染技术雷达 HTML 模板"""
return f"<html><body><h1>{data['title']}</h1></body></html>"
if __name__ == "__main__":
generate_architecture_portal("portal-config.json")十一、总结与实践清单
架构师的工具箱不在于工具的数量,而在于工具的合理组合和持续使用。以下是本文的核心要点总结:
11.1 关键原则
- 架构即代码(Architecture as Code)——将架构描述文件纳入代码仓库,享受版本控制、代码评审、自动化构建的全部好处。
- 分层可视化——使用 C4 模型的四个层次,为不同受众提供不同粒度的架构视图。
- 决策可追溯——通过 ADR 记录每一个重要的架构决策,确保决策的上下文和理由不会随时间丢失。
- 规则可执行——使用 ArchUnit 等工具将架构规则转化为可自动执行的测试,在 CI 中持续守护。
- 持续演进——架构不是一次性的设计,工具也不是一次性的配置。需要定期回顾和调整。
11.2 实践清单
对于希望建立架构治理体系的团队,建议按以下顺序逐步实施:
第一阶段(1-2 周): - 选择一种架构描述语言(推荐 Structurizr DSL) - 为现有系统创建 Context 和 Container 级别的架构描述 - 建立 ADR 目录,补写最重要的 3-5 条历史决策
第二阶段(2-4 周): - 编写核心架构规则的 ArchUnit 测试(分层规则、循环依赖检测) - 将架构测试纳入 CI 流水线 - 配置 Structurizr DSL 的自动导出和发布
第三阶段(1-2 个月): - 引入依赖分析工具,生成完整的依赖矩阵 - 建立技术雷达,每季度更新一次 - 搭建统一的架构门户(可选)
第四阶段(持续): - 每次重要变更时更新架构描述和 ADR - 每个季度回顾一次架构规则和适应度函数 - 根据团队反馈持续优化工具配置
架构治理是一个持续的过程,不要指望一步到位。选择最适合当前阶段的工具,解决最紧迫的问题,然后逐步迭代。工具是手段,目标始终是:让团队对系统架构有共同的理解,并能够在架构约束下高效地演进系统。
上一篇:遗留系统现代化
下一篇:康威定律
参考资料
- Simon Brown,“The C4 Model for Visualising Software Architecture”,https://c4model.com/
- Simon Brown,“Structurizr DSL Language Reference”,https://docs.structurizr.com/dsl/language
- Neal Ford、Rebecca Parsons、Patrick Kua,《演进式架构》(Building Evolutionary Architectures),O’Reilly Media,2017
- Michael Nygard,“Documenting Architecture Decisions”,https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions
- ArchUnit 官方文档,https://www.archunit.org/userguide/html/000_Index.html
- Lattix 官方文档,https://lattix.com/documentation/
- Sonargraph 官方文档,https://www.hello2morrow.com/products/sonargraph
- dependency-cruiser 官方文档,https://github.com/sverweij/dependency-cruiser
- Backstage 官方文档,https://backstage.io/docs/overview/what-is-backstage
- ThoughtWorks Technology Radar,https://www.thoughtworks.com/radar
- Log4brains 官方文档,https://github.com/thomvaill/log4brains
- D2 语言官方文档,https://d2lang.com/
- PlantUML C4 扩展库,https://github.com/plantuml-stdlib/C4-PlantUML
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【系统架构设计百科】架构视图与文档:C4 模型从入门到实战
架构图画完三个月就过期,架构文档写完没人看。问题不在于画不画,而在于用什么模型画、用什么方式维护。本文从 C4 模型的四层视图出发,拆解 diagram-as-code 工具链和文档即代码的工程实践,给出一套让架构文档能活下来的方法。
【系统架构设计百科】架构质量属性:不只是"高可用高性能"
需求评审时写下的'高可用、高性能、高并发',到了架构设计阶段几乎无法落地——因为它们不是可执行的需求。本文从 SEI/CMU 的质量属性理论出发,用 stimulus-response 场景模型把模糊需求变成可量化、可验证的架构约束,并拆解属性之间的冲突与联动关系。
【系统架构设计百科】告警策略:如何避免"狼来了"
大多数团队的告警系统都在制造噪声而不是传递信号。阈值告警看似直观,实则产生大量误报和漏报,值班工程师在凌晨三点被叫醒,却发现只是一次无害的毛刺。本文从告警疲劳的工业数据出发,拆解基于 SLO 的多窗口燃烧率告警算法,深入 Alertmanager 的路由、抑制与分组机制,结合 PagerDuty 的告警疲劳研究和真实工程案例,给出一套可落地的告警策略设计方法。
【系统架构设计百科】复杂性管理:架构的核心战场
系统复杂性是架构腐化的根源——本文从 Brooks 的本质复杂性与偶然复杂性划分出发,结合认知负荷理论与 Parnas 的信息隐藏原则,系统阐述复杂性的来源、度量与控制手段,并给出可操作的架构策略