Reproduction Steps
2026/9/15 16:18:31 网站建设 项目流程

Reproduction Steps

【免费下载链接】claude-skills67 Specialized Skills for Full-Stack Developers. Transform Claude Code into your expert pair programmer.项目地址: https://gitcode.com/GitHub_Trending/claud/claude-skills

  1. Navigate to /users
  2. Click "Load More" button
  3. Wait for loading spinner
  4. ERROR: "Cannot read property 'map' of undefined"

Environment

  • Browser: Chrome 120
  • User: Admin role
  • Data state: 50+ users in database
环境信息(浏览器、用户角色、数据状态)同样关键——bug 往往只在特定数据量或特定角色下触发。这对应 SKILL.md 中 MUST DO 的 "Gather complete error messages and stack traces"。 ### 1.3 检查最近的变更 回归类 bug 十有八九由最近提交引入: ```bash # What changed recently? git log --oneline -10 # What specifically changed in the failing file? git log -p UserList.tsx # When did this start failing? git bisect start git bisect bad HEAD git bisect good v1.2.0

git bisect可以自动化二分定位"第一个坏提交"。关于二分定位的更完整用法,仓库在 strategies.md 中有专门小节,支持git bisect run npm test之类的全自动回归扫描。

1.4 沿数据流反向追踪

从报错点出发,一步一步向前追问"这个变量从哪来":

// Error happens here: users.map(u => u.name) // users is undefined // Trace backward: // Where does 'users' come from? const users = props.users; // Where do props come from? <UserList users={data.users} /> // Where does data come from? const { data } = useQuery(GET_USERS); // ROOT CAUSE: Query returns { users: null } when loading

这一步骤往往能直接暴露根因——本例中,查询处于 loading 状态时返回{ users: null },而组件渲染时没有任何空值保护。

1.5 添加诊断性插桩

在关键边界处加临时日志,确认数据在各环节的真实形态:

// Add temporary logging at boundaries console.log('[UserList] props:', JSON.stringify(props)); console.log('[UserList] users type:', typeof props.users); console.log('[UserList] users value:', props.users); // Check at data source console.log('[API] Response:', response); console.log('[API] Response.data:', response.data);

提示:插桩日志属于临时调试手段。SKILL.md 的约束明确要求 "Remove all debug code before committing(提交前删除所有调试代码)"。


Phase 2:模式分析

目标:找到正常工作的示例,搞清楚"正确行为"应该长什么样。

2.1 定位相似的正常实现

# Find similar components that work correctly grep -r "useQuery" src/components/ --include="*.tsx" # Find how other lists handle loading states grep -r "loading" src/components/*List* --include="*.tsx"

2.2 完整研究参考实现

逐行对比正常与异常实现的差异——往往差异点就是病灶:

// WORKING: ProductList.tsx function ProductList({ products, loading }) { if (loading) return <Spinner />; if (!products) return null; // ← Handles undefined case return products.map(p => <ProductItem key={p.id} {...p} />); } // BROKEN: UserList.tsx function UserList({ users, loading }) { if (loading) return <Spinner />; // Missing: !users check return users.map(u => <UserItem key={u.id} {...u} />); // 💥 Crashes }

2.3 记录全部差异

AspectWorking (ProductList)Broken (UserList)
Null checkif (!products)Missing
Default valueproducts ?? []None
Loading handledBefore renderBefore render
Error handledReturns ErrorStateMissing

差异表让"正常 vs 异常"的差距一目了然,是形成假设的直接输入。


Phase 3:假设验证

目标:用受控实验验证你的理解是否正确。

3.1 形成具体、书面的假设

## Hypothesis #1 **Statement:** The crash occurs because `users` is undefined when the query is complete but returns no data. **Prediction:** Adding a null check before `.map()` will prevent the crash. **Test:** Add `if (!users) return null;` before the map call.

好的假设必须包含三要素:陈述(Statement)可观测的预测(Prediction)最小验证实验(Test)

3.2 用最小变更验证

// Change ONLY one thing function UserList({ users, loading }) { if (loading) return <Spinner />; if (!users) return null; // ← Single change return users.map(u => <UserItem key={u.id} {...u} />); }

3.3 一次只改变一个变量

## Test Results | Hypothesis | Change | Result | Conclusion | |------------|--------|--------|------------| | #1: Null check | Add `if (!users)` | ✓ Pass | Confirmed | Do NOT test multiple hypotheses simultaneously.

严禁同时验证多个假设——否则无法判断究竟是哪个改动生效。这与仓库的调试红线完全一致:SKILL.md 的 MUST NOT DO 明令 "Make multiple changes at once"。


Phase 4:实现

目标:带防护措施地永久修复 bug,而不是打补丁。

4.1 先写失败的测试用例

