
Ddd Architecture Doc
- 14 installs
- 1 repo stars
- Updated July 29, 2026
- full-statck-skills/ddd-skills
Generates DDD architecture documentation: C4 model diagrams, ADRs, domain-model docs, API docs, and decision logs.
About
Produces DDD architecture documentation including C4 diagrams (L1-L4), ADRs, domain-model docs, and team-communication templates. A developer uses it to document a DDD architecture for the team.
- C4 model diagrams in Mermaid
- ADR templates with status tracking
Ddd Architecture Doc by the numbers
- 14 all-time installs (skills.sh)
- Ranked #1,094 of 1,879 Documentation skills by installs in the Skillselion catalog
- Data as of Jul 30, 2026 (Skillselion catalog sync)
npx skills add https://github.com/full-statck-skills/ddd-skills --skill ddd-architecture-docAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 14 |
|---|---|
| repo stars | ★ 1 |
| Last updated | July 29, 2026 |
| Repository | full-statck-skills/ddd-skills ↗ |
What it does
Generates DDD architecture documentation: C4 model diagrams, ADRs, domain-model docs, API docs, and decision logs.
Files
DDD Architecture Documentation
Generate comprehensive DDD architecture documentation: C4 model diagrams (L1-L4), ADRs, domain model docs, API docs, decision logs, and team communication templates.
Workflow
Follow this 5-step workflow when generating architecture documentation:
Step 1: Understand Context — Project size, team, tech stack, domain
Step 2: Identify Audiences — Business / dev / ops
Step 3: Select C4 Level — L1 for business, L2 for ops, L3 for dev team
Step 4: Check Decisions — Any existing ADRs? Need to create new ones?
Step 5: Generate Output — Combine diagrams + ADRs + templates into one docWhen info is insufficient: give a best-guess version first based on common patterns (e.g., e-commerce) + list what specific information is still needed. Never just say "请提供更多信息".
Boundary
✅ 擅长处理
1. C4 模型图生成 — L1 System Context / L2 Container / L3 Component / L4 Code(Mermaid) 2. ADR 架构决策记录 — 模板 + 索引 + 状态追踪 3. 领域模型文档 — 聚合描述 + 实体/值对象/事件列表 4. API 文档 — CQRS 命令/查询分离的 API 规范
⚠️ 需要条件
1. 已有架构决策 — 需要先有决策才能记录 ADR 2. 已识别限界上下文 — 至少知道系统有哪些 BC 才能画 C4 L1 图 3. 技术栈已知 — 需要知道框架/数据库/中间件才能生成 L2 容器图
❌ 超出范围(不适用场景)
1. 无架构决策 → 先做决策再文档(路由到 ddd-architecture-selector) 2. 单人项目 → README + 行内注释即可 3. 需架构选型 → `ddd-architecture-selector` 4. 需代码审查 → `ddd-code-reviewer`
Audience
This skill is designed for: Backend developers (implementing DDD architectures), Software architects (evaluating and selecting patterns), Tech leads (reviewing team implementations), and DDD beginners (learning domain-driven design fundamentals).
Rules
1. Every architecture decision must be documented as an ADR. 2. C4 diagrams must follow Level 1→4 hierarchy. 3. Domain model documentation must reference bounded contexts. 4. All decision logs must include date, context, options, and rationale.
C4 模型四层
DDD → C4 Mapping
C4 Level | DDD Context | Audience
─────────────┼───────────────────────────────┼────────────────
L1 Context | All bounded contexts + externals | Business, Architects
L2 Container | Per-BC deployment units | Architects, DevOps
L3 Component | BC internal layers (Adapter/App/Domain/Infra) | Dev Team
L4 Code | Aggregate internals (entities, VOs, events) | DevelopersL1: System Context — 展示系统与外部关系
graph TB
Customer["👤 Customer"] --> BC1["Bounded Context 1"]
Customer --> BC2["Bounded Context 2"]
Admin["👤 Admin"] --> BC3["Bounded Context 3"]
BC1 --> PaymentGW["💳 Payment Gateway"]L2: Container — 单个 BC 的部署单元
graph TB
Web["Web App"] --> API["API (Spring Boot)"]
API --> DB[("Database (PostgreSQL)")]
API --> Queue["Event Queue (RabbitMQ)"]L3/L4 完整 Mermaid 代码示例见 references/01-c4-examples.md。
When to use each level: L1 for project kickoff, L2 for ops handover, L3 for daily dev reference, L4 for complex aggregates only.
ADR (Architecture Decision Record)
ADR Template
# ADR-{NNN}: {Short Title}
## Status
{Proposed / Accepted / Deprecated / Superseded}
## Context / Decision / Alternatives / Consequences
- **Context**: Why is this decision needed?
- **Decision**: What did we decide?
- **Alternatives**: Options considered with pros/cons, mark chosen
- **Consequences**: Positive + negative impacts
- **Related**: ADR-{NNN}: {related}ADR Status Tracking Table
| ADR# | Title | Status | Date | Superseded By |
|------|-------|:------:|:----:|:----:|
| 001 | Choose COLA Architecture | Accepted | 2024-03-15 | — |
| 002 | CQRS Strategy L2 | Accepted | 2024-03-20 | — |
| 003 | MySQL over PostgreSQL | Deprecated | 2024-02-01 | ADR-005 |Domain Model Documentation
Document each aggregate:
## Aggregate: {Name}
- **Root**: {ClassName} | **Id**: {IdType}
- **Entities**: Table of entity / owner / lifecycle
- **Value Objects**: Table of VO / fields / immutable
- **Domain Events**: Table of event / trigger / consumer
- **Invariants**: 1. {Invariant 1}
- **State Machine**: ```mermaid stateDiagram-v2```API Documentation — CQRS 命令/查询分离
| API Type | Method | Example | CQRS Model |
|---|---|---|---|
| Command | POST/PUT/DELETE | POST /orders | Command Model |
| Query | GET | GET /orders?status=PAID | Query Model |
Command API: triggers domain behavior, publishes domain events, idempotent key required. Query API: reads from query model (may be separate read DB), no side effects.
Architecture Decision Log
Maintain a central index:
docs/adrs/
├── README.md ← Auto-generated ADL index
├── ADR-001-title.md
└── ...Best practices: one ADR file = one decision; ADR in the same repo as code; CI auto-generates the index.
文档维护策略
| 策略 | 频率 | 谁负责 |
|---|---|---|
| PR 时同步更新 ADR + 图 | 每次代码变更 | 开发者 |
| C4 图季度审计 | 每季度 | 架构师 |
| ADL 索引自动生成 | 每次 ADR 变更 | CI |
| 全量架构文档 Review | 每月 | 架构组 |
Golden rule: if code changes the architecture, the doc changes in the same PR.
Gotchas — Common Pitfalls
1. C4 层级乱用 — 每层有明确定义,不要混用。 2. ADR 写太晚 — 决策时同步记录,哪怕只写一句话。 3. 文档与代码不同步 — 每次架构变更后必须更新。 4. 只画图不写决策理由 — C4 展示 What,ADR 解释 Why。 5. 图过于复杂 — 每张图 5-7 节点为限。 6. 过度文档 — 聚焦"别人需要知道什么才能开发"。 7. ADR 不写备选 — 必须记录为什么没选其他方案。 8. 忽略受众 — 不同受众用不同 C4 级别。
FAQ
Q1: 文档应该用什么工具? 先用 Mermaid,复杂度上升后考虑 Structurizr。
Q2: 需要画哪些 C4 层级? L1 + L2 是必须的,L3 视团队规模(>5 人推荐)。
Q3: 怎么保证文档不过期? PR 勾选框 + CI 检查 ADR 一致性 + 月度 Review。
Q4: 遗留系统没有文档怎么办? 先画 AS-IS 的 L1 图 → 记录关键 ADR → 每 sprint 完善一个 BC。
Q5: ADR 需要写多详细? 至少包含背景、决策、备选方案(≥2 个)和影响。
Q6: 多人同时改一个 BC 的文档怎么处理? Git 冲突解决机制即可,PR Review 时同步 Review 文档。
Security & Safety
This skill is pure documentation. It does not collect user data, does not access external services or networks, and contains no executable scripts.
Keywords
- Keywords: architecture documentation, 架构文档, ADR, C4 diagram, C4 模型, architecture decision record, 架构决策记录, domain model doc, 领域模型文档, 技术文档, 架构图, system context, container diagram, component diagram, code diagram, 架构评审, 文档模板, architecture decision log
References
| File | Content | When to Reference |
|---|---|---|
references/01-c4-examples.md | Full C4 L1-L4 Mermaid examples for e-commerce | User needs complete C4 diagrams to copy-paste |
references/02-adr-templates.md | 3 ADR template variants (standard, lightweight, tech) | User needs to write a new ADR |
references/03-doc-templates.md | 3 architecture doc templates (full, lightweight, onboarding) | User needs a document structure to start with |
references/04-toolchain.md | Tool recommendations (Structurizr, Mermaid, PlantUML, ArchUnit) | User asks about tools or automation |
references/05-team-templates.md | Team communication templates (review request, change notice) | User needs to notify or review with team |
references/06-arch-decision-log.md | ADL index format + CI automation | User needs to maintain or automate ADR tracking |
references/07-domain-model-doc.md | Aggregate/BC documentation patterns | User needs to document domain models |
references/08-api-doc-patterns.md | CQRS API documentation patterns + OpenAPI spec | User needs to document APIs with CQRS |
references/09-trace-anti-patterns.md | Architecture doc anti-patterns (5 categories) | User needs to avoid common documentation mistakes |
references/10-faq-deep.md | In-depth FAQ (microservices ADR, legacy systems, security) | User has advanced or edge-case questions |
Related Skills
- ddd-architecture-selector — Architecture selection (before you document, make decisions)
- ddd-architecture-evaluator — Periodic architecture health check
- ddd-code-reviewer — Code-level DDD compliance check
- ddd-cqrs-architecture — CQRS detail for API documentation
- awesome — DDD concept overview
ADR 完整示例 — 电商平台
本文档提供电商平台的 3 个完整 ADR 示例,覆盖架构选型、CQRS、技术选型三类场景。
---
ADR-001: 选择 COLA v5 作为基础架构
状态: 已采纳 (2024-03-15)
背景: 电商中台项目,5 个限界上下文(订单、支付、商品、库存、用户),团队 8 人(4 后端 + 2 前端 + 1 PM + 1 QA)。需要统一的架构规范来约束开发行为。
决策: 采用 COLA v5 架构(菱形架构),单模块简化版。
备选方案:
| 方案 | 优点 | 缺点 | 决定 |
|---|---|---|---|
| 传统三层 | 团队熟悉,学习成本低 | 复杂业务难维护 | ✗ |
| 六边形 | 可测试性强,Port/Adapter 清晰 | 学习成本高,门槛高 | ✗ |
| 整洁架构 | 企业级规范,分层严格 | 过度设计,团队 8 人扛不住 | ✗ |
| COLA v5 | 国内生态好,文档齐全 | — | ✓ |
决策理由: 1. 团队使用 Spring Boot + MyBatis,COLA 对此生态最佳支持 2. COLA 5.0 中文文档齐全,降低团队学习成本 3. 具备内置的架构校验能力,可持续约束开发行为 4. 单模块简化版不引入过多模块 Maven 管理成本
影响:
- 正向:统一了团队架构规范,新人按 COLA 目录结构即可理解代码
- 正向:层次清晰,领域层纯净无框架依赖
- 负向:模块数从 1 增加到 4(adapter/app/domain/infrastructure)
- 负向:新人上手需要 1 周 DDD + COLA 培训
- 中性:CI/CD 需增加 ArchUnit 检查步骤
关联:
- ADR-002: CQRS 实施策略
- ADR-003: 事件中间件选型
---
ADR-002: CQRS L2 策略(数据库分离)
状态: 已采纳 (2024-03-20)
背景: 订单查询 QPS 从 500 增长到 3000+,而写操作 QPS 仅 200。当前的读写混合模型导致:
- 复杂查询(跨聚合 JOIN、聚合统计)需要多表查询,性能差
- 查询缓存方案复杂,缓存一致性难以保证
- 读模式(DTO/VO)与领域模型(Domain Entity)混用,违反分层原则
决策: 采用 CQRS L2 策略,命令模型用 PostgreSQL,查询模型用 Elasticsearch。
备选方案:
| 方案 | 优点 | 缺点 | 决定 |
|---|---|---|---|
| L1 模型分离 | 简单,不增加基础设施 | 还是读同一个 DB,性能瓶颈不解决 | ✗ |
| L2 DB 分离 | 读写独立扩展,查询优化灵活 | 增加 ES 运维 | ✓ |
| L3 Event Sourcing | 完整审计追踪 | 学习成本极高,复杂度过高 | ✗ |
同步机制:
写操作 → Command DB (PostgreSQL) → 领域事件 → RabbitMQ → Projector → Query DB (ES)影响:
- 正向:查询性能提升 10x(从 50ms → 5ms P99)
- 正向:读模型可独立优化,不影响写模型的领域逻辑
- 负向:引入 ES 运维成本和数据同步延迟(< 1s)
- 负向:需要处理同步失败和补偿逻辑
关联:
- ADR-001: COLA v5 架构
- ADR-003: 事件中间件选型
---
ADR-003: 领域事件中间件选型
状态: 已采纳 (2024-03-25)
背景: 跨聚合/跨服务操作需要领域事件实现最终一致性。团队已有消息中间件经验,但需要选择合适的消息方案。
决策: 微服务内使用 Spring ApplicationEvent,跨微服务使用 RabbitMQ + Outbox 表。
备选方案:
| 方案 | 优点 | 缺点 | 决定 |
|---|---|---|---|
| 纯 Spring Event | 简单,零依赖 | 不支持跨服务 | ✗ |
| 纯 Kafka | 高吞吐,持久化好 | 运维复杂,团队不熟 | ✗ |
| Spring Event + RabbitMQ + Outbox | 渐进式,团队熟悉 | — | ✓ |
| 纯 RabbitMQ | 统一消息通道 | 微服务内也用 MQ 太重 | ✗ |
Outbox 模式说明:
业务操作 → 写 DB(含 Outbox 表) → Outbox Poller → 发 RabbitMQ → 消费者
↓
处理成功后删除 Outbox 记录影响:
- 正向:微服务内事件零额外成本(Spring Event)
- 正向:Outbox 模式保证"业务操作"和"事件发布"的原子性
- 正向:RabbitMQ 团队已有运维经验
- 负向:需要 Outbox Poller 组件(可选 Debezium CDC)
- 负向:RabbitMQ 相比 Kafka 在追数据场景能力弱
C4 图完整示例 — 电商平台
本文档展示电商平台完整的 C4 四层图示例。
所有图表使用 Mermaid 格式,可直接嵌入架构文档。
---
L1: System Context — 电商平台全景
graph TB
Customer["👤 顾客"]
Admin["👤 管理员"]
Supplier["🏭 供应商"]
Logistics["🚚 物流系统"]
PaymentGW["💳 支付网关"]
SMSService["📱 短信服务"]
subgraph Platform["🧩 电商平台"]
direction TB
BC1["订单系统"]
BC2["支付系统"]
BC3["商品系统"]
BC4["库存系统"]
BC5["用户系统"]
end
Admin -->|管理商品/订单| BC3
Customer -->|浏览下单| BC1
Customer -->|支付| BC2
Supplier -->|供货| BC4
BC1 -->|发货| Logistics
BC2 -->|调用| PaymentGW
BC1 -->|短信通知| SMSService说明:L1 图展示电商平台与外部角色的交互。这是给业务方和架构师看的"电梯演讲"图。
---
L2: Container — 订单系统内部容器
graph TB
subgraph OrderSystem["📦 订单系统"]
OrderAPI["Order API\n(Spring Boot)"]
OrderWorker["Order Worker\n(Spring Boot)"]
OrderDB[("Order DB\n(PostgreSQL 16)")]
OrderCache[("Order Cache\n(Redis 7.x)")]
OrderQueue["Order Event Queue\n(RabbitMQ 3.13)"]
end
Web["Web App\n(React)"]
Mobile["Mobile App\n(React Native)"]
PaymentSystem["支付系统"]
InventorySystem["库存系统"]
Web -->|REST/JSON| OrderAPI
Mobile -->|REST/JSON| OrderAPI
OrderAPI -->|读写| OrderDB
OrderAPI -->|缓存| OrderCache
OrderAPI -->|发事件| OrderQueue
OrderWorker -->|消费| OrderQueue
OrderWorker -->|写| OrderDB
OrderQueue -->|事件| PaymentSystem
OrderQueue -->|事件| InventorySystem说明:L2 图展示订单系统内部的容器划分和技术选型。开发者和 DevOps 关注的层面。
---
L3: Component — 订单 API 的 COLA 四层
graph TB
subgraph Adapter["适配层\n(adapter)"]
direction TB
Controller["OrderController"]
ReqDTO["CreateOrderRequest"]
RespDTO["OrderResponse"]
end
subgraph App["应用层\n(app)"]
direction TB
AppService["OrderAppService"]
Cmd["CreateOrderCommand"]
Query["OrderQueryService"]
end
subgraph Domain["领域层\n(domain)"]
direction TB
OrderAgg["Order (聚合根)"]
OrderItem["OrderItem (实体)"]
Money["Money (值对象)"]
OrderStatus["OrderStatus (枚举)"]
DomainEvent["OrderCreatedEvent"]
Repo["OrderRepository (接口)"]
DomainSvc["OrderDomainService"]
end
subgraph Infra["基础设施层\n(infrastructure)"]
direction TB
JpaRepo["JpaOrderRepository"]
EventPub["RabbitMqEventPublisher"]
CacheSvc["RedisCacheService"]
end
Controller --> AppService
Controller --> Query
AppService --> Cmd
AppService --> Repo
AppService --> DomainSvc
DomainSvc --> OrderAgg
OrderAgg --> OrderItem
OrderAgg --> Money
OrderAgg --> OrderStatus
OrderAgg --> DomainEvent
JpaRepo -.->|实现| Repo
EventPub --> OrderQueue说明:L3 图展示 COLA 四层架构中每个层的核心组件及其依赖关系。这是开发者日常工作的主要参考图。
---
L4: Code — 订单聚合类图
classDiagram
class Order {
-OrderId id
-CustomerId customerId
-OrderStatus status
-Money totalAmount
-List~OrderItem~ items
-Address shippingAddress
-LocalDateTime createdAt
+pay() void
+cancel(String reason) void
+addItem(ProductId, Money, int) void
+removeItem(ProductId) void
+calculateTotal() Money
+canBePaid() boolean
}
class OrderItem {
-ProductId productId
-String productName
-Money unitPrice
-int quantity
+getSubtotal() Money
+updateQuantity(int) void
}
class Money {
-BigDecimal amount
-Currency currency
+add(Money) Money
+subtract(Money) Money
+multiply(int) Money
+equals(Object) boolean
}
class OrderStatus {
<<enumeration>>
PENDING_PAYMENT
PAID
SHIPPED
DELIVERED
CANCELLED
+canPay() boolean
+canCancel() boolean
+nextStatus() OrderStatus
}
class OrderId {
-String value
+generate() OrderId
+fromString(String) OrderId
+toString() String
}
class Address {
-String province
-String city
-String district
-String detail
-String zipCode
+getFullAddress() String
}
class OrderCreatedEvent {
-OrderId orderId
-CustomerId customerId
-Money totalAmount
-LocalDateTime occurredOn
}
class OrderPaidEvent {
-OrderId orderId
-Money amount
-LocalDateTime paidAt
}
Order "1" --> "*" OrderItem
Order --> Money
Order --> OrderId
Order --> OrderStatus
Order --> Address
Order ..> OrderCreatedEvent : 发布
Order ..> OrderPaidEvent : 发布说明:L4 图展示 Order 聚合的内部类结构。开发者实现具体功能时的参考。
---
关键映射:DDD ↔ C4
| DDD 概念 | C4 级别 | 谁看 |
|---|---|---|
| 全系统所有限界上下文 | L1 System Context | 业务方、架构师 |
| 每个限界上下文部署单元 | L2 Container | 架构师、DevOps |
| 每个容器的 Adapter/App/Domain/Infra | L3 Component | 开发团队 |
| 聚合内部结构(实体、值对象、事件) | L4 Code | 开发者 |
完整架构文档示例 — 电商平台
本文档展示一个完整的电商平台架构文档。
---
电商平台架构文档
版本: v2.1 | 最后更新: 2024-06-01 | 负责人: 架构组
---
1. 架构概览
1.1 架构模式
- 架构: COLA v5(菱形架构)
- CQRS 级别: L2(数据库分离 — 写库 PostgreSQL / 读库 Elasticsearch)
- 微服务: 5 个服务(订单、支付、商品、库存、用户)
1.2 架构约束
1. 依赖规则: 领域层不依赖任何外部框架 2. 聚合规则: 聚合之间通过 ID 引用,不直接引用对象 3. 事务规则: 一个事务只修改一个聚合 4. 事件规则: 跨聚合操作通过领域事件实现最终一致性
---
2. 限界上下文
| 上下文 | 类型 | 职责 | 微服务 | 语言 |
|---|---|---|---|---|
| Order | 核心域 | 订单创建/支付/退款 | ✓ | Java |
| Payment | 核心域 | 支付渠道对接/对账 | ✓ | Java |
| Product | 支撑域 | 商品信息/分类/搜索 | ✓ | Java |
| Inventory | 支撑域 | 库存管理/锁定/释放 | ✓ | Java |
| User | 通用域 | 用户注册/认证/权限 | ✓ | Java |
上下文映射
graph LR
Order -->|OHS| Payment
Order -->|ACL| Inventory
Product -->|Partnership| Inventory
User -->|OHS| Order
User -->|OHS| Payment图例: OHS=开放主机服务, ACL=防腐层, Partnership=伙伴关系
---
3. C4 模型
L1: System Context
graph TB
Customer["👤 顾客"]
Admin["👤 管理员"]
Logistics["🚚 物流系统"]
PaymentGW["💳 支付网关"]
subgraph Platform["电商平台"]
Order["订单服务"]
Payment["支付服务"]
Product["商品服务"]
Inventory["库存服务"]
User["用户服务"]
end
Customer -->|"HTTP"| Order
Customer -->|"HTTP"| Payment
Admin -->|"HTTP"| Product
Order -->|"RPC"| Inventory
Order -->|"事件"| Payment
Payment -->|"HTTP"| PaymentGW
Order -->|"HTTP"| LogisticsL2: Container — 订单服务
graph TB
subgraph OrderSvc["订单服务"]
OrderAPI["Order API\n(Spring Boot)"]
OrderWorker["Order Worker\n(Spring Boot)"]
OrderDB[("Order DB\n(PostgreSQL)")]
OrderCache[("Redis")]
OrderQueue[("RabbitMQ")]
end
Web["Web App\n(React)"]
Mobile["Mobile App\n(React Native)"]
Web --> OrderAPI
Mobile --> OrderAPI
OrderAPI <--> OrderDB
OrderAPI <--> OrderCache
OrderAPI --> OrderQueue
OrderWorker <--> OrderQueue
OrderWorker --> OrderDB---
4. 技术栈
| 组件 | 技术 | 版本 | 说明 |
|---|---|---|---|
| 开发语言 | Java | 21 | — |
| 框架 | Spring Boot | 3.4.x | — |
| ORM | MyBatis Plus | 3.5.x | — |
| 数据库 | PostgreSQL | 16 | 写库 |
| 搜索引擎 | Elasticsearch | 8.x | 读库 |
| 缓存 | Redis | 7.x | 会话 + 缓存 |
| 消息队列 | RabbitMQ | 3.13 | 事件驱动 |
| 注册中心 | Nacos | 2.x | 服务发现 |
| 网关 | Spring Cloud Gateway | 4.x | — |
| 部署 | Kubernetes | 1.28 | — |
---
5. ADR 索引
| ADR# | 标题 | 状态 | 日期 | 负责人 |
|---|---|---|---|---|
| 001 | 选择 COLA v5 作为基础架构 | 已采纳 | 2024-03-15 | 张三 |
| 002 | CQRS L2 策略(DB 分离) | 已采纳 | 2024-03-20 | 李四 |
| 003 | 事件中间件: RabbitMQ | 已采纳 | 2024-03-25 | 王五 |
| 004 | MySQL → PostgreSQL 迁移 | 已采纳 | 2024-04-01 | 张三 |
| 005 | 单体 → 微服务拆分方案 | 已采纳 | 2024-05-01 | 赵六 |
---
6. 架构评审 Checklist
- [x] 依赖方向正确(Domain 零框架依赖)
- [x] 聚合间 ID 引用(无直接对象引用)
- [x] 关键操作有领域事件(OrderCreated, OrderPaid)
- [x] 跨聚合操作使用事件(下单 → 锁定库存)
- [x] ADR 记录完整(5 个决策)
- [x] C4 图与代码一致(已验证)
- [x] ArchUnit 集成 CI(通过)
领域模型文档示例
本文档展示电商平台 Order 和 Payment 两个主要聚合的领域模型文档。
---
聚合:订单(Order)
概述
订单是电商平台的核心聚合,管理订单从创建到完成的整个生命周期。
聚合根
- 类名:
Order - 标识:
OrderId(值对象,UUID 格式) - 业务标识:
orderNumber(人工可读,如 "ORD-20240501-00001")
业务规则(不变式 Invariants)
1. 不可重复支付: 订单只能支付一次,PAID 后不能再次支付 2. 金额一致性: 订单总金额 = 所有 OrderItem 金额之和 3. 合法状态转换: 状态机必须经过 PENDING_PAYMENT → PAID → SHIPPED → DELIVERED 4. 取消条件: 只有 PENDING_PAYMENT 和 PAID 状态的订单可以取消(PAID 取消需退款) 5. 商品数量限制: 单笔订单最多 50 个商品
状态机
stateDiagram-v2
[*] --> PENDING_PAYMENT : 创建订单
PENDING_PAYMENT --> PAID : 支付成功
PENDING_PAYMENT --> CANCELLED : 用户取消
PAID --> SHIPPED : 发货
PAID --> CANCELLED : 退款取消
SHIPPED --> DELIVERED : 确认收货
SHIPPED --> RETURNING : 申请退货
RETURNING --> CANCELLED : 退货完成实体(Entity)
| 实体 | 聚合内唯一 | 生命周期 | 说明 |
|---|---|---|---|
| Order | ✓(聚合根) | 从创建到完成 | 订单主体 |
| OrderItem | ✓ | 随 Order | 订单中的商品行 |
值对象(Value Object)
| 值对象 | 包含字段 | 不可变 | 说明 |
|---|---|---|---|
| OrderId | value: UUID | ✓ | 订单唯一标识 |
| Money | amount, currency | ✓ | 金额(BigDecimal + Currency) |
| OrderStatus | status: Enum | ✓ | 订单状态 |
| Address | province, city, district, detail | ✓ | 收货地址 |
领域事件
| 事件 | 触发条件 | 包含数据 | 消费者 |
|---|---|---|---|
| OrderCreatedEvent | 订单创建成功 | orderId, customerId, totalAmount | 库存服务(锁定库存) |
| OrderPaidEvent | 支付成功 | orderId, amount, paidAt | 物流服务(准备发货) |
| OrderCancelledEvent | 订单取消 | orderId, reason | 库存服务(释放库存) |
| OrderShippedEvent | 已发货 | orderId, trackingNumber | 用户通知服务 |
领域服务
| 服务 | 职责 | 为什么不是实体方法 |
|---|---|---|
| OrderPricingService | 计算订单价格(考虑优惠券、积分、会员折扣) | 涉及多个外部策略,不是订单自身的逻辑 |
| OrderValidationService | 验证下单(用户限购、商品限购、风控) | 跨多个聚合(User、Product)的校验 |
---
聚合:支付记录(PaymentRecord)
概述
支付记录聚合管理每笔支付的生命周期,包括支付、退款、对账。
聚合根
- 类名:
PaymentRecord - 标识:
PaymentId(值对象) - 业务标识:
paymentNo(支付单号)
业务规则
1. 支付金额一致性: 支付金额必须等于对应订单的待支付金额 2. 不可重复支付: 一个订单只能有一笔成功的支付记录 3. 退款金额上限: 退款金额 ≤ 已支付金额 4. 渠道幂等: 同一个支付渠道流水号只能处理一次
状态机
stateDiagram-v2
[*] --> PENDING : 创建支付单
PENDING --> SUCCESS : 支付成功回调
PENDING --> FAILED : 支付失败
SUCCESS --> REFUNDING : 申请退款
REFUNDING --> REFUNDED : 退款成功
REFUNDING --> FAILED : 退款失败值对象
| 值对象 | 说明 |
|---|---|
| PaymentId | 支付唯一标识 |
| Money | 金额(与 Order 共享) |
| PaymentChannel | 支付渠道枚举(WeChat/AliPay/UnionPay) |
| PaymentStatus | 支付状态枚举 |
领域事件
| 事件 | 触发条件 | 消费者 |
|---|---|---|
| PaymentSucceededEvent | 支付成功 | Order(更新订单为已支付) |
| PaymentRefundedEvent | 退款成功 | Order(更新订单为已取消) |
---
聚合间关系
graph LR
Order -->|通过 orderId 引用| PaymentRecord
Order -->|通过 customerId 引用| Customer
Order -->|通过 productId 引用| Product
PaymentRecord -->|通过 orderId 关联| Order关键设计决策:
- 所有跨聚合引用使用 ID(值对象),不使用对象引用
- Order 和 PaymentRecord 通过异步事件(OrderPaidEvent / PaymentSucceededEvent)协作
- Order 不直接持有 PaymentRecord 的引用,而是通过领域事件驱动协作
架构文档维护指南示例
本文档展示一个实际的架构文档维护计划。
---
架构文档维护计划
基本原则
1. 代码变更先改文档:文档在代码仓库中与代码一起 PR 2. ADR 在决策时记录:不做"后补" ADR 3. C4 图季度审查:每季度检查图与实际架构的一致性 4. 文档 Review 纳入开发流程:PR Review 时同步 Review 文档变更
维护节奏
| 频率 | 任务 | 负责人 | 触发条件 |
|---|---|---|---|
| 每次提交 | ADR 更新 | 开发者 | 架构变更 |
| 每次提交 | C4 图更新 | 开发者 | 模块/接口变更 |
| 每周 | ADL 索引更新 | CI | 自动检测 ADR 目录变更 |
| 每月 | 架构文档 Review | 架构师 | 月度架构会议 |
| 每季度 | 全量架构审计 | 架构组 | 季度回顾 |
---
变更流程示例
场景:增加 Redis 缓存层
步骤 1: 评估影响
- 影响 C4 L2 图(订单服务容器图增加 Redis)
- 涉及架构决策(是否用缓存、选 Redis 的原因)
- 需要 ADR
步骤 2: 创建 ADR
# ADR-006: 订单服务增加 Redis 缓存层
## 状态
已采纳 (2024-06-01)
## 背景
订单查询 QPS 从 500 增长到 3000,当前每次查询都走 DB,DB CPU 已达 70%。
## 决策
在订单服务中增加 Redis 缓存层,缓存订单读模型数据。
## 备选方案
| 方案 | 优点 | 缺点 | 决定 |
|------|------|------|:----:|
| Local Cache | 简单 | 多实例不一致 | ✗ |
| Redis Cluster | 高性能、成熟 | 运维增加 | ✓ |
## 影响
- 读操作:先查 Redis → 未命中再查 DB → 回填 Redis
- 写操作:更新 DB 后删除对应缓存
- 缓存 TTL:订单数据 5 分钟,热数据 30 秒步骤 3: 更新 C4 L2 图 在订单服务容器图中增加 Redis 容器节点。
步骤 4: 提交 PR
- 代码变更 + 文档变更 + ADR
- PR 描述包含架构变更声明
---
定期审查结果模板
# 架构文档 6 月审查报告
## 审查时间
2024-06-28 | 审查人: 架构组
## 审查结果
| 文档 | 状态 | 问题 |
|------|:----:|------|
| 架构概览 | ✅ | 最新 |
| C4 L1 图 | ✅ | 最新 |
| C4 L2 图(订单服务) | ⚠️ | 未包含新增的 Redis |
| C4 L2 图(支付服务) | ✅ | 最新 |
| ADR 索引 | ✅ | 最新(含 ADR-006) |
| 领域模型文档 | ⚠️ | Order 新增了优惠券字段 |
## 行动计划
| 优先级 | 任务 | 负责人 | 截止 |
|:------:|------|--------|:----:|
| P0 | 更新 C4 L2 订单->增加 Redis | 张三 | 2024-07-05 |
| P1 | 更新 Order 领域模型文档 | 李四 | 2024-07-10 |文档健康度指标
| 指标 | 目标 | 当前 | 状态 |
|---|---|---|---|
| 文档与代码仓库同步 | 100% | 95% | 🟢 |
| ADR 记录时效性 | 决策后 1 天内 | <1 天 | 🟢 |
| C4 图季度更新 | 100% | 80% | 🟡 |
| 团队文档阅读率 | 80% | 60% | 🟡 |
| 新人 onboarding 时间 | <3 天 | 2.5 天 | 🟢 |
ADR 架构决策记录 — 实战模板
ADR-001: 选择 DDD 分层架构
状态:已采纳 (2024-03-15)
背景:电商中台系统,5 个限界上下文(订单、支付、产品、库存、客户),团队 8 人。需要统一架构规范。
决策:采用 DDD 四层分层架构(Interface → Application → Domain ← Infrastructure)
备选方案:
| 方案 | 优点 | 缺点 | 决定 |
|---|---|---|---|
| 传统三层 | 团队熟悉 | 复杂业务难维护 | ✗ |
| 六边形 | 可测试性强 | 学习成本高 | ✗ |
| COLA v5 | 中文生态好 | 多模块复杂度 | ✗ |
| DDD 四层 | 渐进式、易理解 | 基础设施不可替换 | ✓ |
影响:
- 模块数从 1 个增加到 4 个
- 新人需 1 周 DDD 培训
- CI/CD 需增加 ArchUnit 检查
ADR-002: CQRS 等级选择 L1
状态:已采纳 (2024-03-20)
背景:订单查询和命令的读写模式差异显著。查询需要跨聚合 JOIN,命令只需单聚合操作。
决策:采用 CQRS L1(模型分离),CommandService 和 QueryService 分离,共用同一数据库。
不选 L2 的原因:当前读 QPS < 1000,不需要独立的读数据库;引入 ES 或只读副本会增加运维复杂度。
影响:
- App 层拆分为 command/ 和 query/ 子包
- 后续可平滑升级到 L2
ADR-003: 领域事件中间件选型
状态:已采纳 (2024-03-25)
背景:跨聚合操作需要领域事件实现最终一致性。团队已部署 RabbitMQ。
决策:微服务内使用 Spring ApplicationEvent,跨微服务使用 RabbitMQ + Outbox 表。
备选方案:
| 方案 | 优点 | 缺点 | 决定 |
|---|---|---|---|
| 纯 Spring Event | 简单 | 不支持跨服务 | ✗ |
| 纯 Kafka | 高性能 | 运维复杂 | ✗ |
| Spring Event + RabbitMQ + Outbox | 渐进式 | — | ✓ |
ADR 格式规范
每个 ADR 文件命名:ADR-{NNN}-{简短描述}.md
必须包含: 1. 标题(ADR-NNN) 2. 状态(提议/已采纳/已废弃/已替代) 3. 背景(为什么需要这个决策) 4. 决策(我们决定做什么) 5. 备选方案(考虑过哪些方案) 6. 影响(这个决策会改变什么) 7. 关联(与其他 ADR 的关系)
C4 模型示例 — 电商平台完整四层图
本文档提供电商平台的 C4 模型全四层 Mermaid 图例,可直接嵌入架构文档。
---
L1: System Context Diagram
graph TB
Customer["👤 顾客"]
Admin["👤 管理员"]
Logistics["🚚 物流系统"]
PaymentGateway["💳 支付网关"]
SMS["📱 短信服务"]
subgraph Platform["电商平台"]
OrderBC["订单上下文"]
PaymentBC["支付上下文"]
ProductBC["商品上下文"]
InventoryBC["库存上下文"]
end
Customer -->|"下订单"| OrderBC
Customer -->|"支付"| PaymentBC
Admin -->|"管理商品"| ProductBC
OrderBC -->|"发货通知"| Logistics
PaymentBC -->|"调用"| PaymentGateway
OrderBC -->|"验证库存"| InventoryBC
OrderBC -->|"短信通知"| SMSL2: Container Diagram — 订单上下文
graph TB
subgraph OrderContext["订单上下文"]
OrderAPI["订单 API\n(Spring Boot)"]
OrderDB[("订单数据库\n(PostgreSQL)")]
OrderCache["订单缓存\n(Redis)"]
OrderQueue["订单事件队列\n(RabbitMQ)"]
Worker["订单处理 Worker\n(Spring Boot)"]
end
WebApp["Web App\n(React)"]
MobileApp["移动 App\n(React Native)"]
WebApp -->|REST API| OrderAPI
MobileApp -->|REST API| OrderAPI
OrderAPI -->|读写| OrderDB
OrderAPI -->|缓存查询| OrderCache
OrderAPI -->|发布事件| OrderQueue
Worker -->|消费事件| OrderQueue
Worker --> OrderDB
OrderQueue -->|同步| PaymentContext["支付上下文"]
OrderQueue -->|通知| LogisticsL3: Component Diagram — 订单上下文的 COLA 四层
graph TB
subgraph Adapter["适配层"]
OrderController["OrderController"]
OrderDTO["OrderDTO"]
end
subgraph App["应用层"]
OrderAppService["OrderAppService"]
CreateOrderCmd["CreateOrderCommand"]
CancelOrderCmd["CancelOrderCommand"]
OrderQueryService["OrderQueryService"]
end
subgraph Domain["领域层"]
Order["Order (聚合根)"]
OrderItem["OrderItem (实体)"]
Money["Money (值对象)"]
OrderRepository["OrderRepository (接口)"]
OrderDomainService["OrderDomainService"]
OrderPaidEvent["OrderPaidEvent"]
end
subgraph Infra["基础设施层"]
JpaOrderRepo["JpaOrderRepository"]
EventPublisher["RabbitMqEventPublisher"]
end
OrderController --> OrderAppService
OrderController --> OrderQueryService
OrderAppService --> CreateOrderCmd
OrderAppService --> OrderRepository
OrderAppService --> OrderDomainService
Order --> OrderItem
Order --> Money
Order --> OrderPaidEvent
JpaOrderRepo -.->|implements| OrderRepository
EventPublisher --> OrderQueueL4: Code Diagram — 订单聚合内部结构
classDiagram
class Order {
-OrderId id
-OrderStatus status
-Money totalAmount
-List~OrderItem~ items
-CustomerId customerId
-Address shippingAddress
+pay() void
+cancel(String reason) void
+addItem(OrderItem) void
+removeItem(ProductId) void
+calculateTotal() Money
+canBePaid() boolean
}
class OrderItem {
-ProductId productId
-String productName
-Money unitPrice
-int quantity
+getSubtotal() Money
+updateQuantity(int) void
}
class Money {
-BigDecimal amount
-Currency currency
+add(Money) Money
+subtract(Money) Money
+multiply(BigDecimal) Money
+isGreaterThan(Money) boolean
}
class OrderStatus {
<<enumeration>>
PENDING_PAYMENT
PAID
SHIPPED
DELIVERED
CANCELLED
RETURNING
+canPay() boolean
+canCancel() boolean
+canShip() boolean
}
class OrderId {
-String value
+generate() OrderId
+fromString(String) OrderId
}
class OrderPaidEvent {
-OrderId orderId
-Money amount
-LocalDateTime paidAt
+occurredOn() LocalDateTime
}
Order "1" --> "*" OrderItem
Order --> Money
Order --> OrderId
Order --> OrderStatus
Order --> Address
Order ..> OrderPaidEvent : publishesADR 模板合集
提供 3 种 ADR 模板:标准版、轻量版、技术决策版。
---
模板一:标准版 ADR(推荐)
适用于大多数架构决策场景。
# ADR-{NNN}: {简短描述性标题}
## 状态
{Proposed / Accepted / Deprecated / Superseded by ADR-XXX}
## 背景
为什么需要做这个决策?当前面临什么问题或约束?
- 业务背景:...
- 技术背景:...
- 约束条件:...
## 决策
我们决定做什么?
- 具体方案:...
- 实施范围:...
## 备选方案
| 方案 | 优点 | 缺点 | 决定 |
|------|------|------|:----:|
| 方案 A | ... | ... | ✗ |
| 方案 B | ... | ... | ✗ |
| **方案 C** | ... | ... | ✓ |
## 决策理由
为什么选择这个方案?
1. ...
2. ...
## 影响
- 正面影响:...
- 负面影响:...
- 中性影响:...
## 关联 ADR
- ADR-{NNN}: {关联决策}
- ADR-{NNN}: {被替代的决策}模板二:轻量版 ADR
适用于小型决策或技术选型。
# ADR-{NNN}: {标题}
**状态**: {Proposed/Accepted/Deprecated}
**日期**: {YYYY-MM-DD}
**决策人**: {姓名}
**背景**: 一句话描述为什么需要这个决策。
**决策**: 我们决定采用 {方案}。
**理由**: {为什么选择这个方案}
**影响范围**: {哪些模块/团队受影响}模板三:技术方案 ADR
适用于详细技术方案评审。
# ADR-{NNN}: {技术方案标题}
## 状态
{Proposed / Accepted / Deprecated}
## 问题描述
{清晰描述要解决的技术问题}
## 方案对比
### 方案 A: {方案名称}
- **架构**: ...
- **关键技术**: ...
- **复杂度**: 高/中/低
- **维护成本**: 高/中/低
- **风险**: ...
### 方案 B: {方案名称}
- **架构**: ...
- **关键技术**: ...
- **复杂度**: 高/中/低
- **维护成本**: 高/中/低
- **风险**: ...
### 方案 C: {方案名称}
- **架构**: ...
- **关键技术**: ...
- **复杂度**: 高/中/低
- **维护成本**: 高/中/低
- **风险**: ...
## 选择决策
**选定方案**: {方案名称}
**评分对比**:
| 维度 | 方案 A | 方案 B | 方案 C |
|------|:------:|:------:|:------:|
| 业务匹配度 | 7/10 | 9/10 | 6/10 |
| 技术可行性 | 8/10 | 8/10 | 9/10 |
| 团队适配度 | 6/10 | 9/10 | 5/10 |
| 迁移成本 | 5/10 | 7/10 | 8/10 |
**理由**: ...
## 实施计划
1. {步骤 1}: {时间}
2. {步骤 2}: {时间}
3. {步骤 3}: {时间}
## 回退方案
{如果决策失败,如何回退}
## 关联
- ADR-{NNN}: {关联决策}选择指南
| 场景 | 推荐模板 |
|---|---|
| 重大架构决策(选架构、换 DB) | 标准版 |
| 日常技术选型(框架选择、库选择) | 轻量版 |
| 需跨团队评审的技术方案 | 技术方案版 |
| 快速记录(一人决策) | 轻量版 |
架构文档模板合集
提供 3 种不同用途的架构文档模板:完整版、轻量版、快速入门版。
---
模板一:完整架构文档(推荐)
适用于中大型项目,团队文档标准化。
# {项目名称} 架构文档
> 版本: v{版本号} | 最后更新: {YYYY-MM-DD} | 负责人: {姓名}
---
## 1. 架构概览
### 1.1 架构模式
- **架构**: {Layered / Onion / Hexagonal / Clean / COLA}
- **CQRS 级别**: {None / L1 / L2 / L3}
- **微服务拆分**: {单体 / 微服务}
### 1.2 架构图
> 嵌入 C4 L1(System Context)图
### 1.3 核心约束
- 领域层零框架依赖
- 依赖方向始终指向内层
- 聚合之间通过 ID 引用
- 跨聚合操作使用领域事件
## 2. 限界上下文
| 上下文 | 类型 | 职责 | 部署方式 |
|--------|------|------|:--------:|
| Order | 核心域 | 订单全生命周期管理 | 独立服务 |
| Payment | 核心域 | 支付处理与退款 | 独立服务 |
| Product | 支撑域 | 商品信息管理 | 独立服务 |
| Auth | 通用域 | 用户认证授权 | 共享库 |
### 上下文映射
> 嵌入 Context Map 图(Mermaid)
## 3. 分层规范
### 3.1 依赖方向
详见 `{项目名}/layer-dependencies.md`
### 3.2 层职责
| 层 | 允许 | 禁止 |
|---|------|------|
| Interface | 协议转换、参数校验 | 业务判断 |
| Application | 编排、事务、权限 | 业务 if/else |
| Domain | 业务规则、领域建模 | 框架依赖 |
| Infrastructure | 技术实现 | 业务逻辑 |
## 4. 技术栈
| 组件 | 技术 | 版本 | 用途 |
|------|------|:----:|------|
| 框架 | Spring Boot | 3.4.x | Web 服务 |
| ORM | MyBatis Plus | 3.5.x | 数据访问 |
| 数据库 | PostgreSQL | 16 | 持久化 |
| 缓存 | Redis | 7.x | 会话/缓存 |
| 消息队列 | RabbitMQ | 3.13 | 事件驱动 |
| 搜索引擎 | Elasticsearch | 8.x | 全文搜索 |
## 5. 部署架构
> 嵌入部署图(K8s / Docker Compose)
## 6. 架构决策记录(ADRs)
### ADR 索引
| ADR# | 标题 | 状态 | 日期 |
|------|------|:----:|:----:|
| 001 | 选择 COLA v5 架构 | 已采纳 | 2024-03-15 |
| 002 | CQRS L1 策略 | 已采纳 | 2024-03-20 |
| 003 | 事件中间件选型 | 已采纳 | 2024-03-25 |
### 完整 ADR
> 链接到 `adrs/ADR-{NNN}-{title}.md`
## 7. 安全架构
- 认证方式:JWT + OAuth2
- 授权模型:RBAC(按限界上下文分权)
- 数据加密:传输 TLS 1.3 / 存储 AES-256
- 审计日志:所有写操作记录
## 8. 运维手册
- 监控:Prometheus + Grafana
- 日志:ELK Stack
- 告警:PagerDuty
- 灾备:跨 AZ 部署 + 数据库主从
## 9. 架构评审 Checklist
- [ ] 依赖方向正确
- [ ] Domain 层零框架依赖
- [ ] 无循环依赖
- [ ] 聚合间 ID 引用
- [ ] 关键操作有领域事件
- [ ] ADR 记录完整
- [ ] 架构图与代码一致模板二:轻量架构文档
适用于小团队或快速迭代项目。
# {项目名称} 轻量架构文档
## 架构快照
- **模式**: ...
- **CQRS**: ...
- **关键技术**: ...
## 模块结构
> 项目目录树(核心模块)
## 技术栈清单
> 技术选型表
## 关键 ADR
- ADR-001: ...
- ADR-002: ...
## 架构图
> 嵌入 C4 L1 图模板三:新成员快速入门文档
适用于团队新人 onboarding。
# {项目名称} 架构快速入门
## 五分钟理解架构
- 我们用了什么架构模式?
- 代码模块怎么组织的?
- 核心业务链路是什么?
## 开发环境搭建
1. clone 仓库
2. 配置本地环境
3. 启动项目
## 提交代码流程
- 分支策略
- 提交流程
- Code Review 要点
## 常用文档链接
- 架构文档
- API 文档
- ADR 记录
- 数据库设计
## 找谁帮忙
| 领域 | 负责人 |
|------|--------|
| 订单 | @张三 |
| 支付 | @李四 |架构文档工具链
推荐的工具和最佳实践,帮助团队高效维护架构文档。
---
1. 图表工具
Structurizr(推荐)
- 类型: C4 模型专用工具
- 特点: 代码定义架构图、版本控制友好、支持多视图
- 适用: 中大型项目,需要 C4 模型全量维护
- 地址: structurizr.com
// Structurizr DSL 示例
workspace {
model {
user = person "顾客" "系统用户"
softwareSystem = softwareSystem "电商平台" "在线购物系统"
user -> softwareSystem "下订单"
}
views {
systemContext softwareSystem {
include *
}
}
}Mermaid(轻量)
- 类型: Markdown 内嵌图表
- 特点: 无额外工具、直接写在 Markdown 中
- 适用: 小型项目,文档与代码同仓库
- 支持: GitHub / GitLab / 多数 Markdown 编辑器
PlantUML(开发者友好)
- 类型: 代码驱动图表
- 特点: 丰富的图类型(时序、活动、组件、类图)
- 适用: 需要多种 UML 图型的项目
- 集成: VS Code 插件、CI/CD 自动渲染
draw.io / diagrams.net
- 类型: 可视化拖拽工具
- 特点: 操作直观、开源、可嵌入 Confluence
- 适用: 快速原型、非技术团队合作
2. ADR 管理工具
ADR Tools(CLI)
- 特点: 命令行创建和管理 ADR
- 安装:
npm install -g adr-tools - 用法:
adr new "选择 COLA 架构"
adr list
adr supersede 4 6 # ADR-4 被 ADR-6 替代Log4brains
- 特点: ADR Web 界面 + 自动索引
- 安装:
npm init log4brains - 适用: 团队需要可视化的 ADR 浏览
3. 文档平台
| 平台 | 适用场景 | 优势 |
|---|---|---|
| GitHub Wiki | 开发者团队 | 代码同仓库,PR 驱动文档变更 |
| Confluence | 大型团队 | 富文本编辑,跨团队可见 |
| Notion | 中等团队 | 灵活排版,数据库视图 |
| 语雀 | 国内团队 | 中文友好,知识库管理 |
| MkDocs | 技术团队 | Markdown 驱动,自动部署 |
4. 自动化检查
ArchUnit
- 用途: Java 层依赖方向自动检查
- 集成: JUnit 测试 + CI/CD
@Test
void testLayerDependencies() {
layeredArchitecture()
.layer("Adapter").definedBy("..adapter..")
.layer("App").definedBy("..app..")
.layer("Domain").definedBy("..domain..")
.layer("Infrastructure").definedBy("..infrastructure..")
.whereLayer("Adapter").mayOnlyBeAccessedByLayers("App")
.whereLayer("App").mayOnlyBeAccessedByLayers("Adapter")
.whereLayer("Domain").mayOnlyBeAccessedByLayers("App", "Infrastructure")
.check(importedClasses);
}ADR 合规检查
- ADR 必须与代码一致
- 定期 CI 检查 ADR 索引 vs 实际代码实现
- 架构变更必须有对应的 ADR 更新
5. 推荐工作流
代码变更 → 影响架构?→ 是 → 更新 ADR / 更新 C4 图 / 更新架构文档
↓
PR 评审包含文档变更
↓
合并后自动部署文档站文档与代码同步策略
| 策略 | 适用 | 执行方式 |
|---|---|---|
| PR 强制关联 | 严格团队 | PR 模板含文档更新确认框 |
| 文档 AI 检测 | 自动化 | CI 检测代码架构变更 → 自动提示更新文档 |
| 定期人工审查 | 宽松团队 | 每 sprint 审查一次架构文档 |
团队沟通模板
架构文档不仅仅是技术文档,还包括团队之间的沟通模板。
---
1. 架构评审请求模板
用于发起架构评审。
# 架构评审请求
## 基本信息
- **发起人**: {姓名}
- **日期**: {YYYY-MM-DD}
- **评审范围**: {模块/服务名称}
## 变更内容
{简要描述要评审的架构变更}
## 前置材料
- [ ] 架构变更说明(本请求)
- [ ] ADR 草案(链接)
- [ ] C4 图(L1/L2 变更部分)
- [ ] 受影响模块清单
## 评审要点
1. {要点 1}
2. {要点 2}
## 期望评审人
- @{架构师}
- @{相关模块负责人}2. 架构变更通知模板
架构变更通过后通知团队。
## 🔔 架构变更通知
**变更**: {简洁描述}
**ADR**: ADR-{NNN}
**生效日期**: {YYYY-MM-DD}
**影响范围**: {清单}
### 变更内容
{详细描述}
### 开发者需要做什么
- {行动项 1}
- {行动项 2}
### 回退方案
{如果出问题怎么办}
### 问题反馈
请回复此帖子或联系 @{负责人}3. 架构文档 Review 模板
定期审查架构文档的更新情况。
# 架构文档 Review - {月份}
## 文档完整性
| 文档 | 最新版本 | 最后更新 | 状态 |
|------|---------|:--------:|:----:|
| 架构概览 | v2.3 | 2024-03-15 | ✅ 最新 |
| ADR 索引 | v1.8 | 2024-02-28 | ⚠️ 需更新 |
| C4 图 | v2.1 | 2024-01-20 | ❌ 过期 |
## 过期项详情
1. ADR 索引缺少 ADR-005、ADR-006
2. C4 L2 图与实际部署不一致(新增了 Redis 集群)
## 行动计划
| 任务 | 负责人 | 截止日期 |
|------|--------|:--------:|
| 补充 ADR-005/006 | @张三 | 2024-04-01 |
| 更新 C4 L2 图 | @李四 | 2024-04-05 |4. Onboarding 文档清单
新成员需要阅读的架构文档。
## 新成员架构文档阅读清单
### 第一天
1. [ ] 架构概览文档(30 分钟)
2. [ ] C4 L1 系统上下文图(15 分钟)
3. [ ] 核心业务流文档(30 分钟)
### 第一周
4. [ ] 当前服务 C4 L2/L3 图(1 小时)
5. [ ] 关键 ADR(3-5 个主要决策)
6. [ ] 开发环境搭建文档
### 第一个月
7. [ ] 全部 ADR 索引 + 重要 ADR 详情
8. [ ] C4 L4 代码级理解
9. [ ] 参与一次架构评审架构决策日志(ADL)格式
架构决策日志(Architecture Decision Log, ADL)是 ADR 的索引和管理系统。
本文档提供 ADL 的创建、维护和自动化方案。
---
1. ADL 索引表
# 架构决策日志(ADL)
> 最后更新: {YYYY-MM-DD} | 总 ADR 数: {N}
## 活跃决策
| ADR# | 标题 | 状态 | 采纳日期 | 负责人 | 标签 |
|------|------|:----:|:--------:|:------:|:----:|
| 001 | 选择 COLA v5 架构 | ✅ 已采纳 | 2024-03-15 | @张三 | 架构选型 |
| 002 | CQRS L1 策略 | ✅ 已采纳 | 2024-03-20 | @李四 | CQRS |
| 003 | 事件中间件选型 | ✅ 已采纳 | 2024-03-25 | @王五 | 技术选型 |
| 004 | MySQL 选择 | ❌ 已废弃 | 2024-02-01 | @张三 | DB选型 |
| 005 | 单体 vs 微服务 | ✅ 已采纳 | 2024-04-01 | @赵六 | 架构 |
## 已废弃/已替代
| ADR# | 标题 | 被替代 | 替代者为 |
|------|------|:------:|:--------:|
| 004 | MySQL 选择 | ADR-006 | PostgreSQL 选型 |2. ADR 目录结构
docs/
└── adrs/
├── README.md # ADL 索引(自动生成)
├── ADR-001-choose-cola.md
├── ADR-002-cqrs-l1-strategy.md
├── ADR-003-event-middleware.md
├── ADR-004-deprecated-mysql.md
└── ADR-005-monolith-vs-microservices.md文件命名规范
- 格式:
ADR-{NNN}-{kebab-case-title}.md - NNN: 从 001 开始的三位编号
- 标题: 英文 kebab-case,简短描述
3. ADL 自动化维护
GitHub Actions 示例
name: Update ADL Index
on:
push:
paths:
- 'docs/adrs/**'
jobs:
update-adl:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Generate ADL Index
run: |
echo "# 架构决策日志" > docs/adrs/README.md
echo "" >> docs/adrs/README.md
echo "| ADR# | 标题 | 状态 | 日期 |" >> docs/adrs/README.md
echo "|------|------|:----:|:----:|" >> docs/adrs/README.md
for f in docs/adrs/ADR-*.md; do
title=$(head -1 "$f" | sed 's/# ADR-...: //')
status=$(grep -A1 "^## 状态" "$f" | tail -1)
num=$(echo "$f" | grep -oP 'ADR-\K\d+')
echo "| $num | $title | $status | - |" >> docs/adrs/README.md
done
mv docs/adrs/README.md docs/adrs/README.md
- name: Commit changes
uses: stefanzweifel/git-auto-commit-action@v44. ADL 最佳实践
| 实践 | 说明 |
|---|---|
| 编号唯一 | ADR 编号全局唯一,废弃后不重用 |
| 索引自动化 | CI/CD 自动生成 ADL 索引 |
| 标签分类 | 为 ADR 打标签(架构选型/DB选型/安全决策) |
| 定期审查 | 每季度审查 ADL,标记过时的决策 |
| PR 关联 | 代码 PR 关联相关 ADR |
5. ADL 状态机
→ Accepted(已采纳)
Proposed ──────┤ Deprecated(已废弃)
↓ → Rejected(已拒绝) ↓
修改后重新提交 Superseded(已替代)
↓
保留引用领域模型文档化模式
本文档提供领域模型文档化的最佳实践和模板。
---
1. 聚合文档模板
## 聚合:{聚合名称}
### 概述
{一句话描述这个聚合负责什么业务}
### 聚合根
- **类名**: {ClassName}
- **标识**: {IdType}
- **业务标识**: {业务主键,如订单号}
### 实体
| 实体 | 父聚合根 | 生命周期 |
|------|---------|---------|
| {Entity1} | {AggregateRoot} | 随聚合根 |
### 值对象
| 值对象 | 包含字段 | 不可变 |
|--------|---------|:------:|
| {ValueObject1} | {field1}, {field2} | ✅ |
### 领域事件
| 事件 | 触发条件 | 消费者 |
|------|---------|--------|
| {Event1} | {条件} | {谁处理} |
### 业务不变式(Invariants)
1. {不变式 1}
2. {不变式 2}2. 限界上下文文档模板
## 限界上下文:{上下文名称}
### 基本信息
- **类型**: {核心域 / 支撑域 / 通用域}
- **负责人**: {团队名称}
- **代码仓库**: {repository URL}
### 领域模型概览
> 嵌入聚合关系图(Mermaid)
graph LR Aggregate1["聚合1\n(聚合根)"] Aggregate2["聚合2\n(聚合根)"] Aggregate1 -->|"ID 引用"| Aggregate2
### 聚合清单
| 聚合 | 聚合根 | 说明 |
|------|--------|------|
| {Aggregate1} | {Class1} | {说明} |
### 上下文映射
| 上游上下文 | 下游 | 关系类型 |
|-----------|------|---------|
| {上游BC} | {下游BC} | ACL/OHS/Partnership |
### 领域服务
| 服务名 | 职责 | 位置 |
|--------|------|:----:|
| {Service1} | {职责} | Domain 层 |
### 仓储接口
| 仓库 | 对应聚合 | 主要查询 |
|------|---------|---------|
| {Repository1} | {Aggregate1} | findByXXX, save |3. 文档化最佳实践
| 实践 | 反例 | 正例 |
|---|---|---|
| 用业务语言 | "Order 有 status 字段" | "订单状态决定了用户可以执行的操作" |
| 说明业务规则 | "pay() 方法更新状态" | "只有 DRAFT 状态的订单才能支付,支付后状态变为 PAID" |
| 明确聚合边界 | "Order 引用 Customer 对象" | "Order 通过 customerId 引用 Customer 聚合" |
| 记录领域事件 | 不写事件触发条件 | "当订单支付成功时发布 OrderPaidEvent" |
| 解释值对象 | "Money 是 BigDecimal" | "Money 封装金额计算(加、减、乘、比较),保证金额精确计算" |
4. 领域模型变更记录
# {聚合名称} 领域模型变更日志
| 日期 | 版本 | 变更内容 | 原因 | ADR |
|:----:|:----:|---------|------|:---:|
| 2024-03-15 | v2.0 | Order 增加 shippingAddress 字段 | 支持多地址发货 | ADR-012 |
| 2024-02-01 | v1.5 | OrderItem 从实体改为值对象 | 订单项不可修改 | ADR-008 |API 文档化模式
DDD 架构下的 API 文档规范,面向 CQRS 模式的命令/查询分离。
---
1. 命令 API 文档模板
## POST /api/v1/{resource}/{action}
**命令**: {CommandName}
**ID 支持**: {幂等键}
### 请求体{ "idempotentKey": "{唯一请求 ID}", "data": { ... } }
### 响应{ "code": 0, "message": "success", "data": { "id": "{资源 ID}", "status": "{结果状态}" } }
### 业务规则
1. {规则 1}
2. {规则 2}
### 领域事件
- 成功触发:{EventName}2. 查询 API 文档模板
## GET /api/v1/{resource}s
**查询**: {QueryName}
**CQRS 模型**: {QueryModel}
### 参数
| 参数 | 类型 | 必填 | 说明 |
|------|:----:|:----:|------|
| {param1} | {type} | 是 | {说明} |
### 响应{ "code": 0, "data": { "records": [], "total": 100, "page": 1, "pageSize": 20 } }
### 说明
- 查询不走领域模型,直接从读模型返回
- 不触发领域事件
- 不改变系统状态3. OpenAPI 规范参考
openapi: 3.0.3
info:
title: 电商平台 API
version: 1.0.0
paths:
/api/v1/orders:
post:
summary: 创建订单(命令)
operationId: createOrder
x-cqrs-type: command
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/CreateOrderRequest'
responses:
'200':
description: 订单创建成功
content:
application/json:
schema:
$ref: '#/components/schemas/OrderCreatedResponse'
components:
schemas:
CreateOrderRequest:
type: object
required:
- customerId
- items
properties:
customerId:
type: string
description: 客户 ID
items:
type: array
items:
$ref: '#/components/schemas/OrderItem'
OrderCreatedResponse:
type: object
properties:
orderId:
type: string
status:
type: string4. API 文档章节结构
API 文档标准章节:
1. {资源} Overview
- 所属限界上下文
- CQRS 类型(命令/查询)
2. Endpoints
- 命令类(POST/PUT/DELETE)
- 查询类(GET)
3. 请求/响应格式
- 统一响应格式
- 错误码说明
4. 业务规则
- 命令的业务规则(哪些状态可操作)
- 查询的过滤/排序/分页规则
5. 限流策略
- 命令 API:较低 QPS
- 查询 API:较高 QPS
6. 安全要求
- 认证方式
- 权限要求5. DDD 与非 DDD API 文档差异
| 维度 | 传统 API 文档 | DDD API 文档 |
|---|---|---|
| 关注点 | HTTP 端点 + 参数 | 业务能力 + 领域语义 |
| 命令描述 | "POST /orders 创建订单" | "下单命令:创建新订单,触发订单已创建事件" |
| 参数说明 | "status: 订单状态" | "订单状态:业务状态机,包含 DRAFT→PAID→SHIPPED 等" |
| 事件关联 | 无 | "成功触发 OrderCreatedEvent,由库存消费" |
架构文档反模式
本文档列出 DDD 架构文档中的常见反模式、改进对比和禁忌清单。
---
反模式一:死文档(写一次就过期)
症状
- 文档创建后从未更新
- 代码已经重构多次,文档还是最初版本
- 新成员只能看代码,不能信文档
改进对比
| 维度 | 反模式 | 推荐做法 |
|---|---|---|
| 更新频率 | 写一次,永不更新 | PR 时必须同步更新文档 |
| 关联方式 | 文档和代码独立 | 文档在代码仓库中,变更时一起 PR |
| 验证方式 | 无 | CI 检查 ADR 与代码的一致性 |
禁忌清单
- ❌ 把文档放在和代码无关的独立 Wiki 中(容易忘记更新)
- ❌ 文档只有 PDF 版本(无法版本控制和 diff)
- ❌ 文档没有版本号或最后更新时间
反模式二:假图(图不反映真实架构)
症状
- C4 图里的容器数和实际部署不一致
- 图看起来很美,但跟代码结构对不上
- 图是用 Visio 手动画的,没法自动验证
改进对比
| 维度 | 反模式 | 推荐做法 |
|---|---|---|
| 图表工具 | Visio/Keynote 手绘 | Mermaid/Structurizr 代码驱动 |
| 更新方式 | 每次手动拖拽 | 改了代码就是改了图 |
| 验证方式 | 人工核对 | ArchUnit + CI 验证 |
禁忌清单
- ❌ 使用不可版本控制的二进制图文件(.vsdx/.drawio 不 diff)
- ❌ 一张图包含所有细节(超过 7 个节点)
- ❌ 图的颜色/样式没有统一的规范
反模式三:ADR 不写理由
症状
- ADR 只写了"选了什么",没写"为什么"
- 几个月后回看 ADR,完全记不得当时的考虑
- 新人问"为什么这里用 RabbitMQ 而不是 Kafka",没人能答
改进对比
| 维度 | 反模式 | 推荐做法 |
|---|---|---|
| 内容 | "选了 RabbitMQ" | "选了 RabbitMQ:因为团队已经部署、运维熟悉、QPS < 5000 足够" |
| 备选方案 | 无 | 至少列出 2-3 个备选 + 优缺点 |
| 决策背景 | 无 | 写明当时的业务场景和约束 |
禁忌清单
- ❌ ADR 不写备选方案
- ❌ ADR 只有标题,没有背景和影响分析
- ❌ 决策理由用"大家都觉得"、"业界主流"等空话
反模式四:过度文档(写太多没人读)
症状
- 架构文档 100 页以上,没人完整读过
- 文档包含太多实现细节(每个方法的参数说明)
- 新成员 onboarding 时被告知"看看文档",但看了也没用
改进对比
| 维度 | 反模式 | 推荐做法 |
|---|---|---|
| 粒度 | 每个方法的参数都写 | 写聚合边界、关键业务规则、架构决策 |
| 长度 | > 50 页 | 核心文档 < 10 页,详细信息分到子文档 |
| 用途 | 力图覆盖一切 | 聚焦"别人需要知道什么才能开发" |
禁忌清单
- ❌ 把代码注释复制到文档中
- ❌ 文档包含敏感的凭证、IP、配置
- ❌ 文档沦为"为了有文档而写文档"
反模式五:无图(只有文字描述)
症状
- 架构文档纯文字,没有一张图
- "订单模块调用支付模块"这种关系全靠文字描述
- 新人看完文档还得自己画图才能理解
改进对比
| 维度 | 反模式 | 推荐做法 |
|---|---|---|
| 顶层架构 | 文字描述 | C4 L1 System Context 图 |
| 服务关系 | "A 服务通过 RPC 调用 B 服务" | C4 L2 Container 图 |
| 模块结构 | 目录列表 | C4 L3 Component 图 |
禁忌清单
- ❌ 只有文字没有图的架构文档
- ❌ 图不在文档中,而是"麻烦你去看 X 文档里的图"
- ❌ 图太大/太小,导致无法阅读
架构文档 FAQ(深入篇)
边缘场景、工具兼容、安全合规相关的深度问题。
---
Q1: 微服务架构下 ADR 归哪个团队维护?
每个微服务独立维护自己的 ADR,同时在架构文档中维护一个全局 ADR 索引。
- 各服务 ADR:在各自代码仓库的
docs/adrs/下 - 全局 ADL:在架构文档中引用各服务的 ADR 链接
- 跨服务决策(如服务间协议、消息格式)放在 Team-level 的 ADR
Q2: C4 图需要覆盖所有限界上下文吗?
不需要。C4 图的推荐粒度:
- L1:覆盖全系统(所有限界上下文)
- L2-L4:按限界上下文或微服务独立维护
- 每个图控制在 5-7 个节点内,复杂系统应该分层展开
Q3: 遗留系统没有架构文档,从哪里开始?
渐进式文档化策略: 1. 先画当前实际部署的 C4 L1 图("AS-IS") 2. 识别关键 ADR(最大的 3-5 个历史决策) 3. 只为核心限界上下文写 L2/L3 图 4. 每 sprint 完善一部分 5. 目标:从 AS-IS 到 TO-BE 的演进路线图
Q4: 架构文档放在哪里最合适?
| 存储方式 | 适用 | 不适用 |
|---|---|---|
代码仓库 docs/ | 开发团队维护 | 产品/业务需要访问 |
| Wiki(Confluence/语雀) | 跨团队可见 | 文档与代码脱节 |
| 文档站(MkDocs/GitBook) | 公开文档 | 非技术团队编辑 |
| 推荐:代码仓库 + Wiki 双同步 | 开发者 PR 维护,定期同步到 Wiki | 需要额外 CI 步骤 |
Q5: 如何处理被废弃的 ADR?
保留但标记。废弃的 ADR 不应删除:
- 状态标记为
Deprecated或Superseded by ADR-XXX - ADL 索引中保留,但"活跃决策"表中不显示
- 已废弃的 ADR 从 ADR 编号序列中跳过(不重用编号)
- 通过 ADL 索引可以追溯"为什么这个决策不再有效"
Q6: C4 和 UML 的关系是什么?
| 维度 | C4 模型 | UML |
|---|---|---|
| 定位 | 架构级沟通 | 设计级细节 |
| 受众 | 全团队(含非技术) | 开发者 |
| 粒度 | 粗到细 4 层 | 细粒度 |
| 自动检查 | 困难 | ArchUnit 支持 |
| 推荐做法 | C4 用于架构文档 | UML 用于设计文档 |
Q7: 架构文档需要包含性能指标吗?
需要,但作为参考而非承诺。推荐包含:
- 当前性能基线(P99 延迟、QPS)
- 架构决策对性能的影响(如 CQRS L2 的同步延迟)
- 容量规划信息(预估增长、扩展策略)
- 不建议包含:精确的 SLO(应放在运维监控文档)
Q8: 架构文档如何保护敏感信息?
| 信息类型 | 保护方式 |
|---|---|
| 内网 IP/域名 | 使用占位符(如 {service-name}:{port}) |
| 数据库密码/凭证 | 绝不写入文档 |
| 安全组规则 | 使用 "基于角色的访问控制" 描述替代具体规则 |
| 部署拓扑 | 敏感拓扑不使用公开文档 |