Systematické debugování – metoda místo náhodného zkoušení
Jak hledat chyby metodicky – reprodukce, hypotézy, bisekce, debugger a git bisect. Konkrétní postup a nástroje pro Python, JavaScript i server.
Debugování „metodou pokus–omyl“ funguje u malých chyb. U těch zákeřných vede k hodinám přepisování kódu, které nic nevyřeší. Systematický přístup je pomalejší na prvních pět minut a mnohem rychlejší celkově. Tady je postup, který funguje pro webovou aplikaci, skript i serverovou službu.
Krok 1: spolehlivě chybu reprodukujte
Chyba, kterou neumíte vyvolat, se nedá spolehlivě opravit – nevíte, jestli oprava zabrala. Zapište si:
- Přesné kroky k vyvolání.
- Očekávané chování vs. skutečné chování.
- Prostředí – verze jazyka, OS, prohlížeč, data.
Cíl je zmenšit reprodukci na minimum: místo „po kliknutí na objednávku v administraci“ mít „funkce calculate_vat(Decimal('0.1')) vrací 0“. Nejlepší je minimální reprodukci rovnou zapsat jako test – po opravě zůstane jako ochrana před návratem chyby.
Krok 2: přečtěte, co máte
Než začnete měnit kód, projděte celou chybovou hlášku, stack trace a logy. Spousta chyb je vyřešena tím, že si člověk konečně přečte druhý řádek výpisu.
Užitečné příkazy pro hledání v logu:
journalctl -u myapp --since "10 min ago" --no-pager
grep -n "ERROR" /var/log/myapp/app.log | tail -20
tail -f /var/log/nginx/error.log
Krok 3: formulujte hypotézu a ověřte ji
Neměňte kód naslepo. Formulujte konkrétní tvrzení: „Myslím, že user je None, protože session vypršela.“ Pak navrhněte pokus, který hypotézu potvrdí nebo vyvrátí:
- výpis hodnoty v daném místě,
- breakpoint v debuggeru,
- test s okrajovým vstupem.
Každý pokus zapisujte. Po hodině debugování si jinak nepamatujete, co už jste vyloučili.
Krok 4: zužujte prostor (bisekce)
Když nevíte, kde chyba je, dělte problém napůl:
- Data: funguje to s prvními 500 záznamy? S druhou půlkou?
- Kód: zakomentujte polovinu pipeline – projde to?
- Konfigurace: vraťte polovinu změn.
Každý krok vyloučí půlku možností. Ze 1000 podezřelých míst se na jedno dostanete zhruba za 10 kroků.
git bisect: bisekce v historii
Když „to minulý týden fungovalo“, nechte git najít commit, který chybu zavedl:
git bisect start
git bisect bad # aktuální stav je rozbitý
git bisect good v1.4.0 # tahle verze fungovala
# git přepne na commit uprostřed – otestujte a označte:
git bisect good # nebo: git bisect bad
# … opakujte, dokud git nevypíše první špatný commit
git bisect reset
Pokud máte test, který chybu odhalí, lze bisekci plně automatizovat:
git bisect run pytest tests/test_vat.py -x
Skript musí vrátit 0 pro „dobrý“ a nenulový kód (kromě 125, který znamená „přeskočit“) pro „špatný“.
Krok 5: používejte debugger, ne jen print
print je v pořádku, ale debugger vám ukáže všechny proměnné a dovolí krokovat.
Python – vestavěná funkce breakpoint() (Python 3.7+) zastaví program v pdb:
def calculate_vat(amount, rate):
breakpoint()
return amount * rate
Základní příkazy pdb: n (další řádek), s (vstoupit do funkce), c (pokračovat), p promenna (vypsat), l (zobrazit kód), w (stack), q (konec).
Node.js:
node --inspect-brk server.js
Pak otevřete v Chromu chrome://inspect nebo použijte debugger ve VS Code. V kódu funguje příkaz debugger;.
Prohlížeč: DevTools → Sources → klik na číslo řádku. Užitečné jsou podmíněné breakpointy (pravý klik → Add conditional breakpoint), např. order.id === 1042.
Krok 6: ověřte opravu a příčinu
Oprava je hotová, když:
- Původní reprodukce už chybu nevyvolá.
- Rozumíte, proč chyba vznikla. „Přidal jsem
if x is not Nonea funguje to“ není pochopení – proč tam bylNone? - Existuje test, který by chybu příště zachytil.
- Prověřili jste, zda stejná chyba není jinde (podobný kód, zkopírovaná funkce).
Časté pasti
- Měníte víc věcí naráz. Pak nevíte, co pomohlo. Jedna změna, jeden pokus.
- Debugujete jiný kód, než běží. Cache, neprovedený restart služby, starý build, jiné virtuální prostředí. Ověřte si to – přidejte zjevný log a zkontrolujte, že se objeví.
- Věříte předpokladům. „Tahle funkce určitě vrací seznam.“ Ověřte to.
- Neviditelné rozdíly: mezery na konci řetězce,
\r\nvs.\n, časová pásma,0.1 + 0.2 != 0.3u floatů.
Gumová kachnička a AI
Vysvětlení problému nahlas – třeba gumové kachničce na stole – často odhalí chybu, protože vás donutí projít předpoklady jeden po druhém. Stejně funguje i dobře napsaný dotaz na AI: popište reprodukci, očekávání, skutečnost a co už jste vyloučili. Režim Řešení problémů v ColdHost AI je postavený přesně na takovém postupném hledání příčiny.