debugging-strategies について
debugging-strategies は、コード、性能、本番環境の問題を調べる開発者向けの体系的なデバッグスキルです。再現、情報収集、仮説、検証の流れを軸に、複数言語の例や高度な調査手法を扱います。
主な機能
- 01手順に沿って問題を再現・切り分け
- 02エラー・ログ・環境情報を収集
- 03仮説を立てて個別に検証
- 04二分探索と差分デバッグを活用
- 05性能・メモリ・断続的な障害を調査
- 06JavaScript、Python、Goのデバッグ例
活用シーン
- 01再現しにくい不具合の原因を追跡
- 02本番障害やクラッシュトレースを調査
- 03性能ボトルネックやメモリリークを分析
- 04バージョン比較でリグレッションを特定
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ ovachiever/ droid-tings --skill debugging-strategiesインストール後、Claude Code で/debugging-strategiesを入力して読み込まれたか確認します。
詳細
デバッグ戦略
実証済みの戦略、強力なツール、体系的なアプローチを活用して、デバッグを苛立たしい当てずっぽうから、体系的な問題解決へと変えましょう。
このスキルを使う場面
- 見つけにくいバグの原因を突き止める
- パフォーマンスの問題を調査する
- 不慣れなコードベースを理解する
- 本番環境の問題をデバッグする
- クラッシュダンプやスタックトレースを分析する
- アプリケーションのパフォーマンスをプロファイリングする
- メモリーリークを調査する
- 分散システムをデバッグする
基本原則
1. 科学的手法
1. 観察:実際にはどのような動作をしていますか? 2. 仮説:何が原因として考えられますか? 3. 実験:仮説を検証します 4. 分析:仮説は証明されましたか、それとも否定されましたか? 5. 繰り返し:根本原因が見つかるまで続けます
2. デバッグの心構え
決めつけない:
- 「Xのはずがない」— いいえ、あり得ます
- 「Yは変更していない」— それでも確認しましょう
- 「自分のマシンでは動く」— 理由を突き止めましょう
実践すること:
- 安定して再現する
- 問題を切り分ける
- 詳細なメモを取る
- あらゆることを疑う
- 行き詰まったら休憩する
3. ラバーダックデバッグ
コードと問題を声に出して説明します(ラバーダックや同僚、あるいは自分自身に向けて)。問題が見つかることがよくあります。
体系的なデバッグプロセス
フェーズ 1:再現
## Reproduction Checklist
1. **Can you reproduce it?**
- Always? Sometimes? Randomly?
- Specific conditions needed?
- Can others reproduce it?
2. **Create minimal reproduction**
- Simplify to smallest example
- Remove unrelated code
- Isolate the problem
3. **Document steps**
- Write down exact steps
- Note environment details
- Capture error messages
フェーズ 2:情報収集
## Information Collection
1. **Error Messages**
- Full stack trace
- Error codes
- Console/log output
2. **Environment**
- OS version
- Language/runtime version
- Dependencies versions
- Environment variables
3. **Recent Changes**
- Git history
- Deployment timeline
- Configuration changes
4. **Scope**
- Affects all users or specific ones?
- All browsers or specific ones?
- Production only or also dev?
フェーズ 3:仮説を立てる
## Hypothesis Formation
Based on gathered info, ask:
1. **What changed?**
- Recent code changes
- Dependency updates
- Infrastructure changes
2. **What's different?**
- Working vs broken environment
- Working vs broken user
- Before vs after
3. **Where could this fail?**
- Input validation
- Business logic
- Data layer
- External services
フェーズ 4:テストと検証
## Testing Strategies
1. **Binary Search**
- Comment out half the code
- Narrow down problematic section
- Repeat until found
2. **Add Logging**
- Strategic console.log/print
- Track variable values
- Trace execution flow
3. **Isolate Components**
- Test each piece separately
- Mock dependencies
- Remove complexity
4. **Compare Working vs Broken**
- Diff configurations
- Diff environments
- Diff data
デバッグツール
JavaScript/TypeScript のデバッグ
// Chrome DevTools Debugger
function processOrder(order: Order) {
debugger; // Execution pauses here
const total = calculateTotal(order);
console.log('Total:', total);
// Conditional breakpoint
if (order.items.length > 10) {
debugger; // Only breaks if condition true
}
return total;
}
// Console debugging techniques
console.log('Value:', value); // Basic
console.table(arrayOfObjects); // Table format
console.time('operation'); /* code */ console.timeEnd('operation'); // Timing
console.trace(); // Stack trace
console.assert(value > 0, 'Value must be positive'); // Assertion
// Performance profiling
performance.mark('start-operation');
// ... operation code
performance.mark('end-operation');
performance.measure('operation', 'start-operation', 'end-operation');
console.log(performance.getEntriesByType('measure'));
VS Code デバッガーの設定:
// .vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Debug Program",
"program": "${workspaceFolder}/src/index.ts",
"preLaunchTask": "tsc: build - tsconfig.json",
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
"skipFiles": ["<node_internals>/**"]
},
{
"type": "node",
"request": "launch",
"name": "Debug Tests",
"program": "${workspaceFolder}/node_modules/jest/bin/jest",
"args": ["--runInBand", "--no-cache"],
"console": "integratedTerminal"
}
]
}
Python のデバッグ
# Built-in debugger (pdb)
import pdb
def calculate_total(items):
total = 0
pdb.set_trace() # Debugger starts here
for item in items:
total += item.price * item.quantity
return total
# Breakpoint (Python 3.7+)
def process_order(order):
breakpoint() # More convenient than pdb.set_trace()
# ... code
# Post-mortem debugging
try:
risky_operation()
except Exception:
import pdb
pdb.post_mortem() # Debug at exception point
# IPython debugging (ipdb)
from ipdb import set_trace
set_trace() # Better interface than pdb
# Logging for debugging
import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
def fetch_user(user_id):
logger.debug(f'Fetching user: {user_id}')
user = db.query(User).get(user_id)
logger.debug(f'Found user: {user}')
return user
# Profile performance
import cProfile
import pstats
cProfile.run('slow_function()', 'profile_stats')
stats = pstats.Stats('profile_stats')
stats.sort_stats('cumulative')
stats.print_stats(10) # Top 10 slowest
Go のデバッグ
// Delve debugger
// Install: go install github.com/go-delve/delve/cmd/dlv@latest
// Run: dlv debug main.go
import (
"fmt"
"runtime"
"runtime/debug"
)
// Print stack trace
func debugStack() {
debug.PrintStack()
}
// Panic recovery with debugging
func processRequest() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Panic:", r)
debug.PrintStack()
}
}()
// ... code that might panic
}
// Memory profiling
import _ "net/http/pprof"
// Visit http://localhost:6060/debug/pprof/
// CPU profiling
import (
"os"
"runtime/pprof"
)
f, _ := os.Create("cpu.prof")
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
// ... code to profile
高度なデバッグ手法
手法 1:二分探索デバッグ
# Git bisect for finding regression
git bisect start
git bisect bad # Current commit is bad
git bisect good v1.0.0 # v1.0.0 was good
# Git checks out middle commit
# Test it, then:
git bisect good # if it works
git bisect bad # if it's broken
# Continue until bug found
git bisect reset # when done
手法 2:差分デバッグ
正常な状態と壊れた状態を比較します:
## What's Different?
| Aspect | Working | Broken |
|--------------|-----------------|-----------------|
| Environment | Development | Production |
| Node version | 18.16.0 | 18.15.0 |
| Data | Empty DB | 1M records |
| User | Admin | Regular user |
| Browser | Chrome | Safari |
| Time | During day | After midnight |
Hypothesis: Time-based issue? Check timezone handling.
手法 3:トレースデバッグ
// Function call tracing
function trace(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function(...args: any[]) {
console.log(`Calling ${propertyKey} with args:`, args);
const result = originalMethod.apply(this, args);
console.log(`${propertyKey} returned:`, result);
return result;
};
return descriptor;
}
class OrderService {
@trace
calculateTotal(items: Item[]): number {
return items.reduce((sum, item) => sum + item.price, 0);
}
}
手法 4:メモリーリークの検出
// Chrome DevTools Memory Profiler
// 1. Take heap snapshot
// 2. Perform action
// 3. Take another snapshot
// 4. Compare snapshots
// Node.js memory debugging
if (process.memoryUsage().heapUsed > 500 * 1024 * 1024) {
console.warn('High memory usage:', process.memoryUsage());
// Generate heap dump
require('v8').writeHeapSnapshot();
}
// Find memory leaks in tests
let beforeMemory: number;
beforeEach(() => {
beforeMemory = process.memoryUsage().heapUsed;
});
afterEach(() => {
const afterMemory = process.memoryUsage().heapUsed;
const diff = afterMemory - beforeMemory;
if (diff > 10 * 1024 * 1024) { // 10MB threshold
console.warn(`Possible memory leak: ${diff / 1024 / 1024}MB`);
}
});
問題の種類別デバッグパターン
パターン 1:断続的に発生するバグ
## Strategies for Flaky Bugs
1. **Add extensive logging**
- Log timing information
- Log all state transitions
- Log external interactions
2. **Look for race conditions**
- Concurrent access to shared state
- Async operations completing out of order
- Missing synchronization
3. **Check timing dependencies**
- setTimeout/setInterval
- Promise resolution order
- Animation frame timing
4. **Stress test**
- Run many times
- Vary timing
- Simulate load
パターン 2:パフォーマンスの問題
## Performance Debugging
1. **Profile first**
- Don't optimize blindly
- Measure before and after
- Find bottlenecks
2. **Common culprits**
- N+1 queries
- Unnecessary re-renders
- Large data processing
- Synchronous I/O
3. **Tools**
- Browser DevTools Performance tab
- Lighthouse
- Python: cProfile, line_profiler
- Node: clinic.js, 0x
パターン 3:本番環境のバグ
## Production Debugging
1. **Gather evidence**
- Error tracking (Sentry, Bugsnag)
- Application logs
- User reports
- Metrics/monitoring
2. **Reproduce locally**
- Use production data (anonymized)
- Match environment
- Follow exact steps
3. **Safe investigation**
- Don't change production
- Use feature flags
- Add monitoring/logging
- Test fixes in staging
ベストプラクティス
- まず再現する:再現できない問題は修正できません
- 問題を切り分ける:最小限のケースになるまで複雑さを取り除きます
- エラーメッセージを読む:たいてい役に立ちます
- 最近の変更を確認する:バグの多くは最近発生したものです
- バージョン管理を使う:Git の bisect、blame、履歴を活用します
- 休憩する:新たな視点でよりよく気づけます
- 調査結果を記録する:将来の自分に役立ちます
- 根本原因を修正する:症状だけでなく、根本原因を直します
よくあるデバッグの間違い
- 一度に複数の変更を加える:一度に一つずつ変更します
- エラーメッセージを読まない:スタックトレース全体を読みます
- 複雑な問題だと思い込む:実際には単純なことがよくあります
- 本番環境でデバッグログを使う:リリース前に削除します
- デバッガーを使わない:console.log が常に最適とは限りません
- すぐに諦める:粘り強く取り組めば成果につながります
- 修正をテストしない:実際に動作することを確認します
デバッグのクイックチェックリスト
## When Stuck, Check:
- [ ] Spelling errors (typos in variable names)
- [ ] Case sensitivity (fileName vs filename)
- [ ] Null/undefined values
- [ ] Array index off-by-one
- [ ] Async timing (race conditions)
- [ ] Scope issues (closure, hoisting)
- [ ] Type mismatches
- [ ] Missing dependencies
- [ ] Environment variables
- [ ] File paths (absolute vs relative)
- [ ] Cache issues (clear cache)
- [ ] Stale data (refresh database)
リソース
- references/debugging-tools-guide.md:ツールに関する包括的なドキュメント
- references/performance-profiling.md:パフォーマンスのデバッグガイド
- references/production-debugging.md:稼働中のシステムのデバッグ
- assets/debugging-checklist.md:簡易リファレンスチェックリスト
- assets/common-bugs.md:よくあるバグのパターン
- scripts/debug-helper.ts:デバッグ用ユーティリティ関数
コメント
Markdown 対応