Amikor az ember vesz egy régi kertes házat, hajlamos úgy gondolni rá, mint egy kész dologra. Állnak a falak, működik a villany, folyik a víz, van fűtés, tető, kert. Persze akad majd néhány javítanivaló, de hát melyik házon nincs? Programozóként viszont egyre inkább úgy érzem, hogy egy régi ház valójában nem kész termék, hanem legacy kód. Ráadásul abból a fajtából, amihez nincs Git history, nincs dokumentáció, a korábbi fejlesztőket nem lehet megkérdezni, és ha valamit rosszul refaktorálsz, nem egy teszt bukik el, hanem elmegy az áram vagy elkezd folyni a víz.
„Ez csak egy apró javítás lesz”
A hasonlóság leginkább akkor válik nyilvánvalóvá, amikor nekiállsz valami elsőre teljesen jelentéktelen munkának. „Ezt csak gyorsan megcsináljuk.” A szoftverfejlesztésből jól ismert mondat. Csak arrébb kell rakni valamit, kicserélni egy alkatrészt, kijavítani egy hibát. Aztán kiderül, hogy mögötte van még három másik probléma, valaki húsz éve már megoldotta valahogy, arra később ráépült egy újabb megoldás, és délutánra már fogalmad sincs, hogyan jutottál el az eredeti feladattól odáig, hogy a fél rendszert bontod.
Egy régi házban a fal mögött futó vezeték, az ismeretlen eredetű cső vagy a három réteg egymásra rakott burkolat pontosan ugyanaz, mint egy tizenöt éves kódbázisban a megjegyzés nélküli workaround. Valószínűleg volt valami oka annak, aki csinálta, és az is lehet, hogy az akkori körülmények között teljesen értelmes megoldás volt. Csak az ok azóta elveszett, a megoldás viszont maradt.
Nincs dokumentáció
Egy új építésnél legalább elméletben léteznek tervek. Egy régi háznál viszont sokszor maga az épület a dokumentáció. Nem tudod, miért ott megy egy vezeték, miért van befalazva egy nyílás, miért fordul arra az a cső, vagy hogy egy furcsa megoldás tudatos döntés volt-e, szükségmegoldás, esetleg egyszerűen csak az eredménye annak, hogy akkor éppen az az anyag volt kéznél. Használat közben, bontáskor és javításkor kezded fokozatosan feltérképezni a rendszert, pontosan úgy, ahogy egy ismeretlen kódbázist is csak akkor kezdesz igazán megérteni, amikor először hozzá kell nyúlni.
Ráadásul attól, hogy valami húsz-harminc éve működik, még nem feltétlenül érted, hogyan működik. Ez az egyik legfurcsább tulajdonsága mind a legacy szoftvernek, mind egy régi háznak: a rendszer bizonyítottan üzemképes, mégis tele van olyan részekkel, amelyekhez az ember némi gyanakvással közelít. Nem azért, mert biztosan rosszak, hanem mert nem tudod, milyen feltételezésekre épülnek.
A technológiai adósság itt tényleg a falban van
Egy régi ház technológiai adóssága ráadásul nemcsak szép metafora, hanem sokszor szó szerint ott van a falban. Régi vezetékek, toldások, ideiglenes javítások, egymásra épített átalakítások és olyan megoldások maradnak utánunk, amelyeket ma már biztosan másképp csinálnánk. Ezek egy része azért született, mert nem volt pénz jobbra, más része azért, mert gyorsan kellett megoldani valamit, és biztos akad olyan is, ami már elkészültekor sem volt különösebben jó ötlet.
Amikor az ember elkezdi ezeket felfedezni, könnyű beleesni abba a gondolkodásba, hogy akkor mindent rendbe kell tenni, lehetőleg azonnal. Csakhogy a technológiai adósságot szoftverben sem azért fizetjük vissza, mert létezik, hanem azért, mert problémát okoz vagy várhatóan problémát fog okozni. Egy ronda, de stabil és elszigetelt kódrészlethez sem feltétlenül érdemes hozzányúlni csak azért, mert ma szebben meg tudnánk írni. Ugyanez igaz egy házra is: van, ami veszélyes és sürgős, van, ami hosszabb távon okozhat kárt, és van, ami egyszerűen csak nem tetszik. Ezeket nem érdemes egyforma súlyú problémaként kezelni.
A végtelen backlog
Talán mentálisan ez a legnehezebb része egy régi háznak: a backlog gyakorlatilag soha nem fogy el. Megcsinálsz öt dolgot, és közben észreveszel másik hármat. Rendbe teszel egy szobát, és a frissen elkészült rész mellett hirtelen sokkal jobban látszik, hogy a következő helyiség mennyire ráférne ugyanez. Kicserélsz egy régi szerelvényt, és az új mellett rögtön feltűnik az összes többi régi.
Emiatt nagyon könnyű azt érezni, hogy valójában nem is haladsz. Fejben ugyanis hajlamosak vagyunk nem a ház korábbi állapotához, hanem egy elképzelt kész állapothoz hasonlítani a jelent. Márpedig ebben az összehasonlításban szinte mindig veszíteni fogunk. A kész házban nincs lepattogzott festék, nincs következő felújítandó szoba, nincs gyanús cső és nincs „majd egyszer ezt is meg kellene csinálni”. A valóságban viszont valószínűleg mindig lesz.
Szerintem ennek az elfogadása sokat segít. Nem azért nem jutunk a végére, mert rosszul csináljuk, hanem azért, mert egy ház fenntartása nem olyan projekt, amelynek egyszer csak elfogynak a feladatai. Amint ezt sikerül elfogadni, a „még mindig mennyi minden van hátra” helyett valamivel könnyebb arra figyelni, hogy mennyi minden lett már jobb.
Nem rewrite kell, hanem folyamatos refaktorálás
Programozóként különösen csábító gondolat egy rossz rendszer láttán, hogy egyszerűbb lenne kidobni az egészet és nulláról újraírni. A tapasztalat aztán általában megtanítja, hogy a rewrite ritkán olyan egyszerű, mint amilyennek az elején látszik. Egy háznál pedig különösen nehéz lenne ezt megjátszani, mert miközben javítod, közben ugyanabban a rendszerben kell élned.
Ezért szerintem sokkal egészségesebb folyamatos refaktorálásként tekinteni rá. A fontos és veszélyes problémák kerülnek előre, a kevésbé sürgősek fel a backlogra, és időről időre egy-egy részét jobb állapotba hozzuk. Ha már bontunk egy falat, rendbe lehet tenni azt is, ami mögötte van. Ha egy régi rendszerhez hozzá kell nyúlni, lehet úgy megcsinálni, hogy utána valamivel jobb legyen, mint előtte. Nem kell minden alkalommal az egész házat megmenteni.
És igen, ehhez néha az is hozzátartozik, hogy tudatosan békén hagyunk valamit. Nem minden régi megoldás jelent aktív problémát. Attól, hogy ma már máshogy építenénk meg, még lehet, hogy évtizedek óta tökéletesen ellátja a feladatát, és jelenleg van öt másik dolog, amire sokkal értelmesebb időt és pénzt fordítani.
Néha a lezárt ticketeket is meg kell nézni
Ha a backlog végtelen, akkor különösen fontos időnként nemcsak azt nézni, mi van még rajta, hanem azt is, mi került már le róla. Egy ház ritkán ad olyan egyértelmű lezárást, mint egy projekt, ezért könnyen láthatatlanná válik a haladás. Pedig lehet, hogy tavaly még csöpögött az a cső, rossz volt az a konnektor, tele volt kacattal az a helyiség, vagy évek óta kerülgettél valamit, ami mára egyszerűen megszűnt problémának lenni.
Ezek külön-külön nem feltétlenül látványos eredmények. Sokszor még csak nem is azok a dolgok, amelyeket büszkén mutogat az ember egy felújításról készült előtte-utána fotón. De ha néha végiggondolod, mi minden változott egy-két év alatt, egészen más kép rajzolódik ki. Az apró commitokból idővel meglepően hosszú changelog lesz, és mentálisan szerintem fontos ezt is számon tartani.
A production közben fut
Az egész hasonlatnak talán ez a része tetszik a legjobban: egy lakott ház felújítása valójában folyamatos refaktorálás production környezetben. Ott alszol, főzöl, mosol, használod a vizet, a villanyt és a fűtést, miközben időnként egy-egy darabját szétszeded, kijavítod, majd remélhetőleg jobb állapotban rakod össze. Nem állíthatod le hónapokra a rendszert azért, hogy nyugodtan dolgozhass rajta, és általában tiszta lap sincs.
Talán ezért is érdemes egy régi házat nem valami elrontott dolognak tekinteni, amit egyszer végre „készre kell javítani”, hanem egy évtizedek óta futó rendszernek, amelynek most egy ideig mi vagyunk a karbantartói. Van benne legacy, van technológiai adósság, akadnak érthetetlen workaroundok, és időnként biztosan előkerül valami, amin percekig csak nézünk, hogy ezt vajon mégis miért így csinálták.
Nem kell egyszerre megoldani mindet. Elég, ha tudjuk, mi sürgős, mi várhat, és időnként visszanézünk arra is, mennyivel jobb állapotban van már a rendszer, mint amikor átvettük.
A cél végül itt sem a tökéletes kód, hanem az, hogy a következő verzió egy kicsit jobb legyen az előzőnél.