🚀 快速安装
复制以下命令并运行,立即安装此 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 原始英文文档,方便对照翻译。
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

评论(0)