# Bp Component Design

> 提供组件级设计原则，包括类/模块设计、接口设计、数据模型、并发模型、错误处理。在系统设计阶段讨论组件详细设计时使用，或在 code review 中评估组件质量时使用。

- Skill: `davidyichengwei/bp-component-design` (Agent Skill)
- Install (CLI): `npx skillmds@latest add davidyichengwei/bp-component-design`
- Raw SKILL.md: https://api.skillmd.com/api/skills/davidyichengwei/bp-component-design/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: davidyichengwei (https://skillmd.com/u/davidyichengwei)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/davidyichengwei/bp-component-design

---


# 组件设计

> **使用场景**：`workflow-system-design` skill 在讨论 spec.md **4.2 组件设计** 时加载本 skill。

## 第一性原理

> **组件设计的本质**：把架构方案转化为可实现的代码结构，定义清晰的职责边界和交互契约。

---

## 4.2.1 核心类/模块设计

### SOLID 原则

| 原则 | 含义 | 检查点 |
|------|------|--------|
| **S**ingle Responsibility | 类只做一件事 | 这个类能用一句话描述吗？ |
| **O**pen/Closed | 对扩展开放，对修改关闭 | 新增功能是否需要改现有代码？ |
| **L**iskov Substitution | 子类可替换父类 | 子类是否违反父类契约？ |
| **I**nterface Segregation | 接口精简专一 | 调用方是否被迫依赖不需要的方法？ |
| **D**ependency Inversion | 依赖抽象而非具体 | 高层模块是否直接依赖低层实现？ |

### 设计原则

| 原则 | 说明 |
|------|------|
| **组合优于继承** | 继承紧耦合，组合松耦合易替换 |
| **面向接口编程** | 依赖抽象接口，而非具体实现 |
| **最小知识原则** | 避免链式调用暴露内部结构 |

### 常用设计模式

| 类型 | 模式 | 适用场景 |
|------|------|----------|
| 创建型 | Factory | 封装对象创建逻辑 |
| 创建型 | Builder | 分步构建复杂对象 |
| 结构型 | Adapter | 接口转换 |
| 结构型 | Decorator | 动态添加职责 |
| 行为型 | Strategy | 可替换算法 |
| 行为型 | Template Method | 定义算法骨架，子类实现细节 |
| 行为型 | Iterator | 数据流处理、管道模式 |

### Checklist

- [ ] 类职责是否单一清晰？
- [ ] 继承层次是否合理（不超过 2-3 层）？
- [ ] 依赖是否指向抽象而非具体实现？
- [ ] 模块边界是否明确？

---

## 4.2.2 接口设计

> **接口设计关注对外暴露的 public API**，内部接口在 4.2.1 中定义。

### 设计原则

| 原则 | 说明 |
|------|------|
| **最小化** | 只暴露必要的接口，隐藏实现细节 |
| **一致性** | 命名、参数顺序、错误处理风格统一 |
| **向后兼容** | 接口变更不破坏现有调用方 |
| **自描述** | 接口签名本身能表达意图 |

### 接口定义要素

```cpp
// 示例：接口定义应包含
class StorageEngine {
public:
    // 1. 方法签名：清晰的命名和参数
    // 2. 参数约束：哪些可为空？取值范围？
    // 3. 返回值：成功/失败如何表示？
    // 4. 错误码：可能返回哪些错误？
    // 5. 线程安全：是否可并发调用？
    
    /**
     * @brief 写入 KV 对
     * @param key 键，不能为空
     * @param value 值
     * @return Status::OK 成功
     *         Status::KeyTooLong key 超过 64KB
     *         Status::IOError 写入失败
     * @thread_safety 线程安全
     */
    virtual Status Put(const Slice& key, const Slice& value) = 0;
};
```

### 版本兼容策略

| 变更类型 | 兼容性 | 处理方式 |
|----------|--------|----------|
| 新增方法 | 向后兼容 | 直接添加 |
| 新增可选参数 | 向后兼容 | 提供默认值 |
| 删除方法 | **不兼容** | 先废弃，下个大版本删除 |
| 修改参数类型 | **不兼容** | 新增方法，废弃旧方法 |

