debugging-strategies

Par wshobson · agents

Maîtrisez les techniques de débogage systématique, les outils de profilage et l'analyse des causes profondes pour traquer efficacement les bugs dans n'importe quelle base de code ou stack technologique. À utiliser lors de l'investigation de bugs, de problèmes de performance ou de comportements inattendus.

npx skills add https://github.com/wshobson/agents --skill debugging-strategies

Stratégies de Débogage

Transformez le débogage d'une corvée frustrante en résolution de problèmes systématique grâce à des stratégies éprouvées, des outils puissants et des approches méthodiques.

Quand Utiliser Cette Compétence

  • Traquer des bugs insaisissables
  • Investiguer les problèmes de performance
  • Comprendre des bases de code inconnues
  • Déboguer les problèmes de production
  • Analyser les dumps mémoire et les stack traces
  • Profiler la performance des applications
  • Investiguer les fuites mémoire
  • Déboguer les systèmes distribués

Principes Fondamentaux

1. La Méthode Scientifique

1. Observer : Quel est le comportement réel ? 2. Hypothétiser : Qu'est-ce qui pourrait le causer ? 3. Expérimenter : Testez votre hypothèse 4. Analyser : A-t-elle prouvé/réfuté votre théorie ? 5. Répéter : Jusqu'à trouver la cause racine

2. Mentalité de Débogage

Ne Pas Supposer :

  • « Ça ne peut pas être X » - Si, ça peut l'être
  • « Je n'ai pas changé Y » - Vérifiez quand même
  • « Ça marche sur ma machine » - Découvrez pourquoi

À Faire :

  • Reproduire de façon cohérente
  • Isoler le problème
  • Tenir des notes détaillées
  • Remettre en question tout
  • Prendre des pauses quand on est bloqué

3. Rubber Duck Debugging

Expliquez votre code et votre problème à haute voix (à un canard en caoutchouc, un collègue, ou vous-même). Cela révèle souvent le problème.

Processus de Débogage Systématique

Phase 1 : Reproduire

## Checklist de Reproduction

1. **Pouvez-vous la reproduire ?**
   - Toujours ? Parfois ? Aléatoirement ?
   - Des conditions spécifiques nécessaires ?
   - D'autres peuvent-ils la reproduire ?

2. **Créer une reproduction minimale**
   - Simplifier à l'exemple le plus petit
   - Supprimer le code non apparenté
   - Isoler le problème

3. **Documenter les étapes**
   - Écrire les étapes exactes
   - Noter les détails d'environnement
   - Capturer les messages d'erreur

Phase 2 : Recueillir les Informations

## Collecte d'Informations

1. **Messages d'Erreur**
   - Stack trace complet
   - Codes d'erreur
   - Sortie console/logs

2. **Environnement**
   - Version du système d'exploitation
   - Version du langage/runtime
   - Versions des dépendances
   - Variables d'environnement

3. **Modifications Récentes**
   - Historique Git
   - Timeline de déploiement
   - Modifications de configuration

4. **Portée**
   - Affecte tous les utilisateurs ou des utilisateurs spécifiques ?
   - Tous les navigateurs ou des navigateurs spécifiques ?
   - Production uniquement ou aussi dev ?

Phase 3 : Former une Hypothèse

## Formation d'une Hypothèse

En fonction des informations recueillies, demandez-vous :

1. **Qu'a changé ?**
   - Modifications récentes du code
   - Mises à jour de dépendances
   - Modifications d'infrastructure

2. **Qu'est-ce qui est différent ?**
   - Environnement fonctionnel vs cassé
   - Utilisateur fonctionnel vs cassé
   - Avant vs après

3. **Où ça pourrait échouer ?**
   - Validation des entrées
   - Logique métier
   - Couche données
   - Services externes

Phase 4 : Tester et Vérifier

## Stratégies de Test

1. **Recherche Binaire**
   - Commenter la moitié du code
   - Affiner la section problématique
   - Répéter jusqu'à trouver

2. **Ajouter du Logging**
   - console.log/print stratégiques
   - Suivre les valeurs des variables
   - Tracer le flux d'exécution

3. **Isoler les Composants**
   - Tester chaque élément séparément
   - Mocker les dépendances
   - Supprimer la complexité

