Dave Farley törvényei
Dave Farley egy vicces és érdekes ember, aki nagy tapasztalatokkal rendelkezik a fejlesztés terén, és nem mellesleg kiváló megfigyelő. Projektek és emberekkel való munkája során dolgozta ki a törvényeit — a fejlesztést és a programozást tudományos szemszögből közelítette meg. Az általa lefektetett törvények a következők:
- Az emberek hibásak
- Minden dolog sokkal komplikáltabb, mint ahogy gondolod
- Minden dolog érdekes tud lenni
Az emberek hibásak — de itt nem viselkedésre kell gondolni, hanem inkább az emberre mint valamilyen megtervezett dologra. Az emberi szervezet nem tökéletes, eleve úgy van felépítve, hogy csaljon: optikai csalódás, akusztikai csalódás, vakfolt, stb. Az emberi természetbe kódolva van a nagyjáboli megoldások elégségessége, és valljuk be, az életben sok területen ez elég is. Mi emberek hajlunk arra, hogy „Jól van az úgy" — de egy programban viszont nem lehet majdnem jó számítás vagy majdnem jó működés. Viszont ez természetellenes, és ezért olyan küzdelmes a tesztelés is számunkra. Amint elkezdnek a teszten jó eredmények jönni, azonnal hajlamosak vagyunk azt gondolni, hogy amit csináltunk az jó, és mehet is be rögtön a gitbe.
Miközben nem. Ez nem így van. És itt jön a második törvény: minden dolog komplikáltabb, mint ahogy gondolod. Igenis a peremfeltételek mentén, vagy különleges esetekben egy adott probléma, programkód is képes szélsőséges dolgokra, és ezeket le kell kezelni. Még akkor is, ha csak ritkán fordulhatnak elő, és az alap megoldás, amit elsőre gondoltunk, szinte teljesen lefedi az eseteket.
Viszont a dolgok tesztelése, a hibakezelés a kódban legtöbbször unalmas dolog, mert úgy érezzük, hogy nem a valódi üzleti logikára koncentrálunk, hanem csak a szükséges köröket futjuk. És erre van a harmadik törvény: mindig próbáljuk meg valamilyen érdekes dolgot vagy értéket találni még az unalmas munkában is. Mert minden munka tud élvezetes vagy érdekes lenni, ha a megfelelő szögből tekintünk rá. Ha elkezdünk azon gondolkodni, hogy miként tehetem a saját kódom „golyóállóvá", akkor a hibakezelés kihívássá válik. Én például a teszteknél mindig futtatok egy statisztikát, hogy mekkora a valós kód és a teszt kód egymáshoz viszonyított aránya, és a tesztnek el kell érnie az 50%-ot — ez egy kihívás, amiben el tudunk merülni, és hirtelen a tesztelés sem lesz monoton. De ugyanilyen érzés, amikor valós esetekkel próbálod elérni a 100%-os code coverage-t. Mert közben az az érzésed alakul ki, hogy amit csináltál, abban az üzleti logika mellett a kiváló minőség is ugyanúgy érték. Sőt, ez az, amire igazából büszke vagy. Nem arra lesz az ember büszke, hogy megcsinált egy üzleti funkciót, amit mások is tudnak használni, hanem arra lesz büszke, hogy úgy csinálta meg, hogy arra bátran rá lehet támaszkodni, és a kódját bárki bármikor megnézheti — sőt, örülünk is, ha megnézi! Ennek a gondolkodásnak az elsajátítása teszi lehetővé, hogy egy programozó a TDD rajongója legyen, és e szemlélet szerint végezze a munkáját.
Korábbi kutatások kimutatták, hogy egy programozó 15 sort ír egy nap alatt. Ugye, hogy ez kevés? Viszont a számítás módja a következő volt: a projekt során a tényleges programba bekerülő sorok száma, osztva a projekt első napjától az utolsó napjáig lévő idővel, és osztva a projekten dolgozó programozók számával. A programsorokba csak az éles és végleges kódok számítanak bele, a vargabetűk és tévutak nem. A segédeszközök kódja szintén nem számít bele, és a tesztelésre írt kódok szintén nem. A projekt vége felé lelassul — ez már legtöbbször az átadás után van. Az ügyfél használja a terméket, de még mi mindig javítunk benne, és sokszor csak hibákat keresünk keservesen: debug, teszt, javítás... Ezekben az időkben nem tudunk igazán értékes kódot készíteni, és valójában a projekt idejét ez az egy rész emészti fel. A mai tesztelési módszerekkel, és azzal, hogy a unit tesztek korát éljük, a problémák hamarabb derülnek ki. A unit tesztek segítettek abban, hogy a napi 15 sort feljebb tudjuk vinni. Tehát minél több „nem értékes" kód segít abban, hogy több és több értékes kód legyen.
Régen, ha egy modul elkészült és bekerült a kódba, először éles lett, és voltak benne bugok, vagy olyan esetek, amelyek nem voltak kezelve. Ezek szépen lassan, egyesével felderítésre kerültek, és egy idő után az adott modul stabillá kristályosodott. Ekkor már bátran lehetett rá támaszkodni, és ezek a modulok képezték a szervezet üzleti értékének alapjait — ezek a modulok vagy algoritmusok kincsek voltak, és egy termék vagy vállalkozás tudott ezek köré épülni. Viszont ezeket a modulokat senki nem merte átírni, és nem is volt szabad bennük komoly változtatásokat végrehajtani, mert a rátámaszkodó programok stabilitását veszélyeztettük vele. Ezek a modulok így teljes egészében megkövesedtek, és nem voltak képesek a hosszabb idő után fellépő igények kielégítésére — legyen az egy újabb fejlesztői környezet, egy technológia, vagy akár csak egy szabályrendszer bevezetése. És szépen lassan ezek az egykor stabil sziklák, amikre a szervezet épült, elkezdtek horgonnyá válni, gátakká. Ezeken a projekteken egyszer csak nem volt már élvezetes dolgozni, és a munkamorál és a termelékenység is odaveszett. Még külön szakmai szavunk is van ezekre a forrásokra: „legacy code" — ami ma már szitokszónak számít. Hiszen minden egyes megtalált és javított bug egy újabb if-et, elágazást, vagy esetet rakott a kódba. És ma már egy komplett if-háló van, és amikor megnézünk egy függvényt, és abban olyan vizsgálatot találunk, amit nem tudunk, miért van benne, de ebben az esetben a program egy kicsit másképp működik — akkor már nem merünk belenyúlni, nem uraljuk a kódot. És itt kezdődik a gány kód, a gány a fertő, a fertő a halál...
Ezzel szemben, ma, ha egy adott modul rendelkezik körültekintő unit teszttel, akkor sokkal biztosabbak lehetünk abban, hogy az adott modulban már a fejlesztés során egy jó pár hiba javítva lett, így az induló minősége is sokkal magasabb. Emellett, ha egy újabb hibát találunk a használata során, akkor azt először egy újabb unit teszttel elő kell hozni, és csak utána javítani. Így tudjuk, hogy a javításunk nem tört el más unit teszteket, és a program javítása nem okozott további hibákat a kódban. A unit tesztek további nagy előnye, hogy képessé teszi az adott modult a refaktorálásra és technológiai váltásra, mert amíg a tesztek futnak, addig a program úgy működik, ahogy elvárható. És így a modulok át tudnak esni olyan refakt körökön, amik megszüntetik az if-hálót, és irtják a gányt! A gány a fertő, a fertő a halál...
Azzal, hogy a modulok képesek megújulni, továbbra is be tudják tölteni a stabil szikla szerepét, amire a szervezetet vagy a terméket építeni lehet — de nem válnak érinthetetlen bálványokká és horgonyokká.
A tettek mezeje
De akkor, hogyan csináljuk? Az előző fejezetben azt tárgyaltuk, hogyan ne csináljuk, és milyen hibákat tudunk mi programozók elkövetni — de szükségünk van arra, hogy tudjuk, miként kellene csinálni. Természetesen sok módszer van, ami egyformán lehet jó, és csapatonként, emberenként és termékenként is más-más lehet a megoldás. De közös pontok akkor is vannak, amelyek vagy saját vagy mások tapasztalataiból jönnek, és minden olyan módszer vagy folyamat, amit a szervezet életében alkalmazunk, valahogyan csatlakozik ezekhez az alaptételekhez.
- People first
- Check everything
- Change everything
Az ember az első — a dolgozó, aki az értéket teremti. Nektek kell jól érezni magatokat a helyeteken, nektek kell elégedettnek lenni a feladattal és körülményekkel, és az elért eredményekkel. A második pont: mérj mindent, döntések ne tippek vagy megérzések alapján szülessenek, hanem mérések és eredmények alapján. A harmadik: merj változtatni — ha nem változik a program, ha nem változol te, ha nem változnak a módszerek, akkor nem is tudnak jobbak lenni.
Az ember az első
Adrian Cockcroft, a Netflix technikai igazgatója mondta, hogy ennek a mentalitásnak volt köszönhető, hogy a Netflix képes volt dolgokat megtenni és gyorsabban végrehajtani — mert mindenki a célért dolgozott, és nem központilag volt megmondva, hogy mit kell csinálni. Önálló döntéshozó pontok voltak, csoportok, amelyek a saját dolgaikról tudtak dönteni. Természetesen a döntésnél figyelembe kell venni a szervezet érdekeit, nem csak az egyéni érdekeket. De hiszem, ha motivált és tenni akaró emberek vannak egy csoportban, akkor az egyéni célok és a csoport céljai ugyanazok: létrehozni valamit. Mert akkor az embereknek automatikusan jön a motivációja.
„Ha hajót akarsz építeni, ne hívj össze embereket, hogy gyűjtsenek fát, ne oszd fel a munkát és adj parancsokat, hanem keltsd fel bennük a vágyat a nagy, végtelen tenger iránt."
— Antoine de Saint-Exupéry
What are you doing?
Three men were carrying the stones. Somebody asked them: what are you doing?
„I am working hard," answered the first man, wiping the sweat out of his face.
„I am earning money," the second man said, rolling up the sleeves.
The third man said, looking upwards at the sky: „I am building a temple."
Feel the difference.
Ez a gondolat a motiváció lényege. A főnökök nem tudnak motivációt adni — a vezetés célja a vízió megfogalmazása és életben tartása. Hogy miként? Az első és legfontosabb dolog, hogy a dolgozó az első. Aki értéket teremt, annak kell olyan körülményeket és feladatokat kapnia, amit élvez, amit meg tud csinálni. De ha a korábbi fejezetből indulunk ki, akkor láthatjuk, hogy valójában minden feladat élvezetes tud lenni. Ha valami nem az, akkor csináljuk gyakrabban, és találjuk meg a módját, hogy miként törjük azt apróbb részekre — és végül szüntessük meg így a fájdalmat.
Ha valami fáj, csináld gyakrabban
Számos feladatot tudunk mondani a mindennapi munkákból, amit utálunk — vagy azért, mert monoton, vagy azért, mert sokat kell várni, vagy azért, mert veszélyes és könnyű elrontani. Az „If it hurts, do it more often, and bring the pain forward" Jez Humble Continuous Delivery könyvéből van, és természetesen nem csak a Continuous Delivery-re alkalmazható. Ha egy adott munkafolyamat valamiért kellemetlen, akkor azzal, ha gyakrabban csináljuk, egyrészt rutinná válik, másrészt egy idő után ki fogunk rá találni valamilyen automatizálási lehetőséget.
Nem kell egyből nagyban gondolkodni — a feladatot fel kell bontani kisebb részekre, és azokat egyesével megoldani, egyszerűsíteni vagy automatizálni. Ezek a dolgok már középtávon is hasznot fognak hozni, mert nő a minőség, nem fogja kerülni senki ezt a munkafolyamatot, és így nem rombolja a munkakedvet sem. Ahogy sok más területen, itt is igaz a Pareto-elv: a kellemetlen jelenségek 80%-a az okok mindössze 20%-ára vezethető vissza. Ezeket kell először megoldani — és ezeket is csak kisebb erőbefektetéssel. Először nem a tökéletes megoldás a lényeg, hanem az, hogy valamilyen megoldás legyen a problémára. Minden előrehaladás már segít, és ezt folyamatosan csinálva, folyamatos lesz a fejlődés is.
Természetesen, ha egy dolgot megoldunk, más dolgok még továbbra is kényelmetlenek vagy veszélyesek maradnak — ezeket majd következő körben oldjuk meg, és szépen lassan így fogyasztjuk el a problémát, közösen! Ha valami rosszul ment, vagy rosszul sült el, akkor analizálni kell az okokat, és fejleszteni kell a rendszerünket, hogy elkerüljük a jövőben ezeket a hibákat — és ami még ennél is fontosabb: nem hibáztatunk magunkat vagy másokat! Senki nem akar hibázni, de hibák mégis vannak.
Amit a vevő számára érték, nem a főnök számára érték. Csak akkor lehet sikeres egy szervezet, ha a vevők elégedettek — nem csak ez kell a sikerhez, de e nélkül biztosan nem lesz az.