🚀 快速安装

复制以下命令并运行,立即安装此 Skill:

npx skills add https://github.com/wshobson/agents --skill architecture-decision-records

💡 提示:需要 Node.js 和 NPM

架构决策记录

创建、维护和管理架构决策记录(ADR)的综合模式,用于记录重要技术决策的背景和理由。

何时使用此技能

  • 做出重要的架构决策时
  • 记录技术选型的理由
  • 记录设计的权衡取舍
  • 帮助新团队成员快速了解历史
  • 回顾过去的决策
  • 建立决策流程

核心概念

1. 什么是 ADR?

一份架构决策记录包含:

  • 背景:为何需要做此决策
  • 决策:我们决定做什么
  • 后果:决策带来的影响

2. 何时编写 ADR

编写 ADR 跳过 ADR
引入新的框架 小版本升级
数据库技术选型 修复 Bug
API 设计模式 实现细节
安全架构 日常维护
集成模式 配置变更

3. ADR 生命周期

提议中 → 已接受 → 已弃用 → 已被取代
           已拒绝

模板

模板 1:标准 ADR (MADR 格式)

# ADR-0001:采用 PostgreSQL 作为主数据库

## 状态

已接受

## 背景

我们需要为新的电商平台选择一个主数据库。该系统将处理:

- 约 10,000 并发用户
- 包含层级分类的复杂商品目录
- 订单和支付的事务处理
- 商品的全文搜索
- 门店定位的地理空间查询

团队有 MySQL、PostgreSQL 和 MongoDB 的使用经验。对于金融交易,我们需要 ACID 合规性。

## 决策驱动因素

- **必须满足 ACID 合规性** 用于支付处理
- **必须支持复杂查询** 用于报表
- **最好支持全文搜索** 以减少基础设施复杂性
- **最好有良好的 JSON 支持** 用于灵活的产品属性
- **团队熟悉度** 能减少上手时间

## 考虑的选项

### 选项 1:PostgreSQL

- **优点**:符合 ACID,优秀的 JSON 支持 (JSONB),内置全文搜索,PostGIS 用于地理空间,团队有经验
- **缺点**:复制设置比 MySQL 稍复杂

### 选项 2:MySQL

- **优点**:团队非常熟悉,复制简单,社区庞大
- **缺点**:JSON 支持较弱,无内置全文搜索(需要 Elasticsearch),无内置地理空间(需要扩展)

### 选项 3:MongoDB

- **优点**:灵活的模式,原生 JSON,水平扩展
- **缺点**:(决策时)不支持多文档事务的 ACID,团队经验有限,需要严谨的模式设计

## 决策

我们将采用 **PostgreSQL 15** 作为我们的主数据库。

## 理由

PostgreSQL 在以下方面提供了最佳平衡:

1. **ACID 合规性** 对电商交易至关重要
2. **内置功能**(全文搜索、JSONB、PostGIS)减少了基础设施复杂性
3. **团队熟悉 SQL 数据库**,降低了学习曲线
4. **成熟的生态系统**,拥有优秀的工具和社区支持

复制方面稍复杂的缺点,远比不上减少额外服务(无需单独的 Elasticsearch)带来的好处。

## 后果

### 正面

- 单个数据库处理事务、搜索和地理空间查询
- 降低了运维复杂性(管理的服务更少)
- 为财务数据提供强一致性保证
- 团队可以充分利用现有的 SQL 经验

### 负面

- 需要学习 PostgreSQL 特有的功能(JSONB、全文搜索语法)
- 垂直扩展限制可能需要更早地引入只读副本
- 部分团队成员需要接受 PostgreSQL 专项培训

### 风险

- 全文搜索可能不如专用搜索引擎扩展性好
- 缓解措施:设计上考虑未来按需添加 Elasticsearch 的可能性

## 实施注意事项

- 对于灵活的产品属性,使用 JSONB 类型
- 使用 PgBouncer 实现连接池
- 为只读副本设置流复制
- 使用 pg_trgm 扩展实现模糊搜索

## 相关决策

- ADR-0002:缓存策略(Redis)- 与数据库选型互补
- ADR-0005:搜索架构 - 如果需要 Elasticsearch,可能会取代此决策

## 参考资料

