上传文件至 /

This commit is contained in:
NoelOrin 2026-09-18 06:27:47 +00:00
commit 44a6a6aaf6
1 changed files with 173 additions and 0 deletions

173
SKILL.md Normal file
View File

@ -0,0 +1,173 @@
---
name: software-design-patterns
description: Use when code structure is under pressure — growing if/switch branches, scattered status checks, tight coupling to third-party SDKs, unclear layering or transaction boundaries, extensibility demands, domain modeling, or cross-service reliability (dual writes, retries, sagas, idempotency). Guides selecting, rejecting, and combining GoF, enterprise, DDD, and distributed-system patterns by evidence, and recommends keeping the code simple when the pressure is unproven. Trigger on 重构、解耦、架构评审、扩展点、状态机、双写一致性、重试熔断、CQRS requests even if the user never says "设计模式".
---
# 软件设计模式:选择、拒绝与组合
参考文件是设计决策记录,不是名词解释。按"压力 → 候选 → 排除"推进,不要从模式名反推需求。
## 核心原则
1. **先识别变化点**:什么在变?变化频率?是否已产生维护成本?
2. **最小复杂度优先**:简单分支、普通函数、组合、语言原生特性够用时不引入模式。
3. **收益必须可验证**:降耦合、隔离变化、维护不变量、明确事务边界、提可靠性或可测性。
4. **成本必须计入**:接口、对象、间接调用、状态、异步、持久化、运维。
5. **不为"未来可能"设计**:只有变化有证据或结构已产生压力时才加抽象。
## 工作流
1. **先查日志**:若项目已有设计决策日志,读索引,按模块/变化轴定位受影响的既有记录(见「设计决策日志」)。需求变更时从这一步开始,不要重新从零判断。
2. **说清压力**:指出条件分支、耦合、职责、状态、事务、一致性或可靠性上的具体问题。
3. **路由**:用下方「快速路由」表筛出 **最多 3 个候选**。若命中「停止条件」,直接建议保持简单,**不再读任何参考文件**。
4. **验证候选**:打开候选模式文件,只看 `什么时候使用` / `什么时候不要使用` / `常见误用` / `退出条件`。
5. **组合检查**:推荐 2 个及以上模式时,读 [常见模式组合](references/pattern-combinations.md),确认职责不重叠、故障链可解释。
6. **输出**:按「输出模板」给结论。
7. **落日志**:把结论写入设计决策日志。不是可选项——没有记录的决策等于下次需求变更时重新猜。
**只在**路由表未命中、问题跨多个层级、或需要评分/迁移顺序时,才读 [设计模式决策指南](references/decision-guide.md)。
## 快速路由
| 设计压力 | 首选候选 | 通常不该用的情况 |
|---|---|---|
| `if/switch(type)` 随实现数量增长 | Strategy + Factory Method | 分支少且稳定 |
| `if/switch(status)` 散落 | State | 状态仅是数据标签 |
| 固定流程中少数步骤变化 | Template Method | 变化维度多、组合需求强 |
| 连续规则/过滤且可短路 | Chain of Responsibility | 步骤强耦合、全部必须执行 |
| 一个事实触发多个反应 | Observer / Domain Event | 强一致动作必须同事务完成 |
| 第三方/遗留接口不兼容 | Adapter | 接口本来就兼容 |
| 横切访问控制、事务、远程替身 | Proxy | 只是动态叠加功能时更像 Decorator |
| 功能可按需层层增强 | Decorator | 包装顺序复杂到难以理解 |
| 两个正交变化维度导致类爆炸 | Bridge | 只有一个变化维度 |
| 创建参数多、构造分阶段 | Builder | 简单构造/命名参数已足够 |
| 需要成套切换产品族 | Abstract Factory | 只有一种产品 |
| 复杂子系统需要统一入口 | Facade | Facade 只是无价值转发 |
| 树形结构统一处理叶子/容器 | Composite | 实际是图或行为差异巨大 |
| 领域对象需要稳定身份 | Entity | 只由值决定时用 Value Object |
| 领域对象只由值决定 | Value Object | 有独立身份/生命周期 |
| 强一致对象组需要事务边界 | Aggregate + Aggregate Root | 只是数据库关联关系 |
| 领域规则不自然属于实体 | Domain Service | 只是应用编排或技术服务 |
| 聚合持久化需要隔离 ORM | DDD Repository | 简单 CRUD 或报表查询 |
| 集合式持久化访问抽象 | Enterprise Repository | 富领域模型应按聚合根建模 |
| DB 更新 + MQ 发布双写 | Outbox | 没有跨进程事件传播 |
| 网络瞬态失败 | Retry + Timeout | 永久错误、非幂等写 |
| 持续故障导致资源耗尽 | Circuit Breaker + Bulkhead | 本地廉价调用 |
| 跨服务长事务 | Saga | 单库 ACID 足够 |
| 写模型复杂、读模型差异大 | CQRS | 普通 CRUD |
| 需要完整事实历史/重放 | Event Sourcing | 只为审计日志 |
| 重复请求/消息不能重复副作用 | Idempotency | 天然幂等读操作 |
## 停止条件:保持简单
命中任一条件时推荐"不使用模式":
- 只有一个实现,且未来变化无证据。
- 分支少、稳定、可读,抽象后跳转成本高于收益。
- 新模式引入状态/异步/持久化复杂度,但无对应可靠性或一致性需求。
- 团队无法测试、观测或运维该模式(Event Sourcing、Saga、复杂事件流)。
- 语言或框架已有原生能力:命名参数、DI 容器作用域、平台服务发现、K8s Service。
- 根因是职责划分或数据模型错误——先修边界,不要用模式掩盖。
- 为了消除一个很小很稳定的 `if` 引入多个接口和类;把模式数量当质量指标。
## Gotchas
- **同名不同物**:`enterprise/repository.md` 是集合式持久化抽象(适合 CRUD/查询封装),`ddd/repository.md` 是聚合根级仓储(富领域模型、强事务边界)。选错会让 ORM 类型渗进领域层。
- **Strategy vs State**:Strategy 由调用方/注册表选择,策略之间互不感知;State 由状态对象自己触发迁移并约束合法转换。
- **Decorator vs Proxy**:Decorator 动态叠加职责、调用方知道包装存在;Proxy 控制访问(权限、事务、懒加载、远程替身),真实对象对调用方不可见。
- **Outbox ≠ exactly-once**:只保证至少一次投递,消费端必须按业务键幂等。
- **Saga 补偿 ≠ rollback**:补偿是另一个业务动作,本身会失败,需要重试、可观测和人工兜底。
- **CQRS 与 Event Sourcing 不绑定**:可各自独立采用,不要默认成对引入。
- **Singleton 优先用 DI 容器作用域**,不要手写全局静态实例——那是隐藏的全局状态和测试难题。
- **Adapter 不负责业务编排**:适配层只做类型/协议转换,否则会变成第二个服务层。
- **超时先于重试**:多层无预算重试会放大流量,必须有总预算和退避上限。
## 输出模板
```markdown
## 压力
<具体代码/架构压力;变化频率、失败后果、当前已产生的成本>
## 结论
<主模式>(必要时:<辅助模式>),或明确写「不引入模式,保持 <更简单的做法>」
记录:<docs/design-decisions/NNNN.md>(本次是新建 / 追加 / 取代 / 废弃)
## 理由与排除
- 命中信号:<可观察证据,不是"最佳实践">
- 排除 <最相近候选>:<为什么>
## 最小落地
角色 / 接口所在层 / 创建与装配位置 / 一次请求或消息的调用时序
## 成本与退出条件
<新增间接层、状态、网络跳数、存储、运维负担>;<需求规模下降或假设不成立时如何回退>
## 验证
<不变量测试、边界/并发/重试用例、需要打的指标与日志>
```
异步模式(事件、Outbox、Saga、CQRS、重试)必须在「验证」里写明重复、乱序和恢复策略。
## 设计决策日志(可迭代)
设计结论必须沉淀成记录,随需求变更演进。历史只增不改:旧记录保留,靠状态和「变更历史」表达演进。
**位置**:优先沿用项目已有约定(`docs/adr/`、`docs/decisions/`、`ADR/`、已有设计日志);都没有则用 `docs/design-decisions/`,索引为 `INDEX.md`。
**创建记录**:
```bash
python3 scripts/new_decision.py "支付渠道分支改用 Strategy" # 自动编号 + 更新索引
python3 scripts/new_decision.py "订单状态机改用 State" --supersedes 0001
```
脚本从 [assets/decision-record-template.md](assets/decision-record-template.md) 生成骨架(压力 / 候选与排除 / 结论 / 最小落地 / 成本与退出条件 / 验证 / 变更历史),填内容即可。编号永不复用,不覆盖已有文件。
**需求变更时的三种动作**:
| 情况 | 动作 |
|---|---|
| 结论不变,只是约束/规模变化 | 在原记录「变更历史」追加一行:日期、需求变更、结论是否变 |
| 结论变了 | 新建记录并 `--supersedes <原编号>`;原记录状态改为「已被取代」,保留原文 |
| 命中原记录的「退出条件」 | 原记录状态改为「已废弃」,新建记录写明回退方案与回退后的更简单设计 |
**复盘触发**:每次需求变更后,重扫相关记录的「退出条件」。命中就回退,不要因为已经实现过就继续保留模式。**禁止**删除或静默覆盖旧记录,也禁止只改结论不写理由。
## 采纳前自检
输出建议前确认:
- [ ] 压力是真实的(已有 ≥2 个实现/分支,或已产生回归),不是"未来可能"。
- [ ] 已比较至少一个相近候选并说明排除理由。
- [ ] 更简单方案(函数、参数、组合、平台能力)已被明确排除。
- [ ] 团队能测试和观测新增间接层;异步模式已说明重复/乱序/恢复。
- [ ] 结论已落入设计决策日志:新建记录,或在既有记录上追加变更/取代/废弃。
任一项未通过 → 回到「停止条件」,优先保持简单。
## 模式索引
### GoF / 创建型
- [Singleton](references/gof/creational/singleton.md) · [Factory Method](references/gof/creational/factory-method.md) · [Abstract Factory](references/gof/creational/abstract-factory.md) · [Builder](references/gof/creational/builder.md) · [Prototype](references/gof/creational/prototype.md)
### GoF / 结构型
- [Adapter](references/gof/structural/adapter.md) · [Bridge](references/gof/structural/bridge.md) · [Composite](references/gof/structural/composite.md) · [Decorator](references/gof/structural/decorator.md) · [Facade](references/gof/structural/facade.md) · [Flyweight](references/gof/structural/flyweight.md) · [Proxy](references/gof/structural/proxy.md)
### GoF / 行为型
- [Chain of Responsibility](references/gof/behavioral/chain-of-responsibility.md) · [Command](references/gof/behavioral/command.md) · [Interpreter](references/gof/behavioral/interpreter.md) · [Iterator](references/gof/behavioral/iterator.md) · [Mediator](references/gof/behavioral/mediator.md) · [Memento](references/gof/behavioral/memento.md) · [Observer](references/gof/behavioral/observer.md) · [State](references/gof/behavioral/state.md) · [Strategy](references/gof/behavioral/strategy.md) · [Template Method](references/gof/behavioral/template-method.md) · [Visitor](references/gof/behavioral/visitor.md)
### 企业应用模式
- [Repository](references/enterprise/repository.md) · [Service Layer](references/enterprise/service-layer.md) · [Unit of Work](references/enterprise/unit-of-work.md) · [Data Mapper](references/enterprise/data-mapper.md) · [Active Record](references/enterprise/active-record.md) · [DTO](references/enterprise/dto.md) · [Dependency Injection](references/enterprise/dependency-injection.md) · [MVC](references/enterprise/mvc.md)
### DDD 模式
- [Entity](references/ddd/entity.md) · [Value Object](references/ddd/value-object.md) · [Aggregate](references/ddd/aggregate.md) · [Aggregate Root](references/ddd/aggregate-root.md) · [DDD Repository](references/ddd/repository.md) · [Domain Service](references/ddd/domain-service.md) · [Domain Event](references/ddd/domain-event.md) · [Application Service](references/ddd/application-service.md) · [DDD Factory](references/ddd/factory.md) · [Specification](references/ddd/specification.md)
### 分布式系统模式
- [Saga](references/distributed/saga.md) · [CQRS](references/distributed/cqrs.md) · [Event Sourcing](references/distributed/event-sourcing.md) · [Transactional Outbox](references/distributed/outbox.md) · [Circuit Breaker](references/distributed/circuit-breaker.md) · [Retry](references/distributed/retry.md) · [Bulkhead](references/distributed/bulkhead.md) · [API Gateway](references/distributed/api-gateway.md) · [Service Discovery](references/distributed/service-discovery.md) · [Idempotency](references/distributed/idempotency.md) · [Leader Election](references/distributed/leader-election.md)