Csináljunk legacyból modern szofvert, egy Angular frontend projekt élményei
angular, frontend, legacy
2025-06-30
Miért utálják az IT-sek a HR-eseket?
hr, recruitment, it
2025-01-19
PHP kódminőség fenntartás
php, qa, static code checking, phpunit, phpcs, phpmd, phpstan, churn, phpdd, psalm, phplint, phan
2024-10-17
Failed: bson encoding error: BSON element key cannot contain null bytes
mongo, mongodb, bson, null, key
2024-08-24
Nem bízol a kollégáidban? Akkor valamit rosszul csinálsz!
bizalom vezetokent
2023-05-03
Dolgok, amikről a programozók azt hiszik, hogy tudják, de tévednek
programozoi-tevhitek-falsehoods
2023-04-08
A programozóktól meg kell szabadulni
chatgpt no-code low-code
2023-01-22
Miért fontosak a személyes adatok egyáltalán?
privacyaware, privacy
2023-01-07
Egy tanmese a szerény, de tehetséges informatikusról, akit én csak Gézának hívok
privacyaware, privacy
2023-01-02
Beskatulyáznád magad egy termékkel? Gondold át még egyszer!
learning, vendorlockin, risky
2022-12-11
Rekrúterekről és állásajánlatokról
bérsáv, recruiter, relevancia
2022-10-30
"A hídon akkor kell átmenni, amikor odaérünk."​ - YAGNI
yagni, pagni
2022-10-17
"A lényeg, hogy a munka készen legyen!"
agile, estimation, becsles, scrum, home office
2022-08-20
Munka vs. hivatás, a klasszikus dilemma
hr, hobbi, munka, egyensuly, hivatas
2022-07-18
Miért nem fogok nálatok technikai interjún részt venni?
technikai interju, hr, recruit, leet code, coding challenge, take home challenge
2022-07-04
"Hogyan építsek kapcsolati tőkét, ha karriert szeretnék váltani?"
linkedin, tippek, trukkok
2022-06-10
Junior/Medior/Senior, hogyan mérjük?
junior, medior, senior, hr, grade, level, experience
2022-05-09
11 tipp frontendeseknek, hogyan tegyék hatékonyabbá a munkájukat
frondend, vscode, angular
2021-10-31
Motion zoom - mozgás alapú képrekonstrukció
#52het
2021-06-01
Gesture Launcher
#52het
2021-05-31
CellEvent, első Android alkalmazásom
#52het
2021-05-19
Notebookcheck, azaz hogyan válasszuk ki a legjobb ár-érték arányú eszközt
#52het
2021-05-18
Torrent multiplexer
#52het
2021-05-17
Process watcher, logger
#52het
2021-05-05
Lazy loading material dialog content
lazy loading, angular, material, dialog
2020-12-28
Runtime configuration loading in Angular
angular, runtime, configuration, settings, environment, production
2020-03-29
How to start an Angular project?
angular
2020-03-11
Az 52 hét projekt
#52het
2020-01-01
Akkutöltöttség-jelző
#52het
2020-01-01
NetClub - Kollégiumi internetszolgáltató
#52het
2019-12-31
DeeJayy - Lost Terminal
#52het
2019-12-31
Counter Strike monitor
#52het
2019-12-31
Kollégiumi CS bajnokság 2005
#52het
2019-12-31
Mozgásérzékelős képrögzítő, Camera Capture
#52het
2019-12-30
Többszörös host pingelő
#52het
2019-12-30
Sávszélesség mérő, tesztelő
#52het
2019-12-30
Generáljunk hamis adatokat
#52het
2019-12-30
SQL lekérdezések parancssorból, odbc-vel
#52het
2019-12-30
Nonogram generátor (aka. "Fesse feketére")
#52het
2019-12-30
Egyedi chat alkalmazás, kliens és szerver
#52het
2019-12-29
FontSelector - betűtípusválasztó / font preview
#52het
2019-12-28
Saját hálózati kommunikációs segédszoftver - sox
#52het
2019-12-28
Csoportos e-mail küldő szoftver Delphiben
#52het
2019-12-28
Universal Api caller module for Angular 7-9 With NGRX state management
Ngrx, API, Effects, HttpClient
2019-07-02
A leghosszabb projekt
#52het
2019-04-19
Legelső kioszk projektem: Stari Sör Jukebox
#52het
2019-02-28
BPM számláló
#52het
2018-11-01
Assembly féléves beadandók
#52het
2018-11-01
Chatbot before it was cool
#52het
2018-10-30
StartX - Cseréljük ki a windows tálcáját és a Start menüt
#52het
2018-10-28
What? - fájltípus azonosító
#52het
2018-10-27
Transport Tycoon DirectX
#52het
2018-10-26
Diff - fájlösszehasonlító
#52het
2018-10-26
De Facto - Szoftverfelügyelet
#52het
2018-10-25
CD és DVD katalogizáló
#52het
2018-09-24
MP3 segédeszközök
#52het
2018-09-24
Keylogger - azaz billentyűleütés-figyelő és naplózó alkalmazás
#52het
2018-08-29
Az örök projekt: személyes weboldal és blog
#52het
2018-08-14
Szógyakorló nyelvtanuláshoz
#52het
2018-08-13
Warzone 2100 mentett játék szerkesztő
#52het
2018-08-13
Rejtett Windows-beállításokat konfiguráló program: TweakMaster
#52het
2018-08-13
A DrótPostaGalamb levelezőprogram adatfájljainak dekódolása
#52het
2018-08-13
Privacy jegyzet
2018-07-30
Egy éve ilyenkor
2018-07-25
The Matrix - konzol szimuláció
#52het
2018-07-13
Kakaóreceptkönyv
kakaó
2018-06-29
Crackelés!
#52het
2018-06-22
A K.I.T.T. challenge
#52het
2018-06-18
Doom 2 botokkal
#52het
2018-06-16
Römi játék Delphiben
#52het
2018-06-09
MeetsCow & DeeJayy - Intro
#52het
2018-06-09
Direct viewer - bitmap megjelenítő
#52het
2018-06-09
bazMAG
#52het
2018-06-09
Console Vision - Konzolos ablakkezelő Delphiben
#52het
2018-05-01
Quake 2 egy floppyn
#52het
2018-04-20
Játék-kitömörítők
#52het
2018-04-12
Tetszőleges program elrejtése Windows tálcáról
#52het
2018-04-05
Személyre szabás
#52het
2018-03-28
A year with Angular 5, 6 - Angular 2018
#angular5 #angular #resources #articles
2018-03-16
Az ikon evolúciója
#52het
2018-03-14
Betűtípusok
#52het
2018-03-04
Billentyűzet-gyakorló
#52het
2018-02-28
Zenél is a DeeJayy?
#52het
2018-02-22
Térképrajzoló az Ascii 3D labirintushoz
#52het
2018-02-19
Ascii 3D labyrinth
#52het
2018-02-14
52 hét - 52 projekt, avagy #eletem
#52het
2018-02-14
Dockerezzünk virtualizált környezetben!
docker, xen, ubuntu
2017-11-12
A cloud-initramfs-copymods hatásai paravirtualizált környezetben
ubuntu, xen, copymods, docker, docker-ce, docker.io
2017-11-11
Virtualizáljunk Xen 4.6-tal Ubuntu 16-on (Xenial)
ubuntu, xen, virtualizálás, hypervisor, debootstrap
2017-11-04
Álláskeresésem története
álláskeresés, it, fejvadászok, linkedin, job
2017-10-24
FAR Manager competitors
far manager, file managers
2010-01-01
Blog
blog
2001-01-02