- [PostgreSQL JSON 文档](https://www.postgresql.org/docs/current/datatype-json.html)
- [PostgreSQL 全文搜索](https://www.postgresql.org/docs/current/textsearch.html)
- 内部资料:`/docs/benchmarks/database-comparison.md` 中的性能基准测试

模板 2:轻量级 ADR

# ADR-0012:前端开发采用 TypeScript

**状态**:已接受
**日期**:2024-01-15
**决策者**:@alice, @bob, @charlie

## 背景

我们的 React 代码库已增长到 50 多个组件,并且与属性类型不匹配和未定义错误相关的错误报告越来越多。PropTypes 仅提供运行时检查。

## 决策

在所有新前端代码中采用 TypeScript。逐步迁移现有代码。

## 后果

**好处**:在编译时捕获类型错误,更好的 IDE 支持,代码自文档化。

**坏处**:团队的学习曲线,初期速度放缓,构建复杂性增加。

**缓解措施**:举办 TypeScript 培训,允许通过设置 `allowJs: true` 逐步采用。

模板 3:Y 陈述格式

# ADR-0015:API 网关选型

**构建微服务架构** 的背景下,
面对 **集中式 API 管理、身份验证和速率限制的需求**我们决定采用 **Kong Gateway**而非 **AWS API Gateway 和自定义 Nginx 方案**以实现 **厂商无关性、插件可扩展性和团队对 Lua 的熟悉度**接受 **需要自行管理 Kong 基础设施** 的事实。

模板 4:弃用 ADR

# ADR-0020:弃用 MongoDB,改用 PostgreSQL

## 状态

已接受(取代 ADR-0003)

## 背景

ADR-0003(2021 年)因当时需要模式灵活性而选择 MongoDB 用于用户档案存储。自那以后:

- MongoDB 的多文档事务在我们的用例中仍然存在问题
- 我们的模式已经稳定,很少变化
- 我们现在从其他服务中获得了 PostgreSQL 的专业知识
- 维护两个数据库增加了运维负担

## 决策

弃用 MongoDB,将用户档案迁移至 PostgreSQL。

## 迁移计划

1. **第一阶段**(第 1-2 周):创建 PostgreSQL 模式,启用双写
2. **第二阶段**(第 3-4 周):回填历史数据,验证一致性
3. **第三阶段**(第 5 周):将读操作切换到 PostgreSQL,进行监控
4. **第四阶段**(第 6 周):移除 MongoDB 写操作,下线 MongoDB

## 后果

### 正面

- 单一数据库技术减少了运维复杂性
- 为用户数据提供 ACID 事务
- 团队可以专注于 PostgreSQL 专业技能

### 负面

- 迁移工作量(约 4 周)
- 迁移过程中数据问题的风险
- 失去部分模式灵活性

## 经验教训

从 ADR-0003 的经验中记录:

- 模式灵活性的好处被高估了
- 多数据库的运维成本被低估了
- 在技术决策中应考虑长期维护因素

模板 5:意见征询 (RFC) 风格

# RFC-0025:订单管理采用事件溯源

## 摘要

提议在订单管理领域采用事件溯源模式,以提高可审计性、支持时间查询和业务分析。

## 动机

当前面临的挑战:

1. 审计需求需要完整的订单历史
2. 无法查询“在时间点 X 的订单状态”
3. 分析团队需要事件流来构建实时仪表盘
4. 为客服重建订单状态需要手动操作

## 详细设计

### 事件存储

OrderCreated { orderId, customerId, items[], timestamp }
OrderItemAdded { orderId, item, timestamp }
OrderItemRemoved { orderId, itemId, timestamp }
PaymentReceived { orderId, amount, paymentId, timestamp }
OrderShipped { orderId, trackingNumber, timestamp }

### 投影(视图)

- **CurrentOrderState**:用于查询的物化视图
- **OrderHistory**:用于审计的完整时间线
- **DailyOrderMetrics**:用于分析的聚合数据

### 技术选型

- 事件存储:EventStoreDB(专为事件溯源设计,支持投影)
- 考虑的替代方案:Kafka + 自定义投影服务

## 缺点

- 团队的学习曲线
- 相比 CRUD 增加了复杂性
- 需要谨慎设计事件(存储后不可变)
- 存储增长(事件永不删除)

## 替代方案

1. **审计表**:更简单,但无法支持时间查询
2. **基于现有数据库的变更数据捕获**:复杂,且不改变数据模型
3. **混合模式**:仅对订单状态变更采用事件溯源

## 待解决的问题

- [ ] 事件模式版本控制策略
- [ ] 事件的保留策略
- [ ] 用于性能的快照频率

## 实施计划

1. 用单一订单类型进行原型验证(2 周)
2. 团队事件溯源培训(1 周)
3. 全面实施和迁移(4 周)
4. 监控和优化(持续进行)

## 参考资料

- [Martin Fowler 论事件溯源](https://martinfowler.com/eaaDev/EventSourcing.html)
- [EventStoreDB 文档](https://www.eventstore.com/docs)

ADR 管理

目录结构

docs/
├── adr/
│   ├── README.md           # 索引和指南
│   ├── template.md         # 团队的 ADR 模板
│   ├── 0001-use-postgresql.md
│   ├── 0002-caching-strategy.md
│   ├── 0003-mongodb-user-profiles.md  # [已弃用]
│   └── 0020-deprecate-mongodb.md      # 取代 0003

ADR 索引 (README.md)

# 架构决策记录

此目录包含 [项目名称] 的架构决策记录(ADR)。

## 索引

| ADR 编号                         | 标题                                 | 状态       | 日期       |
| ------------------------------------- | ---------------------------------- | ---------- | ---------- |
| [0001](0001-use-postgresql.md)        | 采用 PostgreSQL 作为主数据库        | 已接受     | 2024-01-10 |
| [0002](0002-caching-strategy.md)      | 基于 Redis 的缓存策略                | 已接受     | 2024-01-12 |
| [0003](0003-mongodb-user-profiles.md) | 用户档案采用 MongoDB                 | 已弃用     | 2023-06-15 |
| [0020](0020-deprecate-mongodb.md)     | 弃用 MongoDB                         | 已接受     | 2024-01-15 |

## 创建新的 ADR

1. 复制 `template.md``NNNN-标题-用短横线连接.md`
2. 填写模板
3. 提交 PR 进行评审
4. 批准后更新此索引

## ADR 状态

- **提议中**:正在讨论中
- **已接受**:已做出决策,正在实施
- **已弃用**:不再相关
- **已被取代**:已被另一个 ADR 替换
- **已拒绝**:考虑过但未采纳

自动化工具 (adr-tools)

# 安装 adr-tools
brew install adr-tools

# 初始化 ADR 目录
adr init docs/adr

# 创建新的 ADR
adr new "采用 PostgreSQL 作为主数据库"

# 取代一个 ADR
adr new -s 3 "弃用 MongoDB,改用 PostgreSQL"

# 生成目录
adr generate toc > docs/adr/README.md

# 链接相关的 ADR
adr link 2 "补充" 1 "被补充"

评审流程

## ADR 评审清单

### 提交前

- [ ] 背景清晰地解释了问题
- [ ] 考虑了所有可行的选项
- [ ] 优缺点平衡且诚实
- [ ] 记录了(正面和负面的)后果
- [ ] 链接了相关的 ADR

### 评审期间

- [ ] 至少有 2 名高级工程师评审过
- [ ] 咨询了受影响的团队
- [ ] 考虑了安全影响
- [ ] 记录了成本影响
- [ ] 评估了可逆性

### 接受后

- [ ] 更新了 ADR 索引
- [ ] 通知了团队
- [ ] 创建了实施相关的任务
- [ ] 更新了相关文档

最佳实践

应该做的

  • 尽早编写 ADR – 在开始实施之前
  • 保持简短 – 最多 1-2 页
  • 诚实地对待权衡 – 包括真正的缺点
  • 链接相关决策 – 构建决策关系图
  • 更新状态 – 当被取代时标记为弃用

避免做的

  • 不要修改已接受的 ADR – 编写新的来取代它
  • 不要跳过背景描述 – 未来的读者需要了解来龙去脉
  • 不要隐藏失败 – 被拒绝的决策也很有价值
  • 不要含糊其辞 – 决策和后果要具体
  • 不要忘记实施 – 没有行动的 ADR 是浪费

📄 原始文档

完整文档(英文):

https://skills.sh/wshobson/agents/architecture-decision-records

💡 提示:点击上方链接查看 skills.sh 原始英文文档,方便对照翻译。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。