4. **Comparer Fonctionnel vs Cassé**
   - Diff des configurations
   - Diff des environnements
   - Diff des données

Outils de Débogage

Débogage JavaScript/TypeScript

// Chrome DevTools Debugger
function processOrder(order: Order) {
  debugger; // L'exécution s'arrête ici

  const total = calculateTotal(order);
  console.log("Total:", total);

  // Point d'arrêt conditionnel
  if (order.items.length > 10) {
    debugger; // S'arrête seulement si la condition est vraie
  }

  return total;
}

// Techniques de débogage console
console.log("Value:", value); // Basique
console.table(arrayOfObjects); // Format tableau
console.time("operation");
/* code */ console.timeEnd("operation"); // Timing
console.trace(); // Stack trace
console.assert(value > 0, "Value must be positive"); // Assertion

// Profiling de performance
performance.mark("start-operation");
// ... code d'opération
performance.mark("end-operation");
performance.measure("operation", "start-operation", "end-operation");
console.log(performance.getEntriesByType("measure"));

Configuration VS Code Debugger :

// .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"
    }
  ]
}

Débogage Python

# Debugger intégré (pdb)
import pdb

def calculate_total(items):
    total = 0
    pdb.set_trace()  # Le debugger démarre ici

    for item in items:
        total += item.price * item.quantity

    return total

# Breakpoint (Python 3.7+)
def process_order(order):
    breakpoint()  # Plus pratique que pdb.set_trace()
    # ... code

# Débogage post-mortem
try:
    risky_operation()
except Exception:
    import pdb
    pdb.post_mortem()  # Déboguer au point d'exception

# IPython debugging (ipdb)
from ipdb import set_trace
set_trace()  # Meilleure interface que pdb

# Logging pour le débogage
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

# Profiler la 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 des plus lentes

Débogage Go

// Delve debugger
// Installation : go install github.com/go-delve/delve/cmd/dlv@latest
// Exécuter : dlv debug main.go

import (
    "fmt"
    "runtime"
    "runtime/debug"
)

// Afficher la stack trace
func debugStack() {
    debug.PrintStack()
}

// Récupération de panic avec débogage
func processRequest() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Panic:", r)
            debug.PrintStack()
        }
    }()

    // ... code qui pourrait paniquer
}

// Profiling mémoire
import _ "net/http/pprof"
// Visitez http://localhost:6060/debug/pprof/

// Profiling CPU
import (
    "os"
    "runtime/pprof"
)

f, _ := os.Create("cpu.prof")
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
// ... code à profiler

Techniques de Débogage Avancées

Technique 1 : Débogage par Recherche Binaire

# Git bisect pour trouver une régression
git bisect start
git bisect bad                    # Le commit actuel est mauvais
git bisect good v1.0.0            # v1.0.0 était bon

# Git vérifie le commit du milieu
# Testez-le, puis :
git bisect good   # si ça marche
git bisect bad    # si c'est cassé

# Continuez jusqu'à trouver le bug
git bisect reset  # quand vous avez terminé

Technique 2 : Débogage Différentiel

Comparez le fonctionnel et le cassé :

## Qu'est-ce qui est Différent ?

| Aspect       | Fonctionnel | Cassé          |
| ------------ | ----------- | -------------- |
| Environnement| Développement | Production |
| Version Node | 18.16.0     | 18.15.0        |
| Données      | BD vide     | 1M d'enregistrements |
| Utilisateur  | Admin       | Utilisateur régulier |
| Navigateur   | Chrome      | Safari         |
| Heure        | Pendant le jour | Après minuit |

Hypothèse : Problème basé sur l'heure ? Vérifiez la gestion des fuseaux horaires.

Technique 3 : Débogage par Traçage

// Traçage des appels de fonction
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);
  }
}

Technique 4 : Détection de Fuites Mémoire

// Chrome DevTools Memory Profiler
// 1. Prendre un snapshot de heap
// 2. Effectuer une action
// 3. Prendre un autre snapshot
// 4. Comparer les snapshots

// Débogage mémoire Node.js
if (process.memoryUsage().heapUsed > 500 * 1024 * 1024) {
  console.warn("High memory usage:", process.memoryUsage());

  // Générer un dump de heap
  require("v8").writeHeapSnapshot();
}