Volt egy projekt

Csatlakoztam egy frontend projekthez, amiről már az első perc előtt tudtam, hogy alacsony kódminőségű (a híre ugyanis megelőzte), és bár aktív fejlesztés alatt van, legacy érzésű a vele való munka. Az új feature-ök fejlesztéséhez a meglévő rossz/elavult mintákat használják, semmi indítattás nem mutatkozott a dolgok jobbá tételére. A tétlenség fluktuációt eredményezett a fejlesztők körében (az évek alatt 50+ ember dolgozott a kódon), a fluktuáció pedig ignoránssá tette őket, így egy önmagába roskadó spirált generálva.

A projektet egy olyan szoftvercég emberei rakták össze eredetileg, amelyik arról híres, hogy a minőséget inkább mennyiséggel próbálja kompenzálni, sikeretelenül. A megbízók azt hitték, hogy a unit test code coverage magas százelékú előírása minőségi kódot eredményezhet - természetesen tévedtek, a "tesztek" gyakorlatilag akadályai voltak a szoftver jobbá tételének később, és nem voltak többek szimpla függvényhívásoknál, valódi ellenőrzés (assertion), lényegében tesztelés nélkül.

Angular/TypeScript projekt, tehát lett volna lehetőség a kvázi-statikus típusosság kihasználásának, mégis a legtöbb helyen figyelmen kívül volt hagyva, remek táptalajt szolgáltatva az olyan hibáknak, amik csak a fejlesztői környezeten kívül fordulnak elő és közvetlenül a végfelhasználók szeme előtt jelentkeznek. Ha voltak is típusok definiálva, gyakori volt az azonos nevű és célú, viszont teljesen különböző helyen és különböző módon implementálva (mindenhol épp csak annyi, amennyi a típusellenőrzőt elcsitítja, semmi több).