在动手改代码之前,先让测试"证明 bug 存在":

describe('UserList', () => { it('should handle undefined users gracefully', () => { // This test should FAIL before the fix const { container } = render(<UserList users={undefined} loading={false} />); expect(container).not.toThrow(); expect(screen.queryByRole('list')).not.toBeInTheDocument(); }); });

这条测试在修复前必须失败(当前实现没有空值保护),修复后通过。TDD 的红绿循环保证了修复的可验证性。对应 SKILL.md 中 MUST DO 的 "Add regression tests after fixing"。

4.2 实现针对根因的单一修复

function UserList({ users, loading }: UserListProps) { if (loading) return <Spinner />; if (!users || users.length === 0) { return <EmptyState message="No users found" />; } return ( <ul role="list"> {users.map(u => <UserItem key={u.id} {...u} />)} </ul> ); }

注意这里比最初的假设多了一个边界:不仅处理undefined,还处理空数组并渲染专门的EmptyState,这是对根因(查询返回空数据)的完整覆盖,而非只堵住崩溃点。

4.3 验证没有产生新的破坏

# Run full test suite npm test # Run specific component tests npm test UserList # Run integration tests npm run test:integration # Verify in browser # 1. Normal case: 50 users # 2. Empty case: 0 users # 3. Loading case: spinner shows # 4. Error case: error message shows

验证覆盖四类场景:正常数据、空数据、加载中、出错态。只有全部通过,才算修复完成。SKILL.md 的 Output Templates 也要求调试结束时给出四件套:Root Cause(根因)→ Evidence(证据)→ Fix(修复)→ Prevention(防复发措施)


三连修复阈值:连续三次失败后立即停止

连续 3 次修复尝试失败 → 停止(After 3 failed fix attempts → STOP)。

三次失败且失败点各不相同,通常意味着架构性问题,而不是孤立的 bug:

Fix Attempt 1: Added null check → New error in child component Fix Attempt 2: Fixed child component → New error in parent Fix Attempt 3: Fixed parent → Original error returns ↓ STOP. QUESTION ARCHITECTURE.

到达阈值时应该做什么

  1. 停止修补症状
  2. 记录失败的模式(每次修复又引入了什么新错误);
  3. 识别被违反的架构假设
  4. 提出结构性变更,而不是继续打补丁;
  5. 与团队讨论后再继续

这个"停手阈值"与决策流程图中的Question architecture分支衔接:当修复尝试次数达到上限仍未通过测试时,流程就进入架构反思,而不是退回 Phase 1 无限重试。


需要重置流程的红旗信号

出现以下任何信号,立即停止当前动作、回到 Phase 1 重新开始:

Red FlagWhy It's Wrong
Proposing solutions before tracing data flowGuessing, not debugging
Making multiple simultaneous changesCan't identify which change worked
Skipping test creationBug will recur
"Let's try this and see if it works"Shotgun debugging
Fixing without understanding the causeBand-aid, not cure

这些信号本质上把调试从"科学实验"退化成"碰运气"。对照 SKILL.md 的 MUST NOT DO 清单可以进一步验证:跳过复现步骤、不做验证就猜测、一次改多处、假定已知根因、在生产环境无防护地调试,都是被明令禁止的行为。


决策流程图

整个调试流程可以用下面这张决策图概括,它是四阶段方法论的运行时总控:

┌──────────────────┐ │ Bug Reported │ └────────┬─────────┘ │ ┌──────────────▼──────────────┐ │ Can you reproduce it? │ └──────────────┬──────────────┘ No │ Yes ┌────────────────┴────────────────┐ ▼ ▼ ┌───────────────┐ ┌─────────────────┐ │ Get more info │ │ Trace data flow │ └───────────────┘ └────────┬────────┘ │ ┌──────────────▼──────────────┐ │ Do you understand the cause? │ └──────────────┬──────────────┘ No │ Yes ┌────────────────────────┴─────────┐ ▼ ▼ ┌───────────────┐ ┌─────────────────┐ │ Study working │ │ Write hypothesis│ │ examples │ └────────┬────────┘ └───────────────┘ │ ┌───────▼───────┐ │ Write test │ └───────┬───────┘ │ ┌───────▼───────┐ │ Implement │ └───────┬───────┘ │ ┌──────────────────▼──────────────────┐ │ Does test pass? │ └──────────────────┬──────────────────┘ No │ Yes ┌────────────────────────┴──────────┐ ▼ ▼ ┌───────────────┐ ┌─────────────────┐ │ Attempt < 3? │ │ Done │ └───────┬───────┘ └─────────────────┘ No │ Yes ┌───────────────┴─────────────────┐ ▼ ▼ ┌───────────────────┐ ┌─────────────────────┐ │ Question │ │ Return to Phase 1 │ │ architecture │ └─────────────────────┘ └───────────────────┘

关键分支解读:

  • 无法复现→ 不盲目猜测,先收集更多信息;
  • 不理解根因→ 去研究正常实现(Phase 2);
  • 理解根因→ 写假设、写测试、实现;
  • 测试未通过→ 判断是否达到三次尝试上限:未达到则返回 Phase 1 重新调查;达到则质疑架构。

配套武器库:工具、策略与常见模式

系统性调试方法论不是孤立的——它在 claude-skills 仓库中与 debugging-wizard 技能的其他参考文档组成完整武器库,在 SKILL.md 的路由表中按场景分发:

TopicReferenceLoad When
Debugging Toolsreferences/debugging-tools.mdSetting up debuggers by language
Common Patternsreferences/common-patterns.mdRecognizing bug patterns
Strategiesreferences/strategies.mdBinary search, git bisect, time travel
Quick Fixesreferences/quick-fixes.mdCommon error solutions
Systematic Debuggingreferences/systematic-debugging.mdComplex bugs, multiple failed fixes, root cause analysis

调试器速查(debugging-tools.md)

# Node.js / TypeScript node --inspect-brk dist/main.js # 暂停在首行,可接 Chrome DevTools # Python python -m pdb script.py # 启动 pdb python -m pdb -c continue script.py # 异常后 post-mortem 检查 # Go (Delve) dlv debug ./cmd/server # (dlv) break main.go:55 # (dlv) print myVar # Rust rust-gdb ./target/debug/app

代码内快速诊断技巧:

debugger; // JS 断点 console.log({ variable }); // 打印变量名+值 console.trace('Called from'); // 打印调用栈
breakpoint() # Python 3.7+ print(f"{variable=}") # Python 3.8+ 打印变量名+值

VS Code 调试配置示例(.vscode/launch.json):

{ "version": "0.2.0", "configurations": [ { "type": "node", "request": "launch", "name": "Debug TypeScript", "program": "${workspaceFolder}/src/main.ts", "preLaunchTask": "tsc: build", "outFiles": ["${workspaceFolder}/dist/**/*.js"] } ] }

核心调试策略(strategies.md)

StrategyBest For
Binary SearchUnknown bug location(未知 bug 位置)
Minimal ReproComplex bugs, reporting(复杂 bug、上报)
Git BisectRegression bugs(回归 bug)
Time TravelKnown error location(已知错误位置)
Rubber DuckLogic errors(逻辑错误)
Delta DebugRecent breakage(近期破坏)

例如二分查找定位未知 bug:注释掉一半代码,测试 bug 是否仍存在,据此确定 bug 所在半区,反复缩小范围直到隔离。最小复现策略则主张:新建最小项目、只保留能复现 bug 的代码、逐个移除依赖、把输入简化到最小失败用例。

高频 bug 模式识别(common-patterns.md)

PatternSymptomLikely Cause
Race conditionIntermittent failuresMissing await, async timing
Off-by-oneMissing first/last item<vs<=, array bounds
Null reference"undefined is not..."Missing null check
Memory leakGrowing memoryUncleaned listeners/intervals
N+1 queriesSlow with more dataFetching in loop
Type coercionUnexpected behavior==instead of===
Closure issueWrong variable valueLoop variable capture
Stale stateOld value usedReact state closure

常见修复范式(quick-fixes.md)也可作为 Phase 4 的直接参考,例如空引用用可选链user?.profile?.name ?? 'Unknown'、异步失败加.catch()或 try/catch、无限递归补递归基例等。注意:quick-fixes 是理解问题后的修复手段,绝不能反过来"先套修复再找问题"——这与系统性调试的第一原则相矛盾。


在 claude-skills 中的定位与触发方式

debugging-wizard 在仓库中归属 quality(质量)领域,其 frontmatter 定义的触发词包括:debug, error, bug, exception, traceback, stack trace, troubleshoot, not working, crash, fix issue。这意味着只要请求中涉及报错排查、崩溃分析、日志关联、根因定位,SKILL.md 就会被自动激活,并按场景加载上述参考文档。

它的核心工作流(Reproduce → Isolate → Hypothesize and test → Fix → Prevent)与本篇四阶段方法论一一对应;其 Output Templates 要求每次调试输出 Root Cause / Evidence / Fix / Prevention,确保调试结论可审计、可复用。

在项目级工作流中,bug 修复链路被编排为:

Bug Investigation: Debugging Wizard → Framework Expert → Test Master → Code Reviewer

【免费下载链接】claude-skills67 Specialized Skills for Full-Stack Developers. Transform Claude Code into your expert pair programmer.项目地址: https://gitcode.com/GitHub_Trending/claud/claude-skills

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询