// Trouver les fuites mémoire dans les tests
let beforeMemory: number;

beforeEach(() => {
  beforeMemory = process.memoryUsage().heapUsed;
});

afterEach(() => {
  const afterMemory = process.memoryUsage().heapUsed;
  const diff = afterMemory - beforeMemory;

  if (diff > 10 * 1024 * 1024) {
    // Seuil de 10MB
    console.warn(`Possible memory leak: ${diff / 1024 / 1024}MB`);
  }
});

Patrons de Débogage par Type de Problème

Patron 1 : Bugs Intermittents

## Stratégies pour les Bugs Flaky

1. **Ajouter un logging extensif**
   - Logger les informations de timing
   - Logger toutes les transitions d'état
   - Logger les interactions externes

2. **Chercher les race conditions**
   - Accès concurrent à l'état partagé
   - Opérations asynchrones s'achevant dans le désordre
   - Synchronisation manquante

3. **Vérifier les dépendances de timing**
   - setTimeout/setInterval
   - Ordre de résolution des Promises
   - Timing des animation frames

4. **Test de charge**
   - Exécuter plusieurs fois
   - Varier le timing
   - Simuler la charge

Patron 2 : Problèmes de Performance

## Débogage de Performance

1. **Profiler d'abord**
   - Ne pas optimiser à l'aveugle
   - Mesurer avant et après
   - Trouver les goulots

2. **Coupables courants**
   - Requêtes N+1
   - Re-rendus inutiles
   - Grand traitement de données
   - E/S synchrone

3. **Outils**
   - Chrome DevTools Performance tab
   - Lighthouse
   - Python : cProfile, line_profiler
   - Node : clinic.js, 0x

Patron 3 : Bugs de Production

## Débogage de Production

1. **Recueillir des preuves**
   - Error tracking (Sentry, Bugsnag)
   - Logs d'application
   - Signalements utilisateur
   - Métriques/monitoring

2. **Reproduire localement**
   - Utiliser les données de production (anonymisées)
   - Correspondre à l'environnement
   - Suivre les étapes exactes

3. **Investigation sécurisée**
   - Ne pas changer la production
   - Utiliser les feature flags
   - Ajouter du monitoring/logging
   - Tester les correctifs en staging

Bonnes Pratiques

  1. Reproduire d'Abord : On ne peut pas corriger ce qu'on ne peut pas reproduire
  2. Isoler le Problème : Supprimer la complexité jusqu'au cas minimal
  3. Lire les Messages d'Erreur : Ils sont généralement utiles
  4. Vérifier les Modifications Récentes : La plupart des bugs sont récents
  5. Utiliser le Contrôle de Version : Git bisect, blame, historique
  6. Prendre des Pauses : Un regard neuf voit mieux
  7. Documenter les Résultats : Aider votre vous du futur
  8. Corriger la Cause Racine : Pas seulement les symptômes

Erreurs Courantes en Débogage

  • Faire Plusieurs Modifications : Changer une seule chose à la fois
  • Ne Pas Lire les Messages d'Erreur : Lire la stack trace complète
  • Supposer que C'est Complexe : Souvent c'est simple
  • Logging de Débogage en Prod : Supprimer avant de livrer
  • Ne Pas Utiliser le Debugger : console.log n'est pas toujours le mieux
  • Abandonner Trop Tôt : La persévérance paie
  • Ne Pas Tester le Correctif : Vérifier qu'il fonctionne réellement

Checklist Rapide de Débogage

## Quand Vous Êtes Bloqué, Vérifier :

- [ ] Erreurs d'orthographe (typos dans les noms de variables)
- [ ] Sensibilité à la casse (fileName vs filename)
- [ ] Valeurs null/undefined
- [ ] Décalage d'index de tableau
- [ ] Timing asynchrone (race conditions)
- [ ] Problèmes de portée (closure, hoisting)
- [ ] Incohérences de type
- [ ] Dépendances manquantes
- [ ] Variables d'environnement
- [ ] Chemins de fichier (absolu vs relatif)
- [ ] Problèmes de cache (vider le cache)
- [ ] Données obsolètes (rafraîchir la base de données)

Skills similaires