A stabilitást további futásidejű (feature flag, autentikáció, cookie consent, stb) és fejlesztési idejű (nyelvi fordítások, ikonpakkok) külső függőségekkel veszélyeztetjük: 3rd party szolgáltatók, amik rendelkezésre állása nem kiszámítható, sem számonkérhető, de az is maximum vihar utáni kármentés, a bukás minden alkalommal a megbízó nevéhez fűződik.

Miután a projekt backendje is nagyon sok függőséggel rendelkezik, amik néhol egymásra is támaszkodnak, integrálódnak, a teljes képet megszerezni sok idő volt (még most sincs meg teljesen).

A gondolat, hogy ezzel valamit kezdeni kell, már azelőtt megszületett, hogy a projekthez csatlakoztam. "Ezt újra kellene írni" - gondoltam és nyitottam meg először a kódot. De elég ideje vagyok a szakmában, hogy tudjam, hogy egy ekkora méretű és ilyen szerepű projektet, ekkora mérnöki kitettséggel nem lehet csak úgy újraírni, ki kell találni rá egy stratégiát. Ezen a stratégián gondolkodtam a megismerés ideje alatt, majd elkezdtem összeszedni azokat az ötleteket, amik szerintem a jó sínre tehetik - életében először - a projektet.

A problémák

Az egyik megfigyelésem, ahogy fent említettem, a típusosság drasztikus hiánya. Hibák komplett kategóriáját ki lehet szűrni azzal, ha minden változónak rendes típust adunk meg. Ez tehát az egyik pont a tervben.

A kód struktúrája és formája teljesen inkonzisztens. Nincs két egyformán kinéző fájl (kivéve az a 2000 soros, amit kompletten átmásoltak, hogy csak egy függvénynevet változtassanak meg benne). A különbözőségek lassú és rossz olvashatóságot eredményeznek, komoly hatással vannak a bővíthetőségre és lehetőséget adnak hibák elkövetésére.

A projekt architektúrája abszolút esetleges. Többféle szerepkör (néha 6-8 is) egyetlen komponensbe került mindenféle racionális ok nélkül (például: a fejlécben volt a "harang" ikon, ezért a fejlécben volt implementálva a komplett értesítéskezelés a-tól z-ig).

A komponensek egymagukban komplett modulokat valósítottak meg, óriási mennyiségű üzleti logika, megjelenési komplexitás, state kezelés egyben. A unitok (amiket aztán tesztelni kellene) nem ritkán 2000 sor fölé nyúltak, ellehetetlenítve a hatékony unit tesztelést.

Szinte semmilyen technikai szabályozás nem volt érvényesítve, sem a TypeScript fordító, sem a linter részéről, ami borzasztó hanyag kódot és kódolást eredményezett.

A dolgot súlyosbította, hogy a közös kódbázison dolgozó frontend fejlesztők 4 különböző csapatba voltak szétosztva, nem voltak egységes irányelvek lefektetve, sem kikényszerítve, nem volt semmilyen technikai vezetés (ami korábban volt, az bár ne is lett volna). A közhely a közös lóról tökéletesen megállta a helyét, ráadásul állatorvosi is volt.

A code reviewnak semmilyen kultúrája nem volt. Amikor odakerültem, visszanéztem az útóbbi 3 hónap pull request-jeit és nem találtam összesen 20 kommentet. Nincs az a tökéletes projekt, amelyik 3 hónap alatt (mondjuk naponta 4 PR-ral ez kb. 240 PR ennyi idő alatt) csupán ennyi kommentet indukál, lehetetlen. Aztán az első általam review-zott PR-ra egyből raktam 15-öt, mert annyi sebből vérzett.

