为什么程序员需要结构化 Skill?
大多数人向 AI 提编程问题时,习惯说”帮我写一个 XXX 功能”或”这段代码有 Bug,帮我修”。这种方式往往得到的是泛泛的回答——缺少上下文、忽略边界情况、没有工程最佳实践。
优秀的编程 Skill = 明确的上下文 + 结构化的思维框架 + 具体的约束条件
本页收录的 10 个 Skill 模板,每一个都基于真实的软件工程方法论,让豆包从”代码生成器”升级为”工程思维搭档”。
所有 Skill 中的 [方括号内容] 为占位符,使用时请替换为你的实际内容。
1. 橡皮鸭调试法(Rubber Duck Debugging)
原理来源: Andrew Hunt & David Thomas《程序员修炼之道》(The Pragmatic Programmer, 1999)。书中提到,当你向一只橡皮鸭(或任何”听众”)逐行解释代码逻辑时,往往能自己发现 Bug。因为解释的过程迫使你放慢速度、理清每一步的逻辑假设。豆包比橡皮鸭更好——它不仅”听”,还会反问。
适用场景: 代码行为与预期不符、调试半天找不到原因、逻辑复杂难以理清
你是我的橡皮鸭调试搭档。我会向你解释一段代码的逻辑,请你扮演一位经验丰富但对我的项目完全不了解的高级工程师。
你的任务:
1. 认真"倾听"我的解释
2. 在每个关键逻辑节点上追问:"你确定这里的假设是成立的吗?"
3. 当我的解释出现跳跃、模糊或自相矛盾时,立即打断我并指出
4. 特别关注以下常见盲区:
- 变量的实际值 vs 我以为的值
- 边界条件(空值、零值、极大值、并发)
- 隐含的执行顺序假设
- 副作用和状态变化
5. 不要直接给出答案,而是通过提问引导我自己发现问题
我的代码语言:[编程语言]
问题描述:[用一句话描述 Bug 现象]
相关代码:
[粘贴你的代码]
请开始提问吧。
使用示例
我的代码语言:Python
问题描述:用户登录后 session 偶尔会丢失
相关代码:
def login(request):
user = authenticate(request.POST['username'], request.POST['password'])
if user:
request.session['user_id'] = user.id
return redirect('/dashboard')
return redirect('/login')
好的,让我来做你的调试搭档。我先确认几个基本问题:
- 你说”偶尔丢失”——这个”偶尔”有规律吗? 比如是特定用户、特定时间段、还是特定操作后丢失?
authenticate 函数在认证失败时返回什么? 你确定它只返回 None 而不是抛异常?如果抛异常,session 的赋值就不会执行,但用户可能看到的错误页面让他们以为登录成功了。
request.session 的后端存储是什么? 内存、数据库、还是 Redis?如果是内存存储并且你有多个 worker 进程…你看出问题了吗?
- 在
redirect('/dashboard') 之前,session 是否已经被持久化了? 有些框架需要显式调用 session.save()…
请逐个回答,我们继续深挖。
2. 第一性原理架构设计
原理来源: 亚里士多德的第一性原理(First Principles)在软件工程中的应用。Elon Musk 多次提到用第一性原理思考问题而非类比推理。在架构设计中,这意味着从需求的本质出发推导架构,而不是看别人用了什么就照搬什么。Fred Brooks 在《人月神话》中也强调”概念完整性”是系统设计最重要的属性。
适用场景: 新项目架构设计、技术选型决策、评估是否该引入某个中间件
请用第一性原理帮我设计系统架构。不要从"业界常用方案"出发,而是从需求的本质出发逐层推导。
第一步:需求本质分析
- 这个系统最核心要解决的问题是什么?(一句话)
- 数据的本质是什么?(结构化/非结构化、读写比例、一致性要求)
- 用户交互的本质是什么?(同步/异步、延迟敏感度)
- 规模的本质是什么?(用户量、数据量、增长曲线)
第二步:约束条件分解
- 物理约束:网络延迟、存储容量、计算资源
- 业务约束:预算、团队规模、上线时间
- 合规约束:数据安全、隐私保护、行业法规
第三步:从底层逐层推导
- 基于数据本质 → 推导存储方案
- 基于交互本质 → 推导通信协议
- 基于规模本质 → 推导扩展策略
- 每一层决策都要说明"为什么这样选"而不是"大家都这样做"
第四步:验证架构
- 这个架构的每个组件都是必要的吗?(去掉任何一个会怎样?)
- 有没有引入不必要的复杂性?
- 最可能出问题的环节在哪里?
我的项目:[项目描述]
团队规模:[人数和技术栈背景]
预期规模:[用户量/数据量/QPS]
上线时间:[期限]
使用示例
我的项目:内部协作文档系统(类似轻量级 Notion)
团队规模:3 个全栈工程师,熟悉 Go 和 Vue
预期规模:公司内部 500 人使用,文档数约 10 万
上线时间:3 个月从第一性原理出发,逐层分析”文档协作”的本质需求,从 CRDT vs OT 的取舍、存储模型选择(树形文档天然适合文档数据库还是关系型?)、实时通信方案(WebSocket 是否必要?SSE 够不够?)、以及 3 人团队的工程复杂度承受上限,推导出一个简洁可行的架构方案。
3. 假设-验证 Bug 排查(科学方法)
原理来源: Karl Popper 的证伪主义(Falsificationism)。科学进步不是通过证明假设正确,而是通过排除错误的假设。优秀的调试过程就是科学方法的应用:观察现象 → 提出假设 → 设计实验验证 → 排除或确认。Andreas Zeller 在《Why Programs Fail》中系统地将科学方法应用于程序调试。
适用场景: 复杂 Bug 排查、线上问题定位、性能瓶颈诊断
请用科学方法帮我排查这个 Bug。严格按照以下步骤:
【观察】
Bug 现象:[详细描述你观察到的异常行为]
复现条件:[什么情况下会出现/不出现]
环境信息:[操作系统、运行时版本、依赖版本等]
最近变更:[最近改动了什么代码或配置]
请执行以下步骤:
步骤一:生成假设清单
基于以上观察,列出所有可能的原因(至少 5 个),并按可能性从高到低排序。格式:
| # | 假设 | 可能性 | 依据 |
步骤二:设计验证实验
对每个假设,设计一个最小成本的验证步骤。关键原则:
- 每次只验证一个变量
- 优先验证能排除最多假设的实验
- 给出具体的命令/代码/检查步骤
步骤三:预测与判定
对每个实验,明确:
- 如果假设成立,预期会观察到什么
- 如果假设不成立,预期会观察到什么
- 如何判定实验结论
步骤四:推荐执行顺序
给出最优的验证顺序,原则是"用最少的实验排除最多的假设"(信息增益最大化)。
使用示例
Bug 现象:Spring Boot 应用在运行 48 小时后响应时间从 50ms 飙升到 5000ms。复现条件:仅在生产环境出现,测试环境正常。最近变更:上周加了一个定时任务每小时执行一次。
会生成包含”内存泄漏(定时任务累积对象)”、“数据库连接池耗尽”、“GC 停顿”、“线程池饱和”、“外部服务超时级联”等假设的排查方案,并给出具体的 jstat、jmap、arthas 等诊断命令。
4. 代码审查清单(系统检查法)
原理来源: Atul Gawande《清单革命》(The Checklist Manifesto, 2009)。医疗界引入手术安全检查清单后,死亡率下降了 47%。同样的道理适用于代码审查——人类大脑在复杂任务中容易遗漏关键检查项,而清单能系统性地消除这种遗漏。Google 和微软的代码审查实践也证明了结构化 Review 的价值。
适用场景: 提交代码前自检、Pull Request 审查、上线前最终检查
请对以下代码进行全面审查,按照五个维度逐一检查。每个维度都必须给出具体发现,不能只说"看起来没问题"。
代码语言:[编程语言]
代码功能:[一句话说明这段代码做什么]
上下文:[这段代码在系统中的位置/重要程度]
代码:
[粘贴代码]
请按以下清单逐项检查:
## 一、安全性 (Security)
- [ ] 是否有 SQL 注入/XSS/CSRF 风险?
- [ ] 用户输入是否经过验证和清洗?
- [ ] 敏感数据(密码、token、密钥)是否安全处理?
- [ ] 是否有越权访问的可能?
- [ ] 错误信息是否泄露了系统内部细节?
## 二、性能 (Performance)
- [ ] 是否有 N+1 查询问题?
- [ ] 循环中是否有不必要的重复计算或 IO 操作?
- [ ] 数据结构选择是否合理?时间/空间复杂度如何?
- [ ] 是否需要缓存?是否有缓存失效的问题?
- [ ] 大数据量场景下是否会有瓶颈?
## 三、可读性 (Readability)
- [ ] 命名是否清晰表达意图?(能否通过名称理解用途)
- [ ] 是否有过长的函数/方法需要拆分?
- [ ] 注释是否足够?是否有过时/误导性的注释?
- [ ] 代码结构是否符合所在项目的约定?
- [ ] 是否有"魔法数字"或硬编码的字符串?
## 四、可维护性 (Maintainability)
- [ ] 是否符合单一职责原则(SRP)?
- [ ] 依赖关系是否合理?耦合度如何?
- [ ] 是否容易编写单元测试?
- [ ] 配置是否外部化?环境切换是否方便?
- [ ] 是否有适当的日志记录?
## 五、边界与异常 (Edge Cases & Error Handling)
- [ ] 空值/null 是否处理?
- [ ] 空集合/空字符串是否处理?
- [ ] 并发/竞态条件是否考虑?
- [ ] 超时和重试机制是否合理?
- [ ] 异常是否被正确捕获和处理?(不是吞掉异常)
最后,请给出:
1. 🔴 必须修复(阻塞上线的问题)
2. 🟡 建议修复(不紧急但应该改进)
3. 🟢 锦上添花(代码质量提升建议)
5. 重构决策矩阵
原理来源: Martin Fowler《重构:改善既有代码的设计》(Refactoring, 1999) 中定义的 22 种”代码坏味道”(Code Smells),以及 Michael Feathers《修改代码的艺术》(Working Effectively with Legacy Code, 2004) 中处理遗留代码的策略。重构不是”觉得代码丑就改”,而是一个有方法论的工程决策。
适用场景: 代码质量恶化但不确定是否值得重构、遗留系统改造评估、技术债务管理
请帮我分析这段代码是否需要重构,以及如何重构。
代码语言:[编程语言]
代码历史:[大约多久的历史,多少人维护过]
当前问题:[为什么觉得需要重构]
代码:
[粘贴代码]
请按以下框架分析:
## 第一步:坏味道诊断
对照 Martin Fowler 的代码坏味道清单,逐一检查:
1. 过长函数 (Long Method)
2. 过大的类 (Large Class)
3. 过长参数列表 (Long Parameter List)
4. 发散式变化 (Divergent Change)
5. 霰弹式修改 (Shotgun Surgery)
6. 依恋情结 (Feature Envy)
7. 数据泥团 (Data Clumps)
8. 基本类型偏执 (Primitive Obsession)
9. 重复代码 (Duplicated Code)
10. 冗余的注释 (Comments as Deodorant)
## 第二步:重构价值评估矩阵
| 评估维度 | 评分(1-5) | 说明 |
|---------|-----------|------|
| 变更频率 | | 这段代码多久改一次? |
| Bug 密度 | | 这段代码经常出 Bug 吗? |
| 理解成本 | | 新人看懂需要多久? |
| 测试覆盖 | | 有没有测试保护? |
| 业务重要性 | | 这是核心功能还是边缘功能? |
综合评分 > 15 → 强烈建议重构
综合评分 10-15 → 可以排期重构
综合评分 < 10 → 暂时不动,标记技术债
## 第三步:重构方案
如果决定重构,给出:
1. 推荐的重构手法(用 Fowler 的标准命名)
2. 重构前后的代码对比
3. 风险评估:重构可能引入什么新问题
4. 安全重构的前提条件(需要先补什么测试)
5. 可以分几步完成(每步都可独立验证和回退)
6. TDD 驱动开发助手
原理来源: Kent Beck《测试驱动开发》(Test-Driven Development: By Example, 2002)。TDD 的核心循环是红-绿-重构:先写一个失败的测试(红),再写最少的代码让测试通过(绿),最后优化代码结构(重构)。Robert C. Martin(Uncle Bob)在《代码整洁之道》中进一步强调 TDD 是专业程序员的基本修养。
适用场景: 开发新功能、重写已有功能、练习 TDD 方法论
请用 TDD 方法帮我实现以下功能。严格遵循"红-绿-重构"循环。
功能需求:[描述你要实现的功能]
编程语言:[语言]
测试框架:[如 pytest / Jest / JUnit 等]
请按以下步骤执行:
【第 1 轮:红灯 — 写第一个失败的测试】
1. 先分析功能需求,拆解为最小的可测试行为单元
2. 从最简单的 case 开始,写出第一个测试用例
3. 解释为什么从这个 case 开始(为什么它是最小的有价值的行为)
4. 此时还没有实现代码,测试应该失败
【第 2 轮:绿灯 — 写最少的代码让测试通过】
1. 写出让当前所有测试通过的最少代码
2. 注意:此时不要追求完美,可以用最"笨"的方式实现
3. 确认测试通过
【第 3 轮:重构 — 优化实现】
1. 在所有测试保护下,优化代码结构
2. 消除重复、改善命名、提取函数
3. 确认重构后测试仍然全部通过
【继续循环】
4. 添加下一个测试用例(覆盖新的行为/边界条件)
5. 重复红-绿-重构循环
6. 直到所有需求行为都被测试覆盖
最终输出:
- 完整的测试文件
- 完整的实现代码
- 每一轮循环的说明(为什么这样写这个测试、为什么这样实现)
使用示例
功能需求:实现一个密码强度验证器(长度至少 8 位、包含大小写、包含数字、包含特殊字符)。Python + pytest。会从”空密码应返回弱”开始,逐步添加长度检查、大小写检查、数字检查、特殊字符检查的测试,每一步都先写测试再写实现,最终得到一个完整且经过充分测试的验证器。
7. 技术方案 RFC 生成器
原理来源: RFC(Request for Comments)文化源自互联网工程任务组(IETF),后被 Uber、Google、Amazon 等公司采用为内部技术决策机制。Amazon 的”六页备忘录”文化(Jeff Bezos 禁止 PPT,要求用完整叙述文档)背后的逻辑是:写作是思考的最严格形式,写不清楚意味着想不清楚。Barbara Minto 的金字塔原理则提供了结构化写作的方法论。
适用场景: 重大技术决策、系统改造方案、新技术引入评估
请帮我撰写一份技术方案 RFC 文档,格式参考 Amazon 六页备忘录和 Uber RFC 模板。
项目名称:[项目名]
一句话描述:[这个方案要解决什么问题]
作者:[你的名字]
请按以下结构生成完整 RFC:
## 1. 背景与动机(Why)
- 当前存在什么问题?用数据和具体案例说明痛点
- 为什么现在需要解决?不解决会怎样?(量化影响)
- 之前是否尝试过其他方案?为什么没有成功?
## 2. 目标与非目标(Scope)
- 本方案要达成的目标(明确、可衡量)
- 明确标注本方案不打算解决的问题(避免范围蔓延)
- 成功标准:如何衡量方案是否成功?
## 3. 方案详细设计(How)
- 整体架构图(用文字描述或 ASCII 图)
- 核心模块说明
- 数据模型设计
- 关键接口定义
- 关键流程的时序描述
## 4. 方案对比(Alternatives)
| 维度 | 方案 A(推荐) | 方案 B | 方案 C(不做) |
|------|--------------|--------|--------------|
| 开发成本 | | | |
| 维护成本 | | | |
| 性能 | | | |
| 扩展性 | | | |
| 风险 | | | |
为什么推荐方案 A?逐条说明决策依据。
## 5. 风险评估与缓解
- 技术风险:[风险] → [缓解策略]
- 业务风险:[风险] → [缓解策略]
- 运维风险:[风险] → [缓解策略]
- 回滚方案:如果方案失败,如何回退?
## 6. 里程碑与排期
| 阶段 | 交付物 | 时间 | 负责人 |
|------|--------|------|--------|
## 7. 开放问题
列出当前尚未确定、需要进一步讨论的问题。
8. 性能优化分析(80/20 法则)
原理来源: 帕累托原则(Pareto Principle)指出 80% 的结果来自 20% 的原因。在性能优化领域,Donald Knuth 有一句经典名言:“Premature optimization is the root of all evil”(过早优化是万恶之源)。正确的做法是先测量,找到真正的瓶颈(那 20%),再集中优化。Brendan Gregg 的《性能之巅》(Systems Performance) 提供了系统化的性能分析方法论(USE 方法)。
适用场景: 系统响应慢、接口超时、资源占用过高、上线前性能评估
请用 80/20 法则帮我分析性能问题,找到导致 80% 性能损耗的 20% 代码。
问题描述:[当前的性能问题,如"API 响应时间 > 2s"]
系统概况:[技术栈、架构简述]
已有数据:[如果有性能监控数据、profile 结果请提供]
代码/架构:
[粘贴相关代码或描述系统架构]
请从以下四个维度逐一分析:
### 维度一:算法与数据结构
- 是否有 O(n^2) 或更差复杂度的操作?
- 数据结构选型是否合理?(例如频繁查找却用了 List 而非 HashMap)
- 是否有可以用空间换时间的优化点?
- 是否有重复计算可以用备忘录模式消除?
### 维度二:I/O 与网络
- 数据库查询是否高效?(N+1 问题、缺少索引、全表扫描)
- 是否有不必要的网络往返?(可以批量的操作被逐条执行)
- 文件 I/O 是否有优化空间?(缓冲、异步、流式处理)
- 外部 API 调用是否可以并行化?
### 维度三:内存
- 是否有内存泄漏的迹象?
- 大对象是否及时释放?
- 缓存策略是否合理?(缓存命中率、过期策略、内存上限)
- GC 压力如何?是否有频繁的 Full GC?
### 维度四:并发
- 是否充分利用了多核/多线程?
- 是否有锁竞争导致的性能退化?
- 线程池/连接池的配置是否合理?
- 异步操作是否适当使用?
最终输出:
1. 瓶颈排名:按影响程度排序的问题清单
2. 优化方案:每个瓶颈的具体优化建议(带代码示例)
3. 预期收益:每项优化预计带来多少提升
4. 优化优先级:投入产出比最高的优化应该先做
9. API 设计评审(RESTful + 一致性原则)
原理来源: Roy Fielding 的博士论文定义了 REST 架构风格。此外,Leonard Richardson 的 REST 成熟度模型(Richardson Maturity Model)提供了 API 设计的分级标准。Microsoft REST API Guidelines 和 Google API Design Guide 是业界公认的最佳实践文档。API 设计的核心原则是一致性——Postel 法则(Be liberal in what you accept, and conservative in what you send)也同样适用。
适用场景: API 设计评审、接口文档审核、新 API 设计
请评审以下 API 设计,从 RESTful 最佳实践和一致性原则出发给出改进建议。
API 列表:
[列出你的 API 端点,格式如:
GET /api/v1/users
POST /api/v1/users
GET /api/v1/users/{id}
PUT /api/v1/users/{id}
DELETE /api/v1/users/{id}
...]
业务背景:[简述业务场景]
请从以下方面逐一评审:
### 1. 资源命名
- 是否使用名词复数形式?(/users 而非 /getUser)
- 是否使用 kebab-case?(/user-profiles 而非 /userProfiles)
- URL 层级是否清晰表达资源关系?
- 是否有动词混入了 URL?(应该用 HTTP 方法表达动作)
### 2. HTTP 方法使用
- GET:是否用于无副作用的查询?
- POST:是否用于创建资源?
- PUT/PATCH:更新语义是否正确?(整体替换 vs 部分更新)
- DELETE:删除行为是否明确?(硬删除 vs 软删除)
- 是否有方法不安全或非幂等的误用?
### 3. 状态码
- 是否正确使用了 2xx(成功)、4xx(客户端错误)、5xx(服务端错误)?
- 是否区分了 400(格式错误)和 422(业务校验失败)?
- 创建成功是否返回 201 而非 200?
- 是否有信息量不足的状态码使用?
### 4. 错误处理
- 错误响应格式是否统一?
- 是否提供了足够的错误细节帮助调用方定位问题?
- 是否避免了暴露系统内部信息?
- 推荐的错误响应结构是什么?
### 5. 分页、排序、过滤
- 列表接口是否支持分页?采用什么分页方式?
- 排序参数设计是否合理?
- 过滤条件是否灵活且安全?
- 是否有性能保护机制(最大每页数量等)?
### 6. 版本化策略
- 是否有版本控制?(URL 路径 vs Header)
- 版本升级策略是否合理?
- 向后兼容性如何保证?
### 7. 认证与安全
- 认证方式是否合理?(JWT / OAuth / API Key)
- 是否有速率限制?
- 敏感数据是否加密传输?
- CORS 策略是否正确配置?
请最终给出:
1. 改进后的 API 设计(完整列表)
2. 每项改进的理由
3. 不兼容变更的迁移建议
10. 系统故障预演(混沌工程思维)
原理来源: Netflix 混沌工程实践,起源于 2011 年的 Chaos Monkey 项目。核心理念是主动在生产环境注入故障来发现系统弱点,而不是等故障自己发生。Casey Rosenthal 和 Nora Jones 在《混沌工程》(Chaos Engineering, 2020) 中将其系统化。Google SRE 的《Site Reliability Engineering》一书中也强调了”预演灾难”的重要性——事前思考永远比事后救火成本低。
适用场景: 上线前风险评估、系统可靠性审查、故障应急预案制定
请对以下系统进行全面的故障预演分析(Pre-mortem Analysis),用混沌工程的思维方式,主动想象各种可能的故障场景。
系统描述:[系统架构和关键组件]
依赖服务:[数据库、消息队列、第三方 API 等]
流量特征:[QPS、峰值时间、流量分布]
当前保护措施:[已有的容错机制]
请按以下框架进行故障预演:
### 一、基础设施故障
假设以下故障逐一发生,分析影响和应对:
1. 单台应用服务器宕机
2. 数据库主节点不可用
3. Redis/缓存集群故障
4. 网络分区(部分节点之间不通)
5. 磁盘空间耗尽
6. DNS 解析故障
### 二、依赖服务故障
1. 下游 API 响应时间从 100ms 飙升到 10s
2. 下游 API 返回 50% 的错误响应
3. 消息队列积压 100 万条消息
4. 第三方支付/短信服务完全不可用
5. CDN 故障,静态资源无法加载
### 三、流量异常
1. 流量突增 10 倍(热点事件/营销活动)
2. 恶意爬虫发起大量请求
3. DDoS 攻击
4. 某个接口被循环调用(客户端 Bug)
### 四、数据异常
1. 数据库数据被误删
2. 缓存与数据库数据不一致
3. 上游系统发送了格式异常的数据
4. 数据迁移过程中出现部分失败
### 五、人为操作故障
1. 错误的配置变更被推送到生产
2. 部署了有 Bug 的新版本
3. 数据库 DDL 变更导致锁表
4. 错误地扩缩容了关键服务
对每个故障场景,请分析:
- **爆炸半径**:影响范围有多大?(某个功能/某类用户/全站不可用)
- **检测时间**:多久能发现这个问题?(有没有监控告警)
- **恢复时间**:预计多久能恢复?
- **应对方案**:具体怎么处理?
- **预防措施**:如何避免或减轻这类故障的影响?
最后,请给出:
1. 系统当前最大的 3 个可靠性风险
2. 优先级最高的 5 项改进措施
3. 建议制定的应急预案清单
使用示例
系统描述:电商订单系统,微服务架构(订单服务、库存服务、支付服务、通知服务),Spring Cloud + MySQL + Redis + RabbitMQ
依赖服务:支付宝/微信支付、短信服务商、物流查询 API
流量特征:日常 500 QPS,大促期间峰值 5000 QPS
当前保护措施:基本的主从复制、Redis Sentinel、服务间 HTTP 超时设置
豆包会对每类故障场景给出详细分析,例如:“如果 Redis Sentinel 发生主从切换,在切换期间(通常 10-30 秒)所有依赖 Redis 的库存扣减操作会失败,可能导致超卖。建议引入本地缓存兜底 + 库存预扣减的两阶段机制…” 并最终给出优先级排序的改进方案。
组合使用建议
这些 Skill 不是孤立的,可以串联使用来覆盖完整的开发生命周期:
| 开发阶段 | 推荐 Skill 组合 |
|---|
| 需求分析 | 第一性原理架构设计 + 技术方案 RFC |
| 编码实现 | TDD 驱动开发 + 代码审查清单 |
| 调试排错 | 橡皮鸭调试法 + 假设-验证 Bug 排查 |
| 性能优化 | 性能优化分析 + API 设计评审 |
| 质量保障 | 重构决策矩阵 + 系统故障预演 |
推荐起步方式: 如果你只能选一个 Skill 开始用,推荐代码审查清单——它适用面最广,每次提交代码前用一次就能显著减少线上问题。