Bog🪲rak a szá🐞ít🐜gépben🐝
A bug (bogár) valamiféle hibás működést jelent egy szoftveren belül. Leggyakrabban ennek oka a hibás programkód vagy helytelen beállítás. Egy programozó életének jelentős részét az fedi le, hogy bug-ok után kutat a forráskódban, megpróbálja felderíteni az okukat és kijavítani őket. Ezt a folyamatot nevezzük bebug-olásnak (debugging).
A “bug” kifejezés használata a megmagyarázhatatlan hibákra már sok évtizeddel a számítógépek és programkódok megjelenése előtt is használatban volt a mérnöki zsargonban.
1947-ben Grace Hopper matematikus, programozó , az Amerikai Tengerészet admirálisa és informatikai legenda a Mark II nevű elektromechanikus számítógépen dolgozott csapatával a Harvard Egyetemen, amikor észrevették, hogy a gép nem működik megfelelően.
A hiba forrását kutatva megtalálták a bűnöst: egy valódi molylepkét, ami beszorult az egyik relébe. A rovart kiszedték és beragasztották a gép naplójába, mellé írva:
„First actual case of bug being found.” (Az első valódi eset, amikor bogarat találtunk.)
Minden bizonnyal nem ez az első eset, amikor egy számítógép nem működött megfelelően és meg kellett találni a probléma okát, de mindenképp ez az első dokumentált példa arra, hogy kicsit túlzottan is szó szerint volt bug-os egy számítógép.
A Debug-olás
A bug a hibás működés jelensége és kiváltó oka egyben. A problémaelhárítás két lépésből áll:
- a probléma okának megtalálása
- a probléma megszüntetése
Ezek közül a második lépés lényegében annyi, hogy helyesen írjuk meg a kódot és megfelelően állítjuk be a Unity Scene-t. Ez lehet kellően komplikált feladat is, gyakran azonban a megoldás triviális miután már megtaláltuk a kiváltó okot. Ezen helyes megoldás elkészítésével foglalkozik gyakorlatilag az összes többi lecke, ezért itt ezt most nem fogjuk bővebben tárgyalni.
Helyette az első lépéssel, a bug okának megtalálásával foglalkozunk behatóan. Ez a feladat nem más, mint egy nyomozómunka. Megpróbáljuk elcsípni egy programozási bűn elkövetőjét, a hibás kódrészletet, a rossz beállítást és mindezt mindig korlátozott információk alapján tesszük. A debug-olás egy kreatív folyamat. Minden bug egy kicsit más és nem csak nyers tudást, de logikát és intuíciót is kell használni a hatékony bogárírtáshoz.
Minden bug egyedi ezért nem lehet teljesen automatizálni a megtalálásukat, ám vannak módszerek és eszközök, amik segítségünkre lehetnek a feladatba, ezeket nézzük most át:
- Próbáld reprodukálni a problémát!
Előfordul, hogy egy probléma nyilvánvaló, folyamatos és egyértelműen szem előtt van. Ekkor ez a lépés triviális. Viszont olyan is előfordul, hogy egy bug rejtőzködőbb természetű és csak a legváratlanabb pillanatokban dugja fel a fejét és okoz hibás működést. Ekkor gyakran reménytelen a probléma gyökerének felderítése anélkül, ha nem tudjuk a hibát egyértelműen reprodukálni. A debug-olás enélkül nem több mint tapogatózás a sötétben.
Mik azok a körülmények, amik kellenek ahhoz, hogy megtörténjen a bug? Milyen esemény vagy események után történik meg? Ha ezek az információk már rendelkezésünkre állnak, már van valami a kezünkben, amin elindulhatunk.
Gyakran fogjátok nem érteni, hogy miért nem működik a kód, de meglepően gyakori jelenség lesz az is, hogy nem értitek, miért működik újra. Ekkor csábító lehet azt tenni, hogy egyszerűen nem foglalkoztok vele, de a legvalószínűbb, hogy valójában nem oldódott meg a probléma, csak megszüntek a feltételek, amikkel látható volt a hatása. Ebben az esetben az a legvalószínűbb, hogy valahol újra fel fogja dugni a fejét a legváratlanabb pillanatban.
Ekkor célszerű némi időt szánni arra, hogy megkeressétek és megértsétek a probléma okát. Ha azonban ez nem sikerül hamar, akkor nem elvetendő az a stratégia sem, hogy tovább álljatok a fejlesztésben és szemfülesen várjátok a bug újbóli megjelenését, amikoris lecsaphattok rá.
- Nem csak kód lehet hibás
Tartsd szem előtt, hogy egy hibás működést nem feltétlenül hibás kód okoz. A Unity Editoron belüli beállítások összessége is ugyanúgy okozhatja a nem várt működést.
Gyakori hibák az Editorban:
- Elfelejtettük feltenni a megírt komponenst a GameObject-hez vagy nem megfelelőhöz adtuk, esetleg jóhoz, de többször is.
- Elfelejtettük beállítani az értékeket az Inspector felületen. Ez igaz nem csak saját szkriptekre, de Unity beépített komponensekre is. ”Miért nem mozog a karakterem? Ja… Csak 0 volt beállítva sebességértéknek.”
- A gyerek GameObject-ek nem megfelelő pozícióban vannak a szülőhöz képest. Ezt könnyű elrontani akkor mikor odébb akarunk tenni egy objektumot, főleg akkor, ha ezen az objektumon belül egy gyerek tartalmazza a Renderer komponenst.
- Error üzenetek elolvasása
Előfordul, hogy egy hibaüzenetet is kapunk a Unity konzolon. Ezt sose hagyjuk figyelmen kívül. A hibaüzenet mindig létfontosságú információkat tartalmaz arról, hogy mi okozza a hibát. Azt is tartalmazza a jelentés, hogy a program mely sorában történt az esemény, ami kiváltotta a kapott üzenetet. Ha duplán a log-ra kattintunk az Visual Studio vagy bármi egyéb IDE automatikusan a kód megfelelő szkriptjének megfelelő sorára ugrik.
Ez azonban nem jelenti feltétlenül azt, hogy az adott soron kell módosítani. Lehet, hogy például egy rossz Editor beállítás az oka a hibának.
Gyakori futási idejű hibaüzenetek:
NullReferenceException
/UnassignedReferenceException
: Akkor fordul elő, amikor egy olyan objektumot próbálsz elérni futási időben, aminek az értéke null, azaz nem nem hivatkozik semmilyen példányra. Ez gyakran akkor történik meg, ha egy GameObject vagy komponens beállításhoz nem rendelsz referenciát az Inspector ablakban.MissingReferenceException
: Akkor fordul elő, amikor egy objektumot próbálsz elérni vagy használni, ami korábban létezett, de már el lett pusztítva.IndexOutOfRangeException
: Azokat a hibákat kezeli, amikor egy tömb elemét próbálod elérni, ami annak határain kívül van. Például, ha egy 10 elemű tömb 11. (10-es index-ű) elemét akarod olvasni vagy módosítani.System.InvalidOperationException
: Akkor történik meg, ha egy műveletet hibásan akarsz elvégezni. Például nem megfelelő paraméterértékekkel hívsz egy metódust.
- Debug.Log
Ezzel metódussal, könnyen belenézhetsz a program belső állapotába. Használatával kiírhatsz bármilyen értéket a konzora vagy akár pusztán jelezheted egy esemény megtörténtét. Arra is használható a Debug.Log()
, hogy felderítsd bizonyos események lefutásának sorrendját.
- Debug.Break
Lehetséges, hogy gyorsan változó paraméterek pontos értékét szeretnéd megvizsgálni egy fix esemény lefutásakor. Ekkor nem feltétlenül kell kiíratni ezt az értéket. Az is hasznos lehet, ha megállítod a játék futását kódból a Debug.Break()
metódussal és Editorban ellenőrzöd bármely objektum és komponens állapotát az Editor-ban.
- Inspector ablak Debug nézet
Használd a Unity Inspector Debug nézetet, ahhoz, hogy ne csak a szerializált változók állpotát tudod megnéznie komponenseken belül, de minden field-et.
Ezt a lehetőséget az Inspector alablak jobb felső sarkában előhívható menüben találod meg (három apró pont egymás fölött). Itt tudsz váltani Normal és Debug mód közt.
- IDE Debugger
A legnagyobb szabadságot ahhoz, hogy áttekintsd egy program belső állapotát és az események lefutásának sorrendjét az IDE-be épített Debugger-e adja.
Ehhez Visual Studio-ban az “Attach to Unity2 behetőségre kell kattintani.
Ezután, ha úgy nevezett “Break point”-okat hagytok egy sor mellett, akkor a program futása megáll, amikor az elérte az adott sort. Break point-ot a kód soraitól balra lévő szürke oszlopra kattintva tudsz lehelyezni. Ha megállt a kód, akkor bármely lokális és tagváltozó által tárolt értéket meg tudod lesni.
- Gizmos.Draw / Debug.Draw
Néha nem működik elég számokat látni, vizuálisan a 3D térben is ki szeretnénk rajzolni információkat. Ehhez használhatod a gizmókat a korábban tanult módon:
Gizmók rajzolása és a Color típus
Emellett a Debug.Draw
paranccsal kirajzolhatsz vonalakat és egyszerű alakokat a OnDrawGizmos
üzenetmetóduson kívül is. Ezt azonban csak ideglenesen debug célokra tedd!
- A Google a barátod
Ne félj rákeresni a problémára, olvasd el a dokumentációt, külsős cikkeket, fórumszálakat, amit csak találsz az adott problémáról.
Emellett ne feledd, még modernebb eszközeid is vannak 2022-től kezdve! Kérdezd meg nyugodtan az egyik elérhető AI chatbotot is a problémáról, mint például az OpenGPT vagy Bing Chat, hátha azok fognak tudni segíteni!
- Lokalizáld a problémát
Előfordul, hogy a szoftvered már túl komplex ahhoz, hogy megtaláld benne a probléma forrását. Ekkor az is segíthet, hogyha felépítesz egy kísérleti szituációt akár egy külön Scene-ben, ahol jól kontrolált feltételek mellett tudsz koncentrálni a hibás működésre.
Probléma megkerülése és elfedése, megoldása
Három módon lehet szembe szegülni egy problémával. Az egyik, hogy megtalálod az okát, jól megérted azt és kidolgozol egy megoldást arra, hogy ne jöjjön többé elő. Mondanom sem kell, hogy természetesen ez az a stratégia, ami minden esetben a leginkább ajánlott. Még akkor is amikor megszerettek egy bug-ot és elő szeretnétek azt léptetni feature-ré akkor is javasolt először megoldani a véletlen problémát és azután újra lefejleszteni jól átgondolt módon.
Azonban bizton állíthatom, hogy nem fogjátok mindig ezt a tiszta utat választani. Sok órás hasztalan debuggolás után meg fog kísérteni mindenkit a programozás sötétebb oldala, ami kevésbé elegáns megoldásokat fog a füledbe suttogni.
Az egyik ösvény, ami ehhez a sötét oldalhoz vezet az, mikor nem érted mi okozza a problémát de tudsz egy megoldást, amivel a hatása kiküszöbölhető. Ez az elfedése a problémának. A másik esetben szintén nem tudod megérteni a probléma okát ezért helyette egy teljesen más megoldást valósítasz meg: Megkerülöd a bugot.
Habár a fentiek egyike sem szép megoldás, őszintétlen lenne azt állítani, hogy tapasztalt fejlesztők nem követnek el ilyesmit állandóan. Inkább csak annyit kérek mindenkitől, hogy mielőtt ezen módszerek egyikéhez folyamodtok szánjatok időt a tisztességes megoldásra is.
Nem azért mondom ezt, mert valamiféle programozói vallás szertartását szeretném betartatni veletek. A megkerülő megoldások gyakran kevésbé elegánsak és átláthatók, mint az elsődleges ötletek. Talán azért sem ezt választottátok először. Még problémásabbak az elfedett problémák, mert a hiba pontos megértése nélkül sosem tudhatjátok, mikor támad fel és kel új életre a bug.