A projekt az összeszedetlensége okán teljesen indokolatlan 3rd party libekkel volt tele. Az Angular alapból biztosít számformázási lehetőségeket, de már a böngészőben is van erre natív támogatás. Ennek ellenére egy 7 éve karbantartatlan libet sikerült erre felhasználniuk. Azaz, már a projekt indulásának pillanatában 2 éve magára volt hagyva ez a lib, bármely józan fejlesztő azonnal nemet mondott volna az installálására. Nem is beszélve a biztonsági problémákról, amik ezekben a csomagokban rejtőzhetnek - a biztonsági audit stabilan 20 fölötti számot mutatott bármely pillanatban.

A hanyagság további problémákat szült: statikus fájlok voltak commitolva a repositoryba (képek, pdf-ek, videók, stb), amik miatt a 30 MB-os projekt git repója 2GB méretű volt.

A state management, ahogy fent említettem, a komponensekben történt, leginkább class property-k felhasználásával. Ez a megközelítés évek óta ellenjavallt a framework szerint, mert kézzel fogható teljesítményproblémákhoz vezet. Ha valahol mégis értelmes módon volt ez kezelve, ott annyi féle minta volt, ahány előfordulás - zéró konzisztencia ebben is.

A projekt belső függőségeinek térképe (import-gráf) egyetlen kusza pókháló volt, minden mindennel összedrótozva, ráadásul tele god-objectekkel.

A stílusozás (CSS) szintén átláthatatlan módon volt megoldva, esetleges volt reszponzív kinézet is, ami aztán rendszeresen visszaütött, amikor valamit módosítani kellett.

Egy csomó külső függőségnek nem voltak meg a típusfájlai vagy wrapper libjei - gyakorlatilag futásidőben töltődtek be és az alkalmazás teljesen rá volt utalva a nem várt változásokra és tippelgetésekre. Volt, amikor az éppen aktuális, minifikált javascript kódot kellett debugolni egy funkció miatt, mert nem volt dokumentálva sem a 3rd party által.

A hab a tortán a branching stratégia esetlegessége, követhető élesítési folyamat hiánya, dedikált webszerver helyett egy content management rendszer használata meglehetősen unortodox módon.

A dilemma

A projekt a jelenlegi állapotában egy szakmai zsákutca, egy fekete lyuk, amibe mérnökök értékes óráit és motívációját égetjük mindenféle fejlődés nélkül. Borítékolható a fluktuáció/elhanyagolás spirál további mélyítése. "Ne panaszkodj annyit, oldd meg!" - neki is láttam.

A megoldás

Elkötelezett voltam abban, hogy ezen változtatni kell. Összegezve a problémákat elkezdtem gondolkodni egy megoldási lépéssorozaton, amit, ha kell, akár egyedül is végig tudok vinni, de nyilván minél többen állunk neki, annál hamarabb tudunk végezni.

A kód formájának konzisztenssé tétele. Ez egy hosszú és unalmas folyamat, aminek része egy előre felállított szabályrendszer alkalmazása minden egyes fájlra, ami a projektben van. A szabályrendszer nagyon sok pillérből áll, kezdve a hivatalos Angular kódolási javaslatokkal, clean kód szabályokkal, linter és fordítási szabályok bevezetésével és egyedi, a projektre szabott szempontokkal.

Típusok bevezetése mindenhova. A dolog elég trükkös, mert megköveteli a kód részleges megértését és némi kísérletezést, utánajárást, tesztelést.

A kód könnyed átstruktúrálása (fölösleges kódok kidobása, egybe tartozó dolgok egymás mellé rendezése a későbbi mozgatást előkészítendő).

Kitakarítani a fölöslegesen behúzott libeket, helyettesíteni azokat, amiknek semmi keresnivalója a projektben vagy elavultak/megbízhatatlanok (lodash, jquery, stb.).

Teljesen megérteni a nagyobb komponensek szerepét, szétdarabolni őket a felelősségi körök alapján. A feldarabolás során átalakítani a belső működésmódjukat úgy, hogy a legkevesebb state managementre legyen szükség. Azaz a class propertyk állítgatása helyett pure function-ök alkalmazása (csak input és output, semmi side-effect). Ezzel lehetővé válik a unit tesztelés, a performanciaoptimalizálás és további komponens-átszervezés.

Megszűntetni a belső state-eket a komponensekben, bekapcsolni az OnPush CDS-t. Szintén megszűntetni a stage management-et a service-ekben, azok helyett globális state managert használni (NGRX), ahol erre mégis szükség van.