### Checklist

- [ ] 接口是否最小化（不暴露不必要的方法）？
- [ ] 参数和返回值是否清晰定义？
- [ ] 错误码是否完整列出？
- [ ] 线程安全性是否说明？
- [ ] 是否考虑了向后兼容？

---

## 4.2.3 数据模型

> **何时需要**：涉及数据存储、Schema 变更、新增数据结构时。

### 设计要素

| 要素 | 需要明确 |
|------|----------|
| **Schema** | 字段定义、类型、约束 |
| **索引** | 查询模式决定索引设计 |
| **编码格式** | 序列化方式（protobuf/flatbuffers/自定义） |
| **存储位置** | 存哪里？生命周期？ |

### Schema 演进

| 策略 | 说明 |
|------|------|
| **向前兼容** | 新代码能读旧数据 |
| **向后兼容** | 旧代码能读新数据（需谨慎设计） |
| **迁移计划** | 如何从旧 Schema 迁移到新 Schema？ |

### Checklist

- [ ] Schema 字段是否完整定义？
- [ ] 索引是否满足查询需求？
- [ ] 是否考虑了 Schema 演进？
- [ ] 迁移/回滚方案是否明确？

---

## 4.2.4 并发模型

> **何时需要**：涉及多线程、异步操作、共享状态时。

### 设计要素

| 要素 | 需要明确 |
|------|----------|
| **线程模型** | 哪些线程？职责是什么？ |
| **共享状态** | 哪些数据被多线程访问？ |
| **同步机制** | 用什么锁？锁的粒度？ |
| **异步边界** | 哪里是同步/异步的边界？ |

### 常见模式

| 模式 | 适用场景 |
|------|----------|
| **单线程 + 事件循环** | I/O 密集、低延迟 |
| **线程池 + 任务队列** | CPU 密集、可并行 |
| **Actor 模型** | 状态隔离、消息传递 |
| **读写锁** | 读多写少 |

### Checklist

- [ ] 线程模型是否清晰？
- [ ] 共享状态是否明确，保护机制是否合理？
- [ ] 是否有死锁风险？
- [ ] 锁粒度是否合适（不过粗也不过细）？

---

## 4.2.5 错误处理

> **何时需要**：涉及外部依赖、I/O 操作、可能失败的场景时。

### 设计要素

| 要素 | 需要明确 |
|------|----------|
| **失败模式** | 可能发生哪些错误？ |
| **错误表示** | 错误码 / 异常 / Status 对象？ |
| **重试策略** | 哪些错误可重试？退避策略？ |
| **恢复机制** | 失败后如何恢复到一致状态？ |

### 错误分类

| 类型 | 示例 | 处理方式 |
|------|------|----------|
| **可重试** | 网络超时、临时不可用 | 指数退避重试 |
| **不可重试** | 参数错误、权限不足 | 直接返回错误 |
| **致命错误** | 数据损坏、不变量被破坏 | 记录日志 + panic/abort |

### 重试策略

```cpp
// 指数退避 + 抖动
int delay_ms = min(base_delay * (1 << retry_count), max_delay);
delay_ms += random(0, delay_ms * 0.1);  // 10% jitter
```

### Checklist

- [ ] 所有可能的失败模式是否列出？
- [ ] 错误表示方式是否统一？
- [ ] 可重试 vs 不可重试是否区分？
- [ ] 失败后的清理/恢复逻辑是否考虑？

---

## 反模式

| 反模式 | 问题 | 改进 |
|--------|------|------|
| God Class | 类承担过多职责 | 拆分为多个小类 |
| Feature Envy | 方法大量访问其他类数据 | 移动到数据所在类 |
| 过度设计 | 不需要的抽象层 | 简单优先，按需抽象 |
| 忽略错误 | 吞掉错误不处理 | 明确处理或向上传播 |
| 锁粒度过粗 | 整个操作加大锁 | 缩小临界区 |

---

## 与其他 Skill 协同

| 场景 | 加载 Skill |
|------|-----------:|
| 涉及分布式场景（网络、一致性、故障） | `bp-distributed-systems` |
| 涉及性能优化 | `bp-performance-optimization` |

