K čemu slouží debugování a jak na něj vyzrát? Jeden z možných způsobů si popíšeme v dnešním článku.
Debugging jde ruku v ruce s programováním. Přesto, že někteří programátoři se nechávají slyšet, že píší takový kód, jenž není potřeba debugovat, existuje mnoho příležitostí, kdy dobrý (případně jakýkoli) debugovací nástroj může pomoci urychlit odhalení problému ve zdrojovém kódu. V praxi totiž programátor často upravuje cizí kód. Může se jednat o různé typy aplikací od jednodušších skriptů přes složitější aplikace až k rozsáhlým webovým systémům.
Ať už se potom jedná o jazyk PHP, Ruby nebo třeba Python, pro každý z nich je ve hře množství frameworků a odlišných programátorských přístupů. Pokud člověk vyvíjí v jednom jazyku, jeden projekt v daném frameworku, má debugging značně zpříjemněn. Problém však může nastat, když je programátor nucen čas od času přeskakovat mezi projekty různého stáří, kvality, struktury a rozsahu. Mezi aplikacemi, které programátor detailně nezná a jejichž fungování má prověřit a většinou upravit.
V tuto chvíli máme jako programátoři více variant. Zavrhněme strčit hlavu do písku a vezměme v potaz, že programátor je tvor líný a několikahodinové zírání do kódu bez napsání nové funkce jej zpravidla nebaví.
Pokud bychom vybrali variantu, že se zabýváme nefunkčním, neznámým nebo složitým projektem v PHP, zřejmě by téměř každý začal více či méně chaoticky v kódu psát var_export() nebo print_r() různých proměnných, kombinovaných s příkazy typu echo „I'm here“; echo „podmínka splněna“; a po pár minutách již jen echo „xxx“; apod.
Takto se dá odhalit jistě mnoho, je to však časově náročné, nezábavné a v neposlední řadě je potom potřeba všechny tyto výpisy odstranit. Díky tomu, že PHP v sobě žádný debugger nemá, troufnu si říci, že touto cestou jde většina programátorů.
Při práci na projektu nad jakýmkoli moderním frameworkem na tom budeme lépe a budeme volat pouze nějakou funkci, která nám přidá obsah proměnné do nějakého debugovacího výpisu, logu apod. Toto řešení je o mnoho pohodlnější, ale pořád člověk musí nejdříve někam napsat volání dané funkce - většinou na více míst, a potom teprve sledovat „co se vlastně děje“.
Třetí možností je použití některého debuggeru pro daný jazyk. V případě PHP může jít například o Xdebug, Fire PHP apod. V tomto případě má programátor k dispozici pokročilý nástroj pro sledování běhu programu a jeho ladění, a to zejména pokud je tento debugger integrován do IDE, ve kterém člověk program píše. Ovšem použití tohoto debuggeru obvykle závisí na tom, zda je na daném počítači instalován, zda je dostupné IDE, které má možnost integrace tohoto debuggeru apod. Nehledě na to, že se může stát, že je třeba aplikaci debugovat (resp. zkontrolovat chování) třeba přímo na produkčním serveru, kde takovýto typ debuggeru nemáme k dispozici.
Ze všech výše uvedených variant zřejmě vyplývá, že žádné řešení není natolik univerzální, aby jeho použití bylo rychlé, jednoduché a možné na kterémkoli projektu bez nutnosti přidávat knihovnu, instalovat debugger nebo jinak zasahovat do aplikace. Chceme prostě vzít kód a vidět, co se v něm děje, kudy jde a co se nám plní do kterých proměnných. Zní to ideálně a krásně. V kompilovaných jazycích bychom s tímto ideálním řešením, které popíšu níže, asi měli problém. Ale v interpretovaném programovacím jazyku typu PHP, Ruby nebo Python tuto možnost máme. Chce to jen trochu si s jazykem pohrát a vytvořit automatizovaný nástroj, který dokáže modifikovat váš kód do podoby potřebné pro debugging a následně vrátit do původní podoby.
Nebudu zde psát konkrétní řešení, ale obecný nástin, jak toho dosáhnout. Prvně si určeme, pro který jazyk náš jednoduchý debugger má fungovat – zvolím jazyk PHP (chci debuggovat PHP aplikace). Nyní zvolme jazyk, ve kterém chceme jednoduchý debugger napsat. Může to být také PHP nebo jakýkoli jazyk, který dokáže rozumně pracovat s textem a upravovat ho. Sám jsem zvolil Ruby, ale může to být cokoli. Debugger bude potom fungovat jako konzolová aplikace spouštěná jako:
Jak už jsem psal, princip tohoto nástroje spočívá v tom, že daný zdrojový soubor modifikuje do podoby, kdy jsou logovány všechny důležité informace bez nutnosti označovat, jaké to mají být. Následně je daný skript spuštěn a na konec zdrojový soubor navrácen do původního stavu. Potom máme v log souboru dostupný celý průběh skriptu se všemi hodnotami. Chce to pár regulárních výrazů a ušetříte si hodiny odhalování problémů.
V log souboru máme dostupný kompletní průběh skriptu. Můžeme hledat a zkoumat, kudy skript běžel, jaké měl parametry, kdy měly které proměnné jaké hodnoty apod. Celé debugování nám nemění obsah původního souboru, ale pokud potřebujeme, můžeme si v kroku 7 tento soubor překopírovat na ostrý server a podívat se do logu na chování v konkrétním prostředí.
Jistě tento způsob debugování nebude pro každého, ale ten, kdo si najde čas na tuto vlastní implementaci, získá určitě mnoho výhod. Samotná implementace není nikterak zdlouhavá. Uvedený debug skript pro PHP i pro Ruby má v obou případech kolem sta řádků. Také je pro každý jazyk trochu jiný – využívá jeho specifika a loguje informace, které jsou v daném jazyce dostupné a důležité. Pro zajímavost přikládám příklad textového výstupu debug logu pro PHP, jedná se o velice jednoduchý, ale ne moc smysluplný příklad, který jen ilustruje fungování:
Soubor test.php
Soubor /tmp/.phpdebug