Átstruktúrálni a kódot úgy, hogy világosan meg lehessen különböztetni a prezentációs komponenseket az üzletiektől - ezzel lehetővé válik a kiszervezés és akár egy-egy ilyen modul egy komplett csapathoz rendelése: sokkal világosabb felelősségi körök és számonkérhetőség, gyorsabb hibajavítás, stb.

Az eredmény

Mivel nem voltam kinevezett lead ezen a projekten, a hatásgyakorlásnak egyéb módjait kellett alkalmaznom. Volt például céges Wiki, amibe felvezettem a komplett tervet, kidolgozva az első néhány nagyobb mérföldkövet. Ezt aztán felhasználtam, amikor a code review során olyan módosításokat láttam, amik nem követték ezeket a sorvezetőket. Természetesen a dokumentációk mindenki számára hozzáférhetőek, szerkeszthetőek és vitathatóak voltak, erre mindenkinek előre fel is hívtam a figyelmét.

Elkezdtem RFC-ket gyártani (Request for Comments) azokról a dolgokról, amik újdonságot jelenthetnek a projekt életében vagy egy régi gyakorlatot challenge-elnek meg. Például keressünk glyph-font alternatívát (mivel a meglévő ingyenes szolgáltatás a beetetés után fizetőssé vált), vagy döntsük el, hogy egy új funkcióra milyen külső libet akarunk használni (milyen feltételek mentén vizsgáljuk meg, hogyan döntjük el, stb.), és további ~10 másik. Az RFC-k lényege az volt, hogy minél többen kritizáljuk meg az ott írtakat egy jussunk egy olyan konszenzusra, amit a legtöbbünk helyesnek gondol.

Az egészet prezentáltam több körben az üzleti döntéshozóknak, időbecsléssel, hatásokkal, várható eredményekkel. A tartalmat úgy formáltam, hogy érhető legyen annak is, aki nem annyira technikai, mint amit a projekt jellege megkíván. Bár minden felmerülő kérdést sikerült teljesen tisztázni, a cégnek nem volt profilja a szoftverfejlesztés, így egy szponzor sem mert mögé állni (annak ellenére, hogy a terv arról szólt, hogy a napi munkával párhuzamosan folynának a refaktorálási tevékenységek).

Nem vagyok az a fajta, aki könnyen beletörődik a ignoranciába, így szponzor nélkül is, értelemszerűen nagyon lassú tempóban, de elkezdtem a napi munka részeként átrágni magamat a problémás részeken. Amikor a cost-cut elérte a szerződésünket, úgy 15%-át sikerült a kódnak úgy rendbetenni, hogy arra a későbbiekben is építeni lehessen.

Rendbe tettem és optimalizáltam a CI/CD pipeline-t is, hogy ne 50 percig fusson egy deploy, csak 3-ig. Ez a fejlesztőknek is sokkal gyorsabb visszajelzést adott a módosításaikkal kapcsolatban (a projekt jellege miatt nem lehetett mindent a saját gépen ellenőrizni). Dokumentáltam az egész fejlesztési és élesítési folyamatot is, ami addig szájról-szájra módszerrel, minden alkalommal torzulva jutott egyik fejlesztőtől a másikig.

Gyakran csináltam live-coding eseményeket, amikor megmutattam a kollégáknak, hogy hogyan is gondolom mindazt, amit leírtam, illetve demonstráltam is. Tartottam külön session-öket, ha bármi egyéb témában merült fel kérdés (pl. hatékony unit-tesztelés; az SVG lehetőségei és korlátai; projekt specifikus 3rd party toolok használata; stb.).

Mit nyertem ezzel?

Szigorúan tech skillek szempontból az ég világon semmit, 100% kidobott idő volt. A projekt végig megőrizte a legacy jellegét, egy igazi soul grinder volt az utolsó percig (nem csak technikai-, de management szempontból is).

Amit a projekt hasznára írok az az, hogy elkezdtem jobban dokumentálni, hatékonyabban és érthetőbben beszélgetni nem-technikai emberekkel. Részt vettem folyamatoptimalizációs tevékenységekben, közösséget építettem, előadtam. Sokkal nagyobb méretekben gondoltam át a szoftver dimenzióit, mint az eddigi projektjeim során. Megterveztem egy al-projektet, aminek a célja az volt, hogy egy elhanyagolt, legacy frontendet modernizáljunk és készítsünk fel arra, hogy hosszú távon, a fluktuációt letörve, karriert építve tudjon rajta dolgozni az összes fejlesztő.