systematic-debugging
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSystematic Debugging
系统调试(Systematic Debugging)
엄격한 디버깅 워크플로우다. 버그, 테스트 실패, 예기치 않은 동작을 다룰 때 사용한다.
핵심 목적은 세 가지다.
- 증상이 아니라 원인을 고친다.
- 추측 기반 수정을 막는다.
- 실패를 테스트로 고정한 뒤 수정한다.
这是一套严格的调试工作流,用于处理Bug、测试失败、异常行为等场景。
核心目标有三个:
- 修复根因而非表面症状
- 避免基于猜测的修改
- 先通过测试锁定失败场景再进行修复
Hard Gates
硬性准则
다음 규칙은 예외 없이 따른다.
- 재현 또는 관측 가능 상태를 만들기 전에는 수정하지 않는다.
- 원인 가설을 명시하기 전에는 수정하지 않는다.
- 실패 테스트 또는 동등한 재현 장치를 만들기 전에는 수정하지 않는다.
- 한 번에 하나의 가설만 검증한다.
- 수정 시 "while I'm here" 리팩터링을 금지한다.
- 수정 시도가 3번 실패하면 추가 패치 전에 구조적 문제를 의심한다.
이 과정을 어기는 것은 디버깅 실패로 본다.
以下规则无例外必须遵守:
- 未构建可复现或可观测状态前不进行修复
- 未明确根因假设前不进行修复
- 未编写失败测试用例或等价复现工具前不进行修复
- 每次仅验证一个假设
- 修复时禁止「顺便」做无关重构
- 连续3次修复失败后,在追加补丁前先排查是否存在结构性问题
违反以上流程即视为调试失败。
When To Use
适用场景
다음 상황이면 이 스킬을 사용한다.
- 테스트가 실패할 때
- 운영 또는 로컬에서 버그가 발생할 때
- 예상과 다른 응답, 상태, 렌더링, 쿼리 결과가 나올 때
- 성능 저하, 타임아웃, 레이스 컨디션, 간헐 실패를 조사할 때
- 이미 한 번 이상 고쳤는데 다시 깨졌을 때
다음 핑계는 허용하지 않는다.
- "간단해 보여서 바로 고치면 된다"
- "시간이 없으니 일단 패치하고 보자"
- "이거 같으니까 그냥 바꿔보자"
出现以下情况时可使用本工作流:
- 测试失败时
- 线上或本地环境出现Bug时
- 出现不符合预期的响应、状态、渲染、查询结果时
- 排查性能下降、超时、竞态条件、偶发失败问题时
- 问题已经修复过一次又再次复现时
不允许以下借口:
- "看起来很简单,直接改就行"
- "没时间了,先打个补丁再说"
- "感觉是这个问题,直接改改试试"
Required Output Contract
必要输出约定
이 스킬을 사용할 때는 내부적으로 아래 항목을 반드시 고정한다.
- Problem statement: 무엇이 잘못되었는지 한 문장으로 정의
- Reproduction path: 어떻게 실패를 재현하거나 관측할지
- Evidence: 실제 관측 결과
- Root-cause hypothesis: 왜 이 문제가 발생한다고 보는지
- Failing guard: 실패 테스트, 재현 스크립트, 로그 검증 중 하나
- Fix: 원인에 대한 단일 수정
- Verification: 수정 후 재현 경로와 관련 테스트 결과
이 7개 중 빠진 항목이 있으면 아직 끝난 일이 아니다.
使用本工作流时必须明确以下7项内容:
- 问题描述:用一句话定义具体问题
- 复现路径:说明如何复现或观测到失败现象
- 证据:实际观测到的结果
- 根因假设:你认为问题出现的原因
- 失败防护:失败测试用例、复现脚本、日志校验三者之一
- 修复方案:针对根因的单一修改
- 验证结果:修复后复现路径的执行结果和相关测试结果
以上7项缺少任意一项都不算调试完成。
Workflow
工作流程
반드시 아래 순서로 진행한다.
必须严格按照以下顺序执行:
Phase 1. Define The Problem
阶段1:定义问题
먼저 문제를 축약한다.
- 실제 기대 동작은 무엇인가
- 실제 관측 동작은 무엇인가
- 영향 범위는 어디까지인가
- 항상 재현되는가, 간헐적인가
출력 형식:
text
Problem: <expected> but got <actual> under <condition>증상과 추측을 섞지 않는다.
text
Good: Product detail API returns 500 when brand is null.
Bad: Serializer is broken because brand mapping seems wrong.首先提炼核心问题:
- 预期的正确行为是什么
- 实际观测到的行为是什么
- 影响范围有多大
- 是必现问题还是偶发问题
输出格式:
text
Problem: <expected> but got <actual> under <condition>不要混合症状和猜测:
text
正确示例: Product detail API returns 500 when brand is null.
错误示例: Serializer is broken because brand mapping seems wrong.Phase 2. Reproduce Or Instrument
阶段2:复现或加埋点
수정 전에 실패를 다시 볼 수 있어야 한다.
우선순위:
- 기존 테스트로 재현
- 최소 통합 테스트로 재현
- 단위 테스트로 재현
- 재현 스크립트 또는 명령으로 관측
- 로그/계측 추가 후 관측
규칙:
- 재현 경로는 가능한 한 가장 작게 만든다.
- UI에서만 보이는 버그라도 더 아래 계층에서 재현 가능하면 그쪽을 선호한다.
- 간헐 실패면 로그, 입력, 시간, 동시성 조건을 추가해 관측성을 높인다.
- 재현되지 않으면 수정으로 넘어가지 말고 관측 수단을 늘린다.
재현 불가 상태에서 해야 할 일:
- 입력값 기록
- 환경 차이 확인
- 최근 변경점 확인
- 경계 지점별 로그 추가
- 동일 증상을 만드는 더 작은 조건 탐색
修复前必须能够复现失败现象。
复现优先级:
- 通过现有测试用例复现
- 通过最小集成测试复现
- 通过单元测试复现
- 通过复现脚本或命令观测
- 添加日志/埋点后观测
规则:
- 复现路径尽可能简化
- 即使是仅在UI上出现的Bug,如果能在下层架构复现则优先选择下层复现
- 针对偶发失败,通过补充日志、输入、时间、并发条件提升可观测性
- 无法复现则不要进入修复环节,优先补充观测手段
无法复现时的处理方案:
- 记录输入值
- 排查环境差异
- 确认近期变更点
- 在边界节点添加日志
- 探索能触发相同症状的最小条件
Phase 3. Gather Evidence
阶段3:收集证据
관측 가능한 사실만 모은다.
항상 확인할 것:
- 에러 메시지와 스택트레이스 전문
- 실패 입력값
- 최근 변경 파일 또는 커밋
- 환경/설정 차이
- 호출 경로와 데이터 흐름
멀티 컴포넌트 문제에서는 경계마다 확인한다.
예시:
- controller -> application -> service -> repository
- client -> API -> external service
- scheduler -> batch service -> database
각 경계에서 확인할 것:
- 무엇이 들어왔는가
- 무엇이 나갔는가
- 어떤 값이 변형되었는가
- 어떤 조건에서만 깨지는가
문제 위치를 특정하기 전에는 고치지 않는다.
仅收集可观测的客观事实:
必须确认项:
- 完整的错误信息和栈追踪
- 触发失败的输入值
- 近期变更的文件或提交
- 环境/配置差异
- 调用路径和数据流
多组件协作的问题需要在每个边界节点确认:
示例边界:
- controller -> application -> service -> repository
- client -> API -> external service
- scheduler -> batch service -> database
每个边界需要确认:
- 输入值是什么
- 输出值是什么
- 哪些值发生了变更
- 仅在什么条件下会出现问题
未定位问题位置前不要进行修复。
Phase 4. Isolate Root Cause
阶段4:隔离根因
원인 후보를 하나만 세운다.
형식:
text
Hypothesis: <root cause> because <evidence>좋은 가설의 조건:
- 단일 원인을 가리킨다
- 관측 증거와 연결된다
- 작은 실험으로 반증 가능하다
나쁜 가설의 예:
- "어딘가 비동기 문제가 있는 것 같다"
- "직렬화 쪽 전체가 불안정한 듯하다"
원인을 소스까지 거슬러 올라간다. 오류가 깊은 스택에서 보이면 증상이 아니라 입력의 출처를 추적한다.
每次仅提出一个根因候选:
格式:
text
Hypothesis: <root cause> because <evidence>好的假设的条件:
- 指向单一原因
- 和观测到的证据关联
- 可以通过小型实验证伪
坏的假设示例:
- "感觉哪里有异步问题"
- "序列化模块整体好像不太稳定"
要溯源到根因的源头代码,如果错误出现在深层调用栈,不要只关注表面症状,要追踪输入的来源。
Phase 5. Lock The Failure
阶段5:锁定失败场景
수정 전에 실패를 고정한다.
우선순위:
- 자동화된 failing test
- 기존 테스트에 회귀 케이스 추가
- 최소 재현 스크립트
- 로그/어설션 기반 임시 검증 장치
규칙:
- 가능하면 자동화 테스트를 만든다.
- 수정 전에는 실패해야 한다.
- 수정 후에는 같은 경로에서 통과해야 한다.
- 테스트 이름은 무엇이 깨졌는지 드러내야 한다.
자동화 테스트를 쓸 수 있으면 스킬을 함께 사용한다.
test-driven-development修复前先锁定失败场景:
优先级:
- 自动化失败测试用例
- 在现有测试中添加回归用例
- 最小复现脚本
- 基于日志/断言的临时校验工具
规则:
- 尽可能编写自动化测试
- 修复前测试用例必须执行失败
- 修复后同一路径测试用例必须执行成功
- 测试名称要清晰体现失败的场景
如果可以编写自动化测试,可搭配工作流使用。
test-driven-developmentPhase 6. Implement A Single Fix
阶段6:执行单一修复
수정은 하나의 가설만 다룬다.
허용:
- 원인에 직접 대응하는 최소 코드 변경
- 검증에 필요한 최소한의 보조 수정
금지:
- 관련 있어 보이는 여러 수정 묶기
- 리팩터링 겸 수정
- 포맷/정리/이름 변경 끼워넣기
- 근거 없는 null-guard 추가
- 예외 삼키기
실패하면 즉시 다시 Phase 1 또는 Phase 3으로 돌아간다. 이전 가설이 틀렸다는 뜻이다.
一次修复仅处理一个假设:
允许的操作:
- 直接针对根因的最小代码修改
- 验证所需的最少辅助修改
禁止的操作:
- 合并多个看起来相关的修改
- 修复同时做重构
- 夹带格式调整/代码清理/命名修改
- 无依据地添加null防护
- 吞掉异常
如果修复失败,立刻回到阶段1或阶段3,说明之前的假设是错误的。
Phase 7. Verify And Close
阶段7:验证并闭环
아래를 모두 만족해야 종료한다.
- 원래 재현 경로가 더 이상 실패하지 않는다.
- 새 failing guard가 통과한다.
- 관련 테스트가 깨지지 않는다.
- 수정이 증상이 아니라 원인을 막는다는 설명이 가능하다.
간헐 버그라면 한 번 통과로 끝내지 않는다. 반복 실행 또는 조건 변화 하 검증이 필요하다.
满足以下所有条件才可结束调试:
- 原复现路径不再触发失败
- 新增的失败防护工具执行通过
- 相关测试用例没有被破坏
- 可以说明修复是针对根因而非仅解决表面症状
如果是偶发Bug,不要仅通过一次成功就判定修复完成,需要重复执行或变更条件多次验证。
Stop Conditions
停止条件
다음 상황이면 멈추고 프레임을 다시 잡는다.
出现以下情况时需要停下来重新梳理思路:
1. Reproduction Failed
1. 无法复现
여러 번 시도해도 재현이 안 되면:
- 관측 수단이 부족한지 본다.
- 환경 차이가 있는지 본다.
- 문제 정의가 잘못되었는지 본다.
재현이 안 되는데 코드를 바꾸는 것은 금지다.
多次尝试都无法复现问题时:
- 检查是否观测手段不足
- 检查是否存在环境差异
- 检查问题定义是否有误
无法复现的情况下禁止修改代码。
2. Three Failed Fixes
2. 连续三次修复失败
세 번 연속으로 수정이 빗나가면 이렇게 판단한다.
- 현재 이해가 틀렸거나
- 문제가 공유 상태, 경계 설계, 책임 분리 같은 구조 문제일 가능성이 크다
이 시점부터는 "네 번째 땜질"이 아니라 구조 논의가 필요하다.
连续三次修复都没有解决问题时,基本可以判定:
- 当前对问题的理解有误,或者
- 问题大概率是共享状态、边界设计、职责拆分等结构性问题导致
此时不应该尝试第四次补丁修复,而需要先讨论结构性问题。
3. No Failing Guard
3. 没有失败防护
실패 테스트나 동등한 재현 장치를 만들 수 없으면, 완료로 선언하지 않는다. 최소한 재현 명령과 관측 결과를 남긴다.
无法编写失败测试用例或等价复现工具时,不要宣称问题已解决,至少要留存复现命令和观测结果。
Red Flags
危险信号
아래 생각이 들면 즉시 멈추고 앞 단계로 돌아간다.
- "이 줄만 바꿔보면 될 것 같다"
- "로그는 나중에 보고 일단 수정해보자"
- "테스트는 나중에 추가하지 뭐"
- "한 번에 이것도 저것도 같이 고치자"
- "에러는 사라졌으니 원인은 몰라도 됐다"
出现以下想法时要立刻停下回到前序阶段:
- "我只要改这一行应该就好了"
- "日志后面再看,先改试试"
- "测试后面再加就行"
- "一次把这几个问题一起改了"
- "错误消失了就行,不用管根因"
Minimal Checklist
最简检查清单
실행 중에는 아래 체크리스트를 기준으로 스스로 검증한다.
- 문제를 한 문장으로 정의했다
- 실패를 재현하거나 관측 가능하게 만들었다
- 증거를 수집했다
- 단일 원인 가설을 만들었다
- 수정 전 실패 guard를 만들었다
- 단일 수정만 적용했다
- 같은 경로로 수정 후 검증했다
执行过程中对照以下清单自我校验:
- 已经用一句话定义清楚问题
- 已经可以复现或观测到失败现象
- 已经收集完相关证据
- 已经提出单一根因假设
- 修复前已经做好失败防护
- 仅执行了单一修复操作
- 修复后通过同一路径完成验证
Completion Standard
完成标准
이 스킬의 완료 기준은 "코드가 바뀌었다"가 아니다.
완료 기준:
- 문제 정의가 명확하다
- 실패가 수정 전에 고정되었다
- 수정이 원인과 연결된다
- 검증 결과가 남아 있다
이 네 가지가 없으면 디버깅은 끝난 것이 아니다.
本工作流的完成标准不是「代码已经修改」。
完成标准:
- 问题定义清晰明确
- 失败场景在修复前已经被锁定
- 修复方案和根因直接关联
- 留存了验证结果
缺少以上任意四点都不算调试完成。