Az infokukac blog 2010. márciusában átköltözött. Átirányítás folyamatban...

Az átirányítás automatikus. Ha mégsem sikerülne, látogasd meg az új oldalt a http://infokukac.com címen, és frissítsd a könyvjelzőidet!

2010. január 29., péntek

Fluent interface

Kb. 2 éve olvastam először a fluent interface-ekről. Akkor nagyon megtetszett, és azóta is folyamatosan alkalmazom a módszert. Nem is gondoltam akkor, hogy Java-ban (vagy C#-ban) a legalapvetőbb nyelvi eszközökkel ilyen kifejező kódot lehet írni.

Az alapprobléma

Az eredeti probléma abban áll, hogy hogyan valósítsuk meg viszonylag sok paraméter átadását a kódban. A legalapvetőbb megoldás a standard módszer:

void doRegistration(String firstName, 
                    String lastName, 
                    String email, 
                    String password, 
                    String country, 
                    String city, 
                    String streetAddress1, 
                    String streetAddress2, 
                    String postalCode, 
                    boolean male, 
                    int age, 
                    boolean wantsNews) {

// ...
}

Jelen esetben 12 paraméter átadásáról van szó. Mondanom sem kell, hogy kínszevedés kliensként az ilyen metódust hívni, hiszen ahhoz, hogy tudjam, mit kell éppen átadni, az IDE-t kell segítségül hívnom. Ráadásul a keletkező kódot ilyen esetben borzasztó utólag is olvasni, hiszen nem rí le róla, hogy a híváskor milyen paraméterket, milyen sorrendben is adok át.

Martin Fowler Refactoring c. könyvében az Introduce Parameter Object c. minta próbál egyszerűsíteni a problémán, és azt javasolja, hogy rakjuk egy objektumba (osztályba) ezeket a paramétereket, majd ezt az objektumot adjuk át.

void doRegistration(RegistrationData data) {
// ...
}

Sajnos, a gond még mindig ugyanaz, hiszen magát a RegistrationData típusú objektumot is fel kell töltenünk ugyanezekkel a paraméterekkel. Megoldás lenne a setter-ek alkalmazása, de őszintén szólva, ha ilyet meglátok a kódban, egy kisebb agyvérzést kapok. Mivel mások által sem javasolt az objektumok kívülről történő piszkálása (sérti az egységbezárás elvét), célszerű más megoldást keresni, és itt jönnek a fluent interface-ek a képbe.

A megoldás

Kliens oldalon a következő a használandó kód (pl. egy tesztben):

RegistrationData registrationData = new RegistrationData()
    .withName("Béla", "Kovács")
    .withAccount("bela.kovacs@gmail.com", "pass1234")
    .withCountry("Hungary")
    .withCity("Budapest")
    .withAddress("Kossuth Lajos utca 13.", ""),
    .withPostalCode("1234"),
    .withMale(true)
    .withAge(20)
    .withWantsNews(false);

doRegistration(registrationData);

A RegistrationData osztály implementációja a következő:

public class RegistrationData {
    private String firstName;
    private String lastName;
    // további mezők

    RegistrationData() {
    }
    
    RegistrationData withName(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
        return this;
    }

    // további with-ek

    String getFirstName() {
        return firstName;
    }

    // további getter-ek (ha szükségesek egyáltalán)
}

A módszer előnye az, hogy amikor olvassuk a kódot, látszik, hogy a hívás pillanatában milyen paraméterek kapják a megfelelő értékeket. Ezért is kapta a fluent nevet a minta, hiszen folyamatosan, gondolkozás nélkül olvashatjuk a kódot, "folyékonyan", mintha természetes nyelven lenne írva. 

Látható az is, hogy nem muszáj egy az egyben átkonvertálni minden paramétert egy with... hívássá, azok csoportosíthatóak nagyobb, jól nevesíthető tömbökbe. Például a firstName-et és lastName-et együtt a withName... metódussal olvassuk be. (Viszont egy ilyen with... hívásba sem szabad sok paramétert bezsúfolni, mert akkor ugyanott tartunk, ahonnan elindultunk.)

A módszer egyetlen hátránya, hogy - a standard, sokparaméteres átadással szemben - nem kényszeríti ki az összes paraméter átadását. Az eredeti példa pl. nem fordul addig, amíg át nem adunk 12 akármilyen paramétert (a típusoknak azért egyezniük kell). Ezt azzal szokták orvosolni, hogy a paraméterek átadása után hívnak egy validate(), void visszatérési értékű metódust, amely elszáll, ha valamilyen paraméter nem lett kitöltve. Másik módszer a probléma megoldására, ha teszteket írunk. Amúgy - megsúgom - ha kihagyunk véletlenül egy paramétert, azt rövid időn belül úgyis észrevesszük, és korrigálhatunk, tehát nem célszerű emiatt túlságosan aggódni. Amit viszont cserébe kapunk, az a nagyfokú olvashatóság.



2010. január 19., kedd

A sprinttervezés (Scrum-sorozat 3/2. rész)

Az előző post kicsit hosszúra sikeredett, viszont megismerhettük a tervezés legfontosabb eszközeit: az előkészítést, a sztoripont fogalmát, a fókuszfaktort, a kapacitástervezést és a Planning Poker-t. Minden együtt van ahhoz, hogy a tervezés teljes forgatókönyvével tisztában lehessünk. 

A tervezés forgatókönyve 

0. Készüljünk elő: aktualizáljuk a Product Backlog-ot, készüljünk fel a sztorikból! 
1. Tervezzük meg a csapat kapacitását: határozzuk meg, hogy az elkövetkezendő sprint alatt hány sztoripontot tudunk teljesíteni! (Ld. kapacitástervezés) 
2. Vegyük a legfontosabb sztorit! 
3. Bontsuk le közösen feladatokra! 
4. Becsüljük meg az egyes feladatok méretét
5. Menjünk vissza a 2. lépésre, amíg tudunk újabb sztorit választani, ami még befér a sprintbe. 

A tervezést rendszerint a Scrummaster moderálja. (Nálunk a meeting request-eket is ő küldi ki a tervezésre.) 

Előfeltétel, hogy a Product Owner priorizálja a Product Backlog-ot a tervezésre. A csapat ezt ne bírálja felül, fogadja el, hogy ez a prioritás. A csapat meg azt állapítja meg, hogy a rögzített hosszúságú sprintben mennyi sztorit tud elkészíteni. 

Feladatokra bontás 

A Product Backlog-ból a sztorikat prioritás szerint vesszük elő. 

Először mindenkinek meg kell értenie, hogy miről szól a sztori. (A mi esetünkben ennek lehetőségét a korábban elkészített rövid, érthető dokumentáció, és az üzleti szakértő (Albert) jelenléte biztosítja.) Ha ez megvan, akkor a csapat közösen lebontja a sztorit kisebb feladatokra. 

Pár dolog: 

  • A kártyákkal történő becslést (Planning Poker) akkor célszerű elvégezni, amikor az aktuális sztori feladatokra bontásán túl vagyunk (mindenki egyszerre emeli a kártyát!). 
  • Magukat a feladatokat becsüljük, nem a teljes sztorit. 
  • Nagyon fontos, hogy akkor vegyünk véglegesnek egy becslést, ha abban a csapat közösen egyetért. Ha véleménykülönbségek vannak, akkor azokat ütköztetni kell (Scrummaster feladata), meg kell vitatni, és konszenzusra kell jutni. 


A feladatokra bontás több eredménnyel is jár: 

  • a csapat végiggondolja a sztori megvalósításának menetét, 
  • ezáltal még jobban megismeri a problémát (esetleg újabb kérdések is felszínre kerülnek), 
  • a kisebb méretű feladatokkal történő becslés pontosabbá teheti a teljes sztori becslését, 
  • ha kisebb méretűek az elvégzendő feladatok, akkor jobban követhetővé válik sprint közben a haladás. (Megszűnik a napokig, hetekig tartó "80-90%-ban kész vagyok, már csak..." probléma.) 

Az alábbiakban összefoglalom azokat a tapasztalatokat, amiket a feladatokra bontásnál szedtünk össze. Figyelem, ezek nem Scrum-szabályok, hanem a saját megfigyeléseink és gyakorlatunk! 

Ne válasszuk szét a munkafázisokat! 

Példa: ha a sztori egy webshop alkalmazásnál a "Regisztráció", akkor ne legyen két külön feladat az, hogy "Regisztráció fejlesztése" és "Regisztráció unit test írás", hanem állapodjon meg a csapat, hogy egy sztori/feladat elvégzéséhez a unit-test-ek megírása is szükséges.

Mivel kisméretű a csapat (max. 7-9 fő), ezért nem szükséges a munkafázisok szerinti szájbarágos feladatrészletezés. Mindenki tudja, hogy mi a feladata. Ha mégis így teszünk, rengeteg függőséget viszünk be a feladatokba, ráadásul drasztikusan megemelkedik a feladatok száma, ami Micro Management-et eredményez. 

Sok kicsi sokra megy! 

Ha túl sok az apró feladat, akkor torzíthatják a becslést. 

Ha túl sok a 0-s sztoripontú feladat, akkor ezek összege is 0. A valóságban ezek valószínűleg a 0-nál sokkal több idő alatt fognak elkészülni. 
A másik eset, hogy ha a sok apró feladatot 0.5 sztoripontra túlbecsüljük (ez kb. fél-1 napos időtávot jelent a biorobot pontrendszerben), akkor a sok ilyen apró feladat együttesen tetemes ráfordítást jelent, pedig valójában lehet, hogy csak 1 nap kellene a fejlesztésükhöz.


Nem baj, ha egy feladat nem egységnyi ideig tart 

Ugye milyen jó lenne, ha egységnyi idejű feladataink lennének (mondjuk, amik egy napig tartanak)? Ha valaki egy nap elkezd egy feladatot, a következő napra be is fejezné. Nagyon könnyen követhető lenne a haladás sprint közben. Ez sajnos a valóságtól elrugaszkodott feltételezés, nem árt azzal tisztában lennünk, hogy ez nem fog menni. Nem lehet úgy megerőszakolni a feladatokra bontást, hogy ez teljesüljön, és ezzel ráadásul elősegítjük a Micro Management-et. 

Törekedni azonban lehet arra, hogy a feladatokra bontás során egy-egy feladat rövid idő alatt teljesíthető legyen (1-2 nap).

Felejtsük el az alkalmazás rétegeit! 

Egy sztorit ne az alapján bontsuk feladatokra, hogy az alkalmazásban milyen rétegek vannak. 

Pl. egyik feladat az X funkcióhoz felhasználói felület készítés, a másik ennek szerveroldalának elkészítése! 

Itt már át is megyünk Micro Management-be. Kétszer annyi kártyánk lenne sprint közben a falon (ha még több rétegre bontanánk, akkor még több), amitől nehézkesebbé válik a haladás áttekintése, és előtérbe kerülhetnek a 0-0.5 sztoripontos feladatok (ld. fenn). 

Azért nem kell a rétegekkel foglalkoznunk, mert legtöbbször az egyes rétegeket nem lehet függetlenül fejleszteni, közös munkára van szükség. Pl. a felhasználó felület helyességét nehéz tesztelni a meglévő szerver oldal nélkül, és a kettő közötti interfészt is közösen kell kialakítani. 



Ne adott emberhez tervezzük a feladatokat! 

Úgy gondolkozzunk, hogy nem tudjuk még, ki fogja csinálni a feladatot! (Merthogy sprint közben fog kiderülni.) Mivel elviekben keresztfunkcionális a csapatunk, és nem rétegek szerint vágjuk a feladatokat, ez teljesíthető.

Ne foglalkozzunk a függőségekkel! 

Nem kell a feladatok közötti függőséggel törődni. Miért? Mert kevesen vagyunk a csapatban, egy sprint rövid ideig tart. Talán a csapat a sprint közben is el tudja dönteni, hogy milyen sorrendben célszerű haladni. (Micro Management, ismerős?)

Nem baj, ha egy feladatot nem egy ember végez 

Az lenne az ideális, ha a sprint közben számonkérhetőek lennének az egyes emberek, hogy hogyan állnak a saját választott feladatukkal. Ha ketten dolgoznak egy feladaton, akkor már nem egyértelmű, hogy ki az, aki miatt nem halad a feladat elvégzése. 

Az, hogy egy feladaton egyszerre csak egy ember dolgozhat, sajnos, ismételten Micro Management-hez vezet, mert a legtöbbször rétegek vagy munkafázisok szerint szerveznénk a feladatokat. Ezért célszerű belenyugodni abba, hogy nincs azzal baj, ha egy feladaton többen is dolgoznak. 

How-to-demo írása 

A Scrum egyik szabálya, hogy az elkészített feladatokat mindenki saját maga demózza az ügyfélnek (vagy a Product Owner-nek). Ezért - annak ellenére, hogy a csapat közösen tervez, fejleszt stb. -, minden fejlesztőn ott a személyes felelősség. Ha nem veszi komolyan a munkát, akkor beég az ügyfél előtt a demón. 


Ahhoz, hogy ne csússzanak félre a dolgok (egyértelmű legyen, hogy mi a fejlesztendő funkció, valamint hogy hogyan lehet azt bemutatni az ügyfél előtt), meg kell határozni, hogy hogyan demózható egy-egy elkészítendő feladat. Ezt nevezik "How-to-demo"-nak. 

Valakik azt javasolják, hogy tervezés közben határozzuk meg, hogy az egyes sztorikat (esetleg feladatokat) hogyan lehet majd demózni. Ez egyfajta specifikáció a fejlesztőnek a sprint idejére, másrészről pedig elfogadási kritérium (Acceptance Criteria). Mi nem ezt a módszert alkalmazzuk, több okból is. 

  • A mi esetünkben nagyon sok ideig tartana, ha egy-egy forgatókönyvet megírnánk, és a tervezés akár több napig is eltartana (annyira komplexek a sztorik). 
  • Megadjuk a lehetőséget arra, hogy ha az implementáció során a modellben valamilyen problémával szembesülünk, akkor korrigálhassuk a forgatókönyvet. Úgy gondoljuk, hogy nem érdemes túlságosan korán specifikálni a feladatot (még a sprint előtti tervezés is több esetben korainak bizonyult!). Helyette hagyjuk, hogy a fejlesztő sprint közben írja meg a forgatókönyvet. Miután elkezdi "felszívni", beleásni magát a sztoriba, sokkal jobban átlátja a lehetőségeket, a lehetséges ellentmondásokat, és így jobb forgatókönyv tud készülni. 

A How-to-demo-t egyébként egy rövid leírásnak kell elképzelni, amit a csapat tagjai megértenek. Nem kell olyan részletekig kidolgozni, hogy az az ügyfél számára is átadható legyen (nekik ott van a demó). 

Egy How-to-demo, amit mi írtunk éles projektben. Egy teljes iratkezelési folyamatot mutat be. A TEST előtag jelzi, hogy az adott ponton ellenőrizhető a meglévő eredmény. 

How-to-demo: Visszavárt irat érkeztése ügyvitelre leadott ügyiratba 

  1. szaboz új iratot készít (1 irattári, 1 tartalék példány), új ügybe 
  2. szaboz a tartalékpéldányt visszavárólag elküldi 
  3. szaboz az ügyiratot leadja ügyviteli irodára 
  4. TEST irodavezetőnél le lehet szűrni az ügyviteli irodán lévő ügyiratokra, a leadott ügyirat megjelenik. 
  5. irodavezető visszavártan érkezteti az elküldött iratot. 
  6. TEST az irat az ügyvitelen marad 
  7. irodavezető kiadja az ügyiratot az ügyviteli irodáról szaboa-nak 
  8. TEST szaboa tud iratot készíteni az ügyiratba 

Sprint Backlog 

A Product Backlog tartalmazza az összes hátralévő sztorit. A Sprint Backlog ehhez képest azon sztorikat tartalmazza, amik beférnek az aktuális sprintbe. Nem csupán a sztorik neve, hanem a lebontott feladatok és azok becslései is szerepelnek benne. 


A táblázatban a következő adatok találhatók:

  • A oszlop: sztori azonosítója, 
  • B oszlop: sztori megnevezése, 
  • C oszlop: a lebontott feladat neve, 
  • D oszlop: prioritás (a sztorié a product backlog alapján, az összes feladat ezt örökli), 
  • E oszlop: a feladatra becsült sztoripontok száma, 
  • F oszlop: a taszk egyedi azonosítója a sprinten belül,
  • 1. sor: hányadik sprintnél járunk, mikor van a demó,
  • 2. sor: a sprint célja - mindig kitaláljuk, hogy miért is van ez a sprint. Pár szóban megfogalmazzuk a célját. Elvégre nem árt, ha tudja az egész csapat, hogy mi is a célja az aktuális munkának. 

Timeboxing 


A Scrum egyik alapvetése, hogy szigorú időkereteket (timebox) alkalmaz. A legalapvetőbb időkeret magának a sprintnek az időtartamára vonatkozik: ha egy sprint kéthetes, akkor egy nappal sem tart tovább. A timeboxing-ot lehet alkalmazni magára a tervezésre is: ha a Scrummaster 2 órát szán a tervezésre, akkor az egy perccel se lehet hosszabb. A csapatnak meg kell tanulnia, hogy hogyan tervezzen hatékonyan, mint ahogy azt is meg kell tanulnia, hogy hogyan szállítsa a sprintre betervezett sztorikat. 

Habár az irodalomban szerepel a timeboxing alkalmazása a tervezésre, bevallom, mi ezt a szabályt nem alkalmaztuk. Nekünk nem voltak terjengősek a tervezések, ha a 2 óra után még kellett fél óra, akkor fél órával tovább tartottuk. A tervezés szigorú timeboxing-ja csupán egy módszer: ha a csapat nem képes megfelelően működni, akkor korlátok közé szorítjuk. Ezáltal megtanulhatja hatékonyan felhasználni a rendelkezésre álló időt. 

Végezetül jöjjön egy képzeletbeli sprinttervezés párbeszéd részlete. 

A fiktív sprinttervezés résztvevői az előző részben említett csapat tagjai: Albert (az üzleti szakértő), Jónás (junior fejlesztő), Döme (junior fejlesztő), Iván (senior fejlesztő), Zalán (senior fejlesztő), Csubi (Scrummaster).

[A fejlesztendő termék egy banki webes rendszer. Éppen megtörtént a kapacitástervezés az aktuális sprintre.]

Csubi: Az első sztori a product backlog-ból az "Átutalás". Albert, mesélnél róla egy kicsit?
Albert: Ezt valószínűleg mindannyian ismeritek már. Egyszerűen arról van szó, hogy egy ügyfél egy meghatározott összeget átutal a saját bankszámlájáról egy másik bankszámlára. Miután bevitte az adatokat, kellene egy ellenőrző képernyő, ahol lecsekkolhatja a bevitt adatokat. Az egészet majd később lehessen időzíteni is, de az egy másik sztori. [Itt Albert arra utal, hogy ez is egy lefejlesztendő funkció, és benne is van a Product Backlog-ban, de kisebb prioritással, és majd egyszer meg kell azt is csinálni.]
Csubi: Elég ennyi infó a feladatokra bontáshoz? 

Csubi körbenéz. Mindenki bólint.

Csubi: Rendben. Érdemes szétbontani feladatokra?
Döme [junior fejlesztő, nemrég érkezett a projektbe]: Lehetne az első az, hogy a funkció kiválasztása a főképernyőről.

[Zalánnak felcsillan a szeme, már várta ezt a magas labdát.]
Zalán: Ezt mindig úgy csináljuk, hogy beleértjük a feladatba. Tehát magától értetődik, hogy ahhoz, hogy egy funkció működjön, ahhoz kell lenni valahol egy linknek vagy gombnak, amivel a funkció elindítható. Ha valaki csinálja az átutalás felhasználói felületét, akkor felrakja ezt a gombot a főképernyőre.

[Döme elbizonytalanodik.]
Döme: Ja, bocs, nem tudtam.
Csubi: Semmi gond. Akkor mi legyen az első feladat?
Jónás: Szerintem legyen az adatok bevitele, utána jöhetne az átutalás.
Iván: Várj, az ellenőrzés ne maradjon ki.
Csubi: Tehát akkor: adatok megadása, ellenőrzés, átutalás. Jó így?

[Senki nem válaszol, mindenki üveges csirkeszemekkel néz maga elé.]
Csubi: Na, mi az? Nem túl fitt a csapat így kora reggel!
Döme: Tegnap volt egy kis pókerparty, a végére kicsit sok lett a vodka.

[Mindenki röhög egyet magában. Csubi is elmosolyodik.]
Csubi: Ja, értem már. Na, jó, akkor úgy veszem, hogy mindenki igent mondott. Be is írom az Excelbe.

[Egyetért a csapat. Csubi kezeli az Excelt: beírja a Sprint backlog-ba az első három feladatot.]
Csubi: Rendben. Becsülhetünk? Az első feladat az adatok megadása. Ki mennyit becsül?

[A kártyák a kezek ügyébe kerülnek, és elindul a gondolkozás. Valaki a kezében tartja az egész paklit. Az első kártyát hátra teszi, majd a következőt megint, és addig folytatja, amíg meg nem találja a kívánt pontszámú lapot. Iván mindig fejjel lefelé tartja őket az asztalon: bal oldalon a 0-ás kártya, utána következik jobbra növekvő sorrendben a többi: 0.5, 1, 2, 3, 5. A többi kártyát nem is rakja maga elé, mert olyan nagyságú feladat még sosem volt, és valószínűleg nem is lesz. Különben az már több sztorivá vagy még kisebb feladattá lenne bontható. Mindenki a kezébe fog egy kártyát, és közben a többieket figyeli, hogy vergődnek-e még a kártya kiválasztásán. Döme, akinek ez az első sprintje, meglehetősen hamar kiválasztotta a saját kártyáját, és mosolyog magában.]
Csubi: Ok. Kérem a téteket!

[Két 2-es, egy 1-es, és egy ?-t mutatnak fel a csapattagok. A ?-et Döme mutatja fel, nem igazán tudja még, hogy hány sztoripontot érhet a feladat.]
Csubi: Na, látom, nincs egyetértés. Jónás! Te miért mutatsz 1-et?
Jónás: Szerintem nem nehéz a feladat, felrakjuk a főképernyőre az új linket, aztán megjelenik egy sima űrlap, viszonylag kevés adattal.
Zalán: Hát, azért szerintem kell a 2 nap. Meg kell írni a unit- és integrációs teszteket is.
Jónás: Ó tényleg, mindig elfelejtem!
Csubi: Rendben. Akkor lehet 2? 

[Mindenki bólint. Döme elfogadja a csapat döntését, és arra gondol, vajon mikor jut el ő is oda, hogy képes legyen jól becsülni. A csapat folytatja a következő feladattal.]



2010. január 15., péntek

Agilis Szoftverfejlesztők Egyesülete előadás (Scrum, DDD), 2010. január 14.

A mai nap résztvettem az Agilis Szoftverfejlesztők Egyesületének klubdélutánján. Kb. 15-en voltunk, egészen családias volt a hangulat. Nekem úgy tűnt, hogy sok ember már régóta ismeri egymást. 

Nem ismerem az egyesületet, de szimpatikus a kezdeményezésük, hogy széles körben népszerűsítsék az agilis elveket. Mint megtudtam, ezek a klubdélutánok rendszeresek, a következő egy hónap múlva lesz újra.

Az estének két témája volt: az első a Scrum-hoz és a becsléshez kapcsolódik, a második pedig a Domain Driven Design-hoz (szakterület vezérelt tervezés). Mindkét téma alapból érdekel.

Időalapú tervezés kontra komplexitás alapú tervezés

Az előadó Dr. Bodó Árpád Zsolt volt. Rövid bemutatkozásként megtudthattuk, hogy a Sprint Consulting vezetője, és évek óta segít fejlesztői csapatoknak Scrum-bevezetésben. Érdekességképpen megemlítette, hogy 5-6 éve saját erőből próbálták a Scrum-ot és az agilis módszertanokat meghonosítani, de miután egyik kudarc a másikat követte, arra a felismerésre kellett jutniuk, hogy megfelelő továbbképzés nélkül ez nem lehetséges. A tréning elvégzése után Certified Scrummaster bizonyítványt szerzett, és végre megértette, hogy miről szól ez az egész, és hogyan lehet sikeresen alkalmazni a gyakorlatban a módszert. 

Zsolt egy rövid Scrum-os összefoglalóval kezdett azok kedvéért, akik nem ismerik. Szerintem ez alatt az 1-2 perc alatt elég jól sikerült az összefoglalás, bár kérdés, hogy azok, akiknek ez új volt, bírták-e követni. Azért azt hiányoltam, hogy a Scrum-folyamat lépéseinél kimaradt a demó utáni retrospective, és nem kapott kellő hangsúlyt a Scrum-ban a tanulás. 

Az előadás a becslésről szólt, azaz, hogy hogyan becsüljük meg a product backlog sztorijait, ill. egy sprinttervezésen a lebontott feladatokat. Természetes reakciónak tűnik, hogy az idő a megfelelő módszer, a standard kérdés az lehetne, hogy hány óráig/napig tart lefejleszteni egy-egy funkciót. Ezzel azonban több gond is van: egyrészt az egyes emberek gyorsabban, mások lassabban dolgoznak. Valahol átlagosan egy nap 4 órát, a jobb(?) helyeken 6 órát dolgoznak a napi 8 munkaórából. Megtudtuk azt is, hogy ha ismert a határidő, akkor az időbecslések hajlamosak olyan irányba ferdülni, hogy határidőre teljesíthetőek legyenek a feladatok (pszichológiai hatás). Az időbeli becslés tehát az első gondolat ellenére nem túl precíz.

Jobb hatásfokot érhetünk el, ha alternatív módszerként az agilis módszertanokban elterjedt relatív becslést alkalmazzuk. A lényege, hogy veszünk egy olyan feladatot, amelyet mindenki ismer a csapatból, ezt etalonnak nevezzük ki, és ennek a komplexitásához, méretéhez képest viszonyítjuk a kérdéses, becsülendő feladatot. A becslést a csapat közösen végzi a planning poker segítségével. A mértékegység ebben az esetben nem idő, hanem egy dimenziónélküli szám. (Amelyet nevezhetünk sztoripontnak, ahogy a Scrum teszi.) Így tehát függetleníthetjük magunkat az időtől, elvonatkoztatunk tőle, és egy absztrakt mértékegységben végezzük a becslést.

Ugyan az előadó hangsúlyozta, hogy az idővel nem kalkulálunk, azért valljuk be, pontosan erről van szó, csak egy más formában. (Minek becsülnénk, ha nem arra lennénk kíváncsiak, hogy mennyi ideig tart a feladat?) A becsült komplexitást egyenesen arányosan az időnek feleltetjük meg: ha van egy kéthetes sprintünk, tudnunk kell, hogy eközben a csapat pl. 30 sztoripontot tud elvégezni. Tehát, akármennyire is becsüljük a feladatokat sztoriponttal, 30 sztoripont = 2 hét, azaz 3 sztoripont = 1 nap. A lényeg, hogy a becslés pillanatában felejtsük el az időt, és relatív becslést alkalmazzunk egy már ismert feladat alapján.

Aki új volt a Scrum-ban, az hallhatott arról, hogy nem csak idő alapon becsülhetünk, hanem attól elvonatkoztatva, aki pedig már ismerte a problémakört, az mélyíthette ismereteit. Nekem például új volt az, hogy eredetileg a Scrum-ban idő alapon történt a becslés, és a fejlődése során később tértek át a relatív becslésre.

Az előadás lendületes, lényegretörő volt. Az előadó a sok személyes példa által számomra hitelesnek tűnt, és az is érződött, hogy már sokszor adott elő.

Domain Driven Design szituációs játék

Bevallom őszintén, hogy amikor decemberben erre a klubdélutánra bukkantam, és azt olvastam, hogy ennek a szituációs játéknak a témája az, hogy egy szakterületi tudást hogyan alakítsunk UML-modellé, letettem arról, hogy eljöjjek. Én nem hiszek ebben a megközelítésben. Végül Csuti meggyőzött, hogy nézzünk el.

Ez nem egy előadás, inkább egy interaktív "show" volt. Zsuffa Zsolt először egy rövid bevezetőt tartott. Említésre került, hogy a DDD atyja Eric Evans, akinek a könyvét én is minden fejlesztőnek ajánlom, akit érdekel az, hogy hogyan lehet a komplex üzleti problémákat jól megoldani. 

Zsolt kiemelte, hogy a DDD lényege a Domain Model, a paradigma hátterében pedig az objektum orientált programozás és az UML áll - bár bevallotta, hogy ezt így nyíltan (hogy az UML a DDD része lenne) Evans soha nem állította. És ebben nagyon igaza is van! A könyv és Evans megnyilvánulásai ugyanis mind azt hangsúlyozzák, hogy az UML csupán egy eszköz, amely segítheti a kommunikációt, de semmiképpen nem az a megjelenési forma, amely elsődlegesen közli a Domain Model-t. Ugyanis az maga a kód. Az OOP-vel kapcsolatban pedig az a helyzet, hogy leginkább ez a paradigma alkalmas ma arra, hogy a Domain Model-ben rejlő nagyfokú komplexitást a leghatékonyabban kezeljük. Maga Evans is emleget más paradigmákat a könyvében (pl. logikai programozás), de arra a következtetésre jut, hogy nem alkalmasak a gyakorlatban a felmerülő problémák hatékony kezelésére. Tehát a DDD nem igazán az OOP-ről szól, annak ellenére, hogy a megvalósítás során az OOP-t használja, mint eddigi legalkalmasabb leíró paradigmát.

Zsolt elképzelésének hátterében az áll, hogy amikor a fejlesztő (elemző) az ügyféllel beszélget, akkor a megismert fogalmak és az ezek közötti összefüggések alapján egy UML-osztálydiagramot célszerű készíteni. Jó ötletnek tartottam, hogy ezt élőben is prezentálta: a Magyar Szabadalmi Hivatal egy szakértőjét hívta meg, aki a szabadalmak, oltalmak, ügyek, beadványok, kérelmek, intézkedések, eljárások stb. világába vezetett el minket. A szakértő az általunk feltett kérdésekre válaszolt, ez alapján készült folyamatosan az ábra. A beszélgetés során feltárásra kerültek a fogalmak és a közöttük lévő kapcsolatok (pl. egy beadvány leír egy vagy több találmányt). Személy szerint sajnáltam, hogy a szakértővel történő beszélgetést félbe kellett hagyni, mert felizzott bennem a rejtett Sylar-képességem: úgy éreztem, nem volt elég az információból, meg akarom érteni az egészet! :)

Zsolt a lerajzolt UML-osztálydiagramot méltatta. Erős kritikai érzékem fellángolt:

  • "Az ügyfél előtt rajzolunk, ezáltal ő is látja, érti, miről beszélünk." - Mi is próbálkoztunk ezzel, de nem igazán jött be a dolog. Pedig semmi rosszat nem mondhattunk az ügyfélre. Jó gondolkozása volt, csak nem az OOP volt az élete. Meggyőződésem, hogy doksikba is teljesen felesleges UML-t rajzolni a mezei ügyfélnek, ha kövspecről van szó. (Lehet, hogy a bankos rendszerszervezők megértik, de a többség nem, és nem is érdekli.) Ha már rajzolni akarunk nekik, akkor jobban tetszik a gondolattérképes megközelítés. Mi már csak arra használjuk az osztálydiagramokat, ha valamilyen konkrét megoldást akarunk felvázolni egymásnak (fejlesztők). Utána letöröljük a táblát, és lekódoljuk.
  • "Ez a követelményspecifikáció!" - Ezt azért erős túlzásnak tartom. Valaki meg is jegyezte, hogy léteznek nemfunkcionális követelmények is, és azok nem ábrázolhatóak osztálydiagrammal. Másrészt pedig hiába térképeztük fel az üzleti fogalomrendszert, és rajzoltunk hozzá osztálydiagramot, ez nem sokat jelent az ügyfélnek: egyrészt ő tisztában van a saját fogalmaival, nem igazán érdekli a modell sem, másrészt kicsit nehezen bólint rá egy kövspecben egy osztálydiagramra, ami egyszerre 20 entitást ábrázol, és amin az entitások közötti kapcsolatrendszer leginkább egy szabásmintára emlékezteti. Másrészt egy osztálydiagram vajmi kevés. Egy statikus képet ábrázol, semmi folyamat nincs benne. Erre más leírások is kellenek (user story-k, use-case-ek, folyamatábrák - ki miben hisz).
  • "Az osztálydiagramból a megfelelő modellező eszközzel legenerálható a forráskód. És ez nagy előny, mert a domain model a legfontosabb!" Igen, legenerálható, de semmi haszna nincs. Mit érünk vele, hogy egy 20-30 entitásból álló Domain Model osztályait nem kézzel, hanem automatikusan generálva hozzuk létre? A kapcsolatokhoz létrejön egy Set vagy egy List, és akkor mi van? Ez a forráskódnak csak elenyésző része, hiszen ez csak az entitások osztályfejeinek definíciója + néhány mező deklarációja. A forráskód legnagyobb része magában a metódusokban van. Ha változik a domain model, nincs lehetőségünk újra generálni (hiszen minden, amit utána írtunk bele a kódba, elveszlik/elveszhet), ill. a táblára felrajzolt osztálydiagramot korántsem biztos, hogy egy az egyben kell megfelelteni az osztályoknak. Két dolog jut ezzel kapcsolatban kapásból az eszembe: az öröklődés helytelen használata (rajzon könnyű előrukkolni vele, kódoláskor sokszor hiba használni), a másik pedig, hogy ORM alkalmazása esetén bizonyos korlátok közé vagyunk szorítva. (A kódgenerálással kapcsolatban az MDA hívei biztosan másképpen vélekednek, és most megköveznek. Én nem hiszek abban, hogy a módszerük komplex rendszereknél hatékonyan működik.)
  • "Nem attól lesz jó a program, hogy jó a felhasználói felülete, hanem attól, hogy jó a Domain Model-je." - Kinek mi a jó... Ha nagyon jó a felhasználói felület, akkor az ügyfelet nem érdekli a mögötte lévő kód. Sajnos, ha trehányul van megírva egy kód, akkor ott minőségi és megbízhatósági problémák fognak fellépni. Sok esetben a trehány kódból következik, hogy a felhasználói felület sem lesz különb. Nem szól ez másról csak az igényességről.

Az volt az érzésem, hogy a hallgatóság igen nehezen fogta Zsolt szavait (ez leginkább az oda nem illő kérdésekből látszott). Nem volt túl összeszedett, kicsit csapongó volt, és önmagának is ellentmondott időként - ezt mintha el is ismerte volna :) ("Ha lenne pénz, vessző, paripa, akkor tökéletesen meg lehetne csinálni a kövspecet." - Nem igaz, mert az ügyfél nem tudja, hogy pontosan mit akar! Ez így ellentmond az agilis megközelítésnek: fejlesszünk iteratívan és inkrementálisan.). 

Én jórészt nem értettem vele egyet. Láttam, hogy lelkes, és várja a visszajelzéseket, de szerintem csak a felszínt kapargatta. Sajnáltam, hogy ezt a kedvenc témakörömet nem sikerült illően evangelizálni.

A klubdélutánról felvétel készült. Remélem, közzéteszik az egyesület honlapján.


2010. január 7., csütörtök

A szoftverfejlesztés gyakran elfeledett alapigazságai (fordítás)

Véletlenül találtam rá Robert L. Glass cikkére, amely a "Frequently Forgotten Fundamental Facts about Software Engineering" címet viseli.  Nagyon tetszett, véleményem szerint sok igazságot tartalmaz. Úgy gondoltam, érdemes lefordítani magyarra. A cikk 2001-ben írodott, nyomokban tartalmaz olyan gondolatot, ami 9 év elteltével már nem annyira aktuális, de ennek ellenére még mindig megállja a helyét.


Robert L. Glass: A szoftverfejlesztés gyakran elfeledett alapigazságai

Ez a cikk egyszerű gyűjteménye azon szoftverfejlesztéssel kapcsolatos tényeknek, alapigazságoknak, amelyekben hiszek. Ezt a listát azért teregetem itt ki, mert túl sok ember, aki magát szoftverfejlesztőnek, -tervezőnek, informatikusnak, programozó matematikusnak stb. tartja, egyáltalán nincs tisztában vele, vagy lehet, hogy egyszerűen már elfeledte.

Nem várom el, hogy egyetérts mindenben, talán az igazságok némelyike fel is fog idegesítni. Én örülök ennek, legalább elkezdődhet egy párbeszéd közöttünk, hogy mely tények valóban tények, és mi csupán az én élénk, kritikus képzeletem szüleménye. Most már elég a bevezetőből: lássuk, mik a leggyakrabban elfeledett alapigazságok a szoftverfejlesztésben! 

Komplexitás

[C1] A probléma komplexitásának 10% növekedése, a szoftvermegoldás komplexitásában 100%-os növekedést eredményez. Ne is próbáljuk ezt a körülményt elkerülni (habár a komplexitás csökkentése minden esetben kívánatos), ez egyszerűen így van. (Hogy miért igaz ez, ld. az RD2-es pontot a "Követelmények és tervezés részben".)

Az emberek

[P1] A legfontosabb tényező, amelynek a segítségével szembenézhetünk a komplexitással nem az a számos eszköz és technológia, amelyet a fejlesztők alkalmaznak, hanem sokkal inkább a minőségi fejlesztők maguk.
[P2] A jó fejlesztők akár 30x jobbak is lehetnek a középszerű programozóknál, az "egyéni különbségek" ("individual differences") kutatás szerint. A fizetésük nem lehet alkukérdés, a szoftveriparban ők jelentik a legnagyobb üzletet.

Eszközök és technológiák

[T1] A legtöbb szoftvereszköz és -technológia kb. 5-30% produktivitás- és minőségnövekedést eredményez. Egyszer valaki kitalálta, hogy ezek egy nagyságrendbeli előnnyel kecsegtetnek (10-es szorzó). A hype-olás a szoftverfejlesztés pestise.
[T2] Egy új eszköznek, technológiának a megtanulása kezdetben a fejlesztő produktivitásának hanyatlását és a termék minőségének csökkenését eredményezi. Csak akkor várhatjuk a tényleges előnyöket, ha a tanulási időszakon túl vagyunk.

A minőség

[Q1] A minőség bizonyos tulajdonságok halmaza. Mindenki különbözőképpen definiálja ezen tulajdonságokat, a leggyakrabban elfogadottak azonban a hordozhatóság, megbízhatóság, teljesítmény, ergonómia, tesztelhetőség, érthetőség és módosíthatóság.
[Q2] A minőség nem egyenlő a felhasználói elégedettséggel, a követelményeknek való megfelelőséggel és a költség, ill. határidő korlátok betartásával, azonban ezek között egy érdekes kapcsolat áll fenn: Felhasználói elégedettség = a termék minősége + követelményeknek való megfelelőség + szállítás a szükséges időben + megfelelő költségek.
[Q3] Mivel a minőség nem csupán a megbízhatóságot jelenti, ezért sokkal többről szól, mint a szoftverhibákról.
[Q4] Ha az egyik minőséggel kapcsolatos tulajdonságon javítunk, az gyakran a másik rovására megy. Pl. ha a teljesítményen növelünk, az gyakran a módosíthatóság rovására megy.

Megbízhatóság

[RE1] A hibák keresése és javítása durván 40%-a a kifejlesztés költségének. Ezért ez a legfontosabb fázis a (ki)fejlesztés életciklusában.
[RE2] Vannak bizonyos hibák, amelyket a programozók viszonylag gyakran elkövetnek. Ezek közé tartozik az off-by-one hiba (másnéven: +/- 1-es hiba), a definition vagy reference inconsistency (ha vki tudja, mire gondol a szerző, szóljon! - pityufiu), ill. a mélyebb tervezési döntések mellőzése. Ezért az olyan technikák, mint pl. az N-verziós (vagy többverziós) programozás, amely több, különböző fejlesztőktől származó megoldás alapján kísérel meg egy helyes végeredményt megállapítani, kudarcra vannak ítélve.
[RE3] Amikor egy tipikus programozó azt hiszi, hogy a program alaposan le van tesztelve, valójában kb. 55-60%-a van megfuttatva a kód logikai útvonalainak. Az automatizált eszközök, mint pl. a kódlefedettség-elemzők megemelhetik ezt a szintet 85-90%-ra. A 100%-os szint elérése szinte lehetetlen.
[RE4] Még ha a 100%-os kódlefedettségi szint elérhető is lenne (ld. RE3), akkoris a 100%-os lefedettség elégtelen kritérium lenne a teszteléshez. A szoftverhibák durván 35%-a köszönhető a hiányzó logikai útvonalaknak, a hibák további 40%-a az logikai útvonalak egyedi kombinációinak futtatásából ered. Ezeket nem lehet 100%-os kódlefedettséggel észrevenni. (Ez azt jelenti, hogy a 100%-os kódlefedettség a lehetséges hibák kb. 25%-át képes detektálni!)
[RE5] Nincs legjobb módszer a hibák megszüntetésére. A különféle technikák vegyítése elkerülhetetlen.
[RE6] (RE5 folyománya) A szoftverben mindig maradnak hibák, még a legkeményebb ellenőrzések után is. A cél egyrészt, hogy csökkentsük a számukat, de inkább az, hogy csökkentsük a hatásukat.

Teljesítmény

[EF1] A teljesítmény sokkal inkább a jó tervezés, jó architektúra kérdése, mint inkább a jó kódolásé. Úgyhogy ha a projekt követelményei között a teljesítmény kitüntetett, akkor azt az életciklus elején figyelembe kell venni.
[EF2] A magasszintű programozási nyelvekben írt kódok futási ideje - a megfelelő fordítói optimalizálások után - akár 90%-át is elérheti a vele egyenértékű, assembly-ben írt kódhoz képest. Ez azonban eléggé feladatfüggő: bizonyos feladatokat sokkal nehezebb hatékonyan magasszintű nyelvekben lekódolni.
[EF3] A méretre vagy futási időre történő optimalizálás egymással ellentétes. Az egyikben történő javítás rontja a másikat.

Karbantartás

[M1] A minőség és karbantartás között érdekes kapcsolat áll fenn (ld. Q3, Q4).
[M2] A karbantartás tipikusan a teljes szoftverköltség 40-80%-át (átlagosan 60%-át) viszi el. Ezért általában ez a legfontosabb fázis.
[M3] A továbbfejlesztések durván a szoftverkarbantartási költségek 60%-áért felelősek. A hibajavítás csak 17% körül van. Ígyhát a szoftverkarbantartás leginkább a régi programban történő új funkciók hozzáadásáról szól, nem pedig a hibajavításról.
[M4] Az előző két szabályt hívhatjuk a szoftverek "60-60-as szabály"-ának.
[M5] A legtöbb szoftverfejlesztéssel és -karbantartással kapcsolatos feladat azonos - kivéve azt a plusz karbantartással kapcsolatos feladatot, amikor megkell érteni, hogy mit is csinál a létező termék. Ez a domináns karbantartási tevékenység, kb. 30%-át viszi el a karbantartási időnek. Így aztán nem teljesen alaptalan az az állítás, hogy a karbantartás nehezebb, mint a fejlesztés.

Követelmények és tervezés

[RD1] A határidőből kifutó projektek egyik leggyakoribb oka az instabil követelmények (a másikat ld. ES1).
[RD2] Amikor a projekt a követelményfelmérési szakaszból a tervezési szakaszba jut, az a "származtatott követelmények" robbanását eredményezi. A tervezési fázisban elkészülő követelménylista gyakran 50x nagyobb az eredeti követelménylistánál.
[RD3] Részben ez a robbanás okolható azért, hogy olyan nehéz nyomonkövetni a követelményeket (az eredeti követelmények megvalósulását az egymást követő projektfázisok egyes projekttermékeiben), annak ellenére, hogy mindenki egyetért, hogy a nyomonkövetésnek meg kellene valósulnia.
[RD4] Egy szoftveres problémára ritkán adódik csupán egy legjobb megoldás. (Bill Curtis egyszer azt mondta, hogy ha egy szoba tele van szoftvertervező szakértőkkel, és bármelyik kettő véletlenül egyetért, akkor az már biztosan többség.) Ennek következménye például az is, hogy az újrafelhasználható tervezési megoldásokra irányuló kísérletek olyan sokáig ellenálltak a jelentős fejlődésnek.

Review-k és vizsgálatok

[RI1] A szigorú (code) review-k gyakran szüntetik meg a szoftvertermék hibáinak 90%-át még mielőtt az az első teszteléseken átesne. (Sok kutatási eredmény szól erről. Hát, persze! Honnan is tudjuk, hogy mikor találtuk meg az összes hiba 100-át?!)
[RI2] A szigorú (code) review-k sokkal hatékonyabbak, költségkímélőbbek, mint bármely más hibamegszüntető stratégia, beleértve magát a tesztelést is, de nem szabad, hogy magát a tesztelést helyettesítse. (Ld. RE5)
[RI3] A szigorú review-zást jól csinálni extrém kihívás, és a legtöbb szervezet nem is csinálja, legalábbis nem az összes szoftverrel kapcsolatos termékükre (beleértve a dokumentációkat is).
[RI4] A szállítás utáni eredmények áttekintését általában fontosnak tartják, mert mérhető válik az ügyfél elégedettsége, és terepet biztosít a folyamatok fejlesztésére. Mégis a legtöbb szervezet nem csinálja. Amikor ezeket a review-kat meg kellene tartani (3-12 hónappal a szállítás után) a review potenciális résztvevői már szét is szóródtak más projektekre.

Újrafelhasználhatóság

[REU1] Az újrafelhasználhatóság kicsiben (szubrutinok könyvtárai) kb. 50 évvel ezelőtt kezdődött, és viszonylag megoldott probléma.
[REU2] Az újrafelhasználhatóság nagyban (komponensek szintjén) jórészt még mindig megoldatlan, annak ellenére, hogy mindenki egyetért abban, hogy fontos és kívánatos dolog.
[REU3] Véleménykülönbségek találhatóak abban, hogy _miért_ nem megoldott még mindig a komponens szintű újrafelhasználhatóság. A legtöbben úgy gondolják, hogy nem technológiai, hanem menedzsment probléma (szándék, nem szakértelem kérdése). (Mások szerint az a nehéz, hogy a különféle programozási feladatok között megtaláljuk a közös részproblémát. Ha ez igaz, akkor ez azt jelenti, hogy a "nagybani" újrafelhasználhatóság relatív megoldatlansága a szoftver természetének és a szoftverek által megoldott problémák velejárója.)
[REU4] A nagybani újrafelhasználhatóság kapcsolódó rendszercsaládok között működik a legjobban, ezért szakterületfüggő. Ez leszűkíti a lehetséges alkalmazási lehetőségét.
[REU5] A minta-újrahasznosítás az egyetlen megoldás a kód újrafelhasználhatóságának problémájára.

Becslés

[ES1] A határidőből kifutó projektek egyik leggyakoribb oka az optimista becslés (a másikat ld. RD1).
[ES2] A legtöbb becslést még az életciklus elején végzik. Ez teljesen érthető, amíg rá nem jön valaki arra, hogy ez az egész még a követelményfelmérés előtt történik, akkor, amikor még nem is értjük a problémát. Ígyhát a becslések legtöbbször rossz időben történnek.
[ES3] A legtöbb becslést - legalábbis néhány kutató szerint - a felső menedzsment vagy a marketing készíti, nem pedig azok az emberek és főnökeik, akik magát a szoftvert készítik. Ígyhát nem is a megfelelő emberek végzik a becslést.
[ES4] Ahogy a projekt halad, a becsléseket ritkán vizsgálják felül. Ígyhát a rossz időben és a nem megfelelő emberek által készített becslés soha nem kerül javításra.
[ES5] Mivel a becslések hibásak, nincs okunk arra, hogy azt feltételezzük, hogy a szoftverprojektek költségen és határidőn belül fognak elkészülni. Pedig mindenki azt hiszi!
[ES6] Egy projekttanulmányban, amely képtelen volt a becslések szerinti elvárásokat teljesíteni, a menedzsment úgy látta, hogy a projekt egy bukás volt, a technikai résztvevők viszont életük legsikeresebb projektjének tartották! Ez jól illusztrálja a menedzsment és a technikai szereplők szemszögéből a becslés szerepének és a projekt sikerének széttartását. A korábbi tények figyelembevételével ez aligha meglepő.
[ES7] A becslések által kitűzött célok elérése gyakran okoz nyomást, amely azt eredményezi, hogy a fejlesztők mellőzik a jó szoftverfejlesztési technikákat. Ez abszurd ok miatti abszurd eredmény.

Kutatás

[RES1] Sok kutató hirdeti az igét ahelyett, hogy vizsgálódna. Ennek eredményeképpen (a) néhány fennhéjázott fogalom kevésbe értékes, mint amennyire a pártfogója gondolja, és (b) kevés az a kiértékelő kutatás, amely segítene megállapítani az új eszközök és technológiák tényleges értékét.


Ezek hát az én szoftverfejlesztéssel kapcsolatos igazságaim. Mik a Tieid? Azt várom, hogy ha párbeszédet kezdeményezünk egymással, akkor újabb tényekre derülhet fény, amiket vagy kifelejtettem, vagy amiknek nem voltam tudatában. Különösképpen az új tények érdekelnek, de természetesen arra is kíváncsi vagyok, ha valamivel nem értesz egyet. 

A szerző címe: rglass@indiana.edu (és angolul várja a hozzászólásokat :))


2010. január 6., szerda

A sprinttervezés (Scrum-sorozat 3/1. rész)

A Scrum-ról szóló cikksorozatomat egy gyorstalpalóval kezdtem, aztán arról írtam, hogy mi a célja a product backlog-nak, és hogy hogyan készül. Most a sprinttervezésről lesz szó. Először a tervezés filozófiájáról írok és felsorolom az eszközeit. A következő részben a tervezés forgatókönyve kerül ismertetésre.

A cikk végén egy kis kitérőt tartok: arról a csapatról és projektről írok, amelyben sikerült a Scrum-ot meghonosítanunk.

Mi a sprinttervezés? 

A sprintet megelőzően egy tervezésre kerül sor, ahol a csapat elkötelezi magát az éppen legfontosabb sztorik lefejlesztésére. Az elkötelezés közös becslés alapján történik. A csapat a product backlog elejéről kiválasztja azokat a sztorikat, amik a sprintbe beleférnek.

Minek a sprinttervezés?

Ahhoz, hogy egy sprintnek neki gyűrközhessen a csapat, megfelelő tervezés szükséges. A tervezés során érti meg a csapat, hogy miket fog megvalósítani a sprint során, és a tagok közösen becslik meg, hogy az egyes lefejlesztendő sztorik mekkora méretűek (szándékosan nem azt írtam, hogy ráfordítást becsülnek). Ez alapján a becslés alapján határozzák meg, hogy a fix hosszúságú sprint alatt (ami a szakirodalom szerint tipikusan 1-4 hét) mi kerülhet be a sprintbe a product backlog-ból.

A legtöbb szakirodalom csupán a tervezés lebonyolításával foglalkozik. A saját tapasztalatunk szerint ahhoz, hogy egy tervezés és a későbbi sprint hatékony lehessen, bizonyos előkészítést kell elvégezni. Az előkészítésnek két kulcsfontosságú elemét azonosítottuk. 

Előkészítés 1. fázisa: "Legyen a product backlog up-to-date!"


A sprinttervezést jó eséllyel megelőzte egy korábbi sprint (kivéve, ha épp az első sprinttervezésünknél tartunk), ez alatt az idő alatt is változhatott a product backlog. Miért? 

  1. Változhattak a körülmények (külső tényezők hatására). Pl. a határidő vmi miatt korábbra vagy későbbre került, esetleg kiderült, hogy a szoftvert egy másik szervezetnél vezetik be először (ahol esetleg más funkciók fontosabbak a teljes szoftverből).
  2. Az előző sprinttervezés, ill. az utána következő sprint közben a csapat tanult, és jobban megismerte az üzleti problémát. Pl. rájött a csapat, hogy egy sztori szétbontható több - eltérő prioritású - kisebb sztorira, vagy pl. sprint közben "előjött" egy megbújó üzleti probléma (amely új sztoriként beillesztésre kerül a product backlog-ba).

A product backlog-ot célszerű a következő sprint elejére (tervezés előtt) frissíteni, hogy a tervezés az aktuális prioritások alapján mehessen. 

Előkészítés 2. fázisa: "Tudjuk, hogy mit jelentenek az egyes sztorik!"

Az a tapasztalatunk, hogy hiába van egy aktualizált product backlog, sokszor ennyi nem elégséges a tervezéshez. Ennek az oka az, hogy általában nem mindenki számára világos, hogy valójában mi is az, amit meg kell valósítani az egyes sztorikban. Elég kínos a tervezéskori "improvizálás", amikor ott derül ki, hogy az egész csapatnak fogalma sincs arról, hogy pontosan mit is jelent egy-egy sztori. Ilyenkor egy jó adag bizonytalanság települhet rá a csapatra, ami a további tervezés és az utána következő sprint bukását eredményezheti.

Tegyük fel, hogy a következő legfontosabb sztorink a product backlog-ból a következő: "felhasználók és szervezeti egységek összerendelése". Hogyan fogja tudni megérteni a csapat, hogy mit is kell itt csinálni? Hol van az a tudás, hogy ez mit is jelent valójában? 

A saját csapatunkban én vagyok a felelős azért, hogy a következő sprinttervezésre a product backlog priorizálva legyen, és elkészüljön minden egyes sztoriról egy olyan minimális leírás, amelyből a csapat megérti, hogy mi a feladat. Ezt a rövid (1-2 oldalas) doksit mindenki a tervezés előtt elolvassa, hogy képben legyen. (Ha valami annyira triviális, hogy írni sem kell róla, akkor kihagyom a doksiból.) A dokumentum közvetlenül a sprinttervezés előtt készül el (ez nem a követelményspecifikáció), ezért mindig a legaktuálisabb tudást reprezentálja. Informális, pont annyi van benne, amennyi szükséges. Nincsenek benne UML-ábrák, rendszerint nincsenek benne implementációs, technológiai részletek.


Felmerülhet a kérdés, hogy mi alapján írom meg én önkényesen a sztorik leírását. 

A projekt kezdetekor az ügyfél oldaláról áthívtunk a csapatba egy olyan személyt, aki értett az üzleti problémához. (Őt nem is az ügyfél, hanem a mi cégünk foglalkoztatta tovább.) Hívják Őt Albertnek. Ő az üzleti szakértőnk (business expert). Bármilyen kérdésünk van, ő azonnal válaszol. Nem kell az ügyféltől időpontot kérnünk, felkészülnünk az interjúkra, mert ott van Albert. 

Kezdetben Albertet közösen "zaklattuk". Az üzleti probléma elég bonyolultnak bizonyult, a csapat részéről felmerülő rengeteg kérdésből megismert válaszok lassan formálódtak csak egy konzisztens modellé. Igazán kemény dió volt kibogozni, hogy mi is a feladat, mit is jelentenek az egyes üzleti fogalmak. Mivel engem érdekelt az üzleti probléma, úgy alakult, hogy én lettem az, aki a legtöbbet kezdett beszélgetetni Alberttel. Én lettem a probléma üzleti elemezője (business analyst). Megértettem a gondolkozását, megértettem az üzleti problémát. Rendszereztem a gondolatait, és egy nagyvonalú modellé gyúrtam a fejemben. A beszélgetések során Albertnek a saját gondolatai is rendszereződtek. Ezek az elsődleges beszélgetések határozzák meg a mai napig is a csapat továbbhaladásának az irányát. 

A munkafolyamat tehát a következő: Albertből kiszedem a következő sprinthez a sztorikhoz szükséges összes információt, közösen megrágjuk a témát, én röviden leírom egy doksiban az infókat, és a csapattal közösen átbeszélünk mindent a tervezésen.

Mi ilyen módon adaptálódtunk a környezetünkhöz. Nem gyártunk tonnaszám haszontalan dokumentációkat, előnyben részesítjük a szóbeli kommunikációt, a tudás a csapattagok fejében és a jól megírt kódban található.

Ez nem kifejezetten a Scrum-módszertan része, de szükséges tudatosítani azt, hogy egy Scrum-folyamat megvalósításakor (is) számos egyéb problémára kell odafigyelni és megoldani.

Idő helyett becsüljük a sztori méretét!

A Scrum ajánlásai alapján ahhoz, hogy a projektünket valahogy az időskálára helyezzük, nem célszerű közvetlenül az idővel becsülni. Érdemes elvonatkoztatni, és a lefejlesztendő sztorikat, elvégzendő feladatokat pontokban meghatározni. A pontot másképpen sztoripontnak is nevezik, hiszen egy sztori relatív méretét (esetleg komplexitását) adja meg.

Mekkora méretű feladatot is jelöl 1 sztoripont? A válasz: mindegy, a lényeg, hogy a csapat ugyanazt értse 1 sztoripont alatt.

1. példa: mi úgy kezdtük a Scrum-ot, hogy 1 sztoripont alatt azt a feladatmennyiséget értettük, amennyit 1 ember 100%-os hatékonysággal 1 nap alatt el tud végezni (1 "biorobot" nap). Nehéz elképzelni, mégis megpróbáltuk: vajon hogyan dolgoznánk, ha a székünk egy WC lenne, és a szükséges tápanyagokat intravénásan vezetnénk a testünkbe, hogy a szükséges anyagcserére, táplálkozásra fordítandó időt is megspóroljuk? Döcögősen indult az elején a becslés, mindenki kétkedve és bizonytalanul becsült, de pár sprint után, kialakult mindenki fejében egy közel egységes elképzelés, hogy mit is értünk 1 sztoripont alatt.

2. példa: más csapatnál úgy rögzítették a sztoripont fogalmát, hogy kiválasztottak egy olyan korábbi "egészséges méretű" feladatot, amiről a csapat tudta, hogy mennyi idő alatt készítette el. Tudták, hogy kb. 5 napot vett igénybe a feladat, pontosan ismerték a feladat nehézségét, komplexitását is. Azt mondták, hogy legyen ez a feladat 5 sztoripont méretű. Minden később felmerült feladatnál ehhez a feladathoz képest becsültek: vajon kisebb vagy nagyobb méretű az új feladat az etalonhoz képest? Mennyivel?

Kapacitástervezés, a fókuszfaktor

A tervezés elején először meghatározzuk, hogy az elkövetkezendő sprintben hány sztoripontot tud teljesíteni a csapat. A mi csapatunk esetében (fenti 1. példa) - definíció szerint - 1 sztoripont 100%-os hatékonysággal pontosan 1 napot jelent, ezért egy ember elvileg pont annyi sztoripontot tud megcsinálni, mint ahány napos a sprint.

A valóságban mi 70%-os hatékonysággal számolunk. Ezt a hatékonysági tényezőt a Scrum-ban fókuszfaktornak (focus factor) nevezik. Ha valaki leterheltebb, és más feladatai is vannak, mint a projektben történő új sztorik fejlesztése, a fókuszfaktorát csökkentjük. Ha valamely napokon szabin lesz, akkor azokon a napokon nem "termel" sztoripontot.

Példa: 

2 hétig (10 munkanapig) tart a következő sprint, és 2009. január 4-én kezdődik. Van egy 4 fős fejlesztői csapatunk a következő tagokkal:

  • Jónás: a sprint első két napján szabin lesz, a default 70%-os fókuszfaktorral számolunk rá,
  • Döme: junior fejlesztő, 2 hónapja dolgozik a projekten, az ő fókuszfaktorát 50%-ban állapítottuk meg, az első héten szabin lesz,
  • Zalán: teljes mellbedobással tud a sprintben dolgozni, a default 70% fókuszfaktorral számolunk rá,
  • Iván: bizonyos support feladatokat is ellát a projekten, ha bejelentés érkezik az ügyféltől, kivizsgálja, és megoldást talál rá. Az ő fókuszfaktorát 30%-ban állapítottuk meg.

Egy táblázatot készítünk a fentiek összegzésére (Excelt haszálunk). Azokon a napokon, amikor valaki nem dolgozik, 0-t írunk a megfelelő mezőbe, egyébként 1-et. (Előfordul, hogy a 0.5-öt is használjuk, ha valaki pl. csak fél napig van.)


A példában szereplő csapat a kéthetes sprint alatt 18.1 sztoripontot tud teljesíteni.

Téli időszakban vagy H1N1-fertőzés idején is - a fennálló kockázat miatt - csökkenthető a csapat fókuszfaktora. Csökkentett fókuszfaktorral számolunk egy csapattagnál akkor is, ha hosszú szabadságról tér vissza.

A fókuszfaktorok Scrum-ban történő alkalmazása nem egzakt tudomány, tapasztalati alapon kell őket "belőni". Ha sikeres egy sprint, meg lehet kísérelni a fókuszfaktorok növelését (ergo több feladatot vállalhat a csapat). Ha elbukik egy sprint, és a bukás oka az volt, hogy sok feladatot vállalt a csapat, akkor csökkenthető a fókuszfaktor. Ne feledjük, hogy más tényezőket is figyelembe kell vennünk, amikor a fókuszfaktorokat megállapítjuk, vagy változtatni kívánjuk:

  • Sprintről sprintre más és más feladatokat csinál a csapat, ezért a becslések egyfajta bizonytalanságot visznek a rendszerbe. Például: lehet, hogy az egyik sprintben túlbecsültük a feladatokat, a másikban alulbecsültük.
  • Változhat a sztoripont jelentése: fél év múlva ugyanazt jelenti-e a csapat számára 1 sztoripont?

Cél, hogy meghatározzuk, mennyi sztoripontot tud a csapat egy sprint alatt megcsinálni (ezt hívják sebességnek, angolul velocity-nek). Ehhez leginkább az kell, hogy a csapatban fixálódjon a sztoripont fogalma, ismerjük a fókuszfaktort, és jól menjen a becslés. Pár sikeres sprint után ezek elérhetőek. Ha megismertük a csapat sebességét, középtávú becslésekre lehetünk képesek a product backlog alapján.

Planning poker

Amikor a csapat becsül, sztoripontokat alkalmaz az éppen becsülendő feladat méretének meghatározásához. A Scrum-ban mindenkinek saját kártyái vannak, amiken a következő számok találhatók:  



(Mi a kártyákat magunk nyomtattuk, de lehet rendelni online is kártyapaklit.)

A számok nagyjából Fibonacci-sorozatot követnek (azaz a sorozat egy eleme az őt megelőző két szám összege). Azért választották így a kártyákon lévő számokat, hogy a becslések során megkönnyítsék a döntést. Minél nagyobb méretű egy sztori, annál nehezebb megmondani, hogy pontosan hány sztoripontot is ér. Másfelől nem is érdemes túlbonyolítani: ha nagyméretű a feladat, ne is álmodjunk róla, hogy pontosan meghatározzuk, mennyi idő/sztoripont a megvalósítása. 

Megjegyzések:

  • Azért vannak a kártyák, hogy ne befolyásoljanak a többiek becsléskor (és magunk se befolyásoljuk őket). Egyszerre kell mindenkinek felemelnie a saját választott kártyáját.
  • Az gyanús, ha tervezés közben nagyméretű sztoripontok röpködnek (mondjuk 5-nél nagyobbak). Az azt jelenti, hogy a sztorit több kisebb sztorira lehet bontani. Ilyenkor gyakran előfordul, hogy a széteső alsztorik nem is egyforma prioritásúak (ld. előző írásomat a product backlog-ról). Ha létrejön egy ilyen kevésbe fontos alsztori, rakjuk be a product backlog-ba, ne csináljuk meg ebben a sprintben. 
  • A nagyméretű sztoripontokat rendszerint a product backlog-ban történő becslésnél alkalmazzuk (ld. szintén az előző írásomat).
  • A 0 méretű feladatok a pár perces feladatokat jelentik (max. 10-20p).
  • A ? azt jelzi, hogy a csapattagnak fogalma sincs, mennyi sztoripontra becsülje az aktuális feladatot. A tapasztalat az azért, hogy egy idő után mindenkinek van valami elképzelése, tehát érdemes felemelni egy számot. Ha van új csapattag, természetesen nála érthető a bizonytalanság.
  • A kávé jelzés mutatja, hogy a csapat elfáradt a tervezés közben. Érdemes egy szünetet tartani. :)

Megismertük a tervezés eszközeit. Most már minden adott ahhoz, hogy a tervezés forgatókönyszerűen ismertetésre kerüljön. A sorozat következő része ezzel folytatódik.

Egy kis kitérő: a csapat, a projekt

Fontos egy rövid áttekintést adnom a szóban forgó projekt hátteréről. Így talán közelebb hozhatom az Olvasót ahhoz, hogy nálunk hogyan is épül fel a csapat, és miről is szól a projekt. 

  • technológia:
  • üzleti oldal:
    • állami szektor,
    • üzleti probléma: elektronikus iratkezelés, irodai környezet,
    • ügyfél szervezet mérete: 15.000 fő,
    • az üzleti probléma igen komplex.
  • a csapat (az összetétele változott az idők során, ez egy fél évvel ezelőtti állapot):
    • 5 fejlesztő (ebből 2 junior fejlesztő), 
    • 1 tesztelő,
    • 1 üzleti szakértő (korábban az ügyfél oldalon dolgozott, áthoztuk a projektre),
    • ScrumMaster,
    • a teljes csapat (a ScrumMastert leszámítva) egy szobában dolgozik,
    • velocity: kb. 30 sztoripont/sprint (12 nap).
  • a projekt:
    • zöldmezős egyedi szoftverfejlesztés,
    • 2007-ben indult a fejlesztés,
    • azóta is tart, a vége még jó pár év múlva várható (a 15.000 fős szervezet egyes részeinek bevonása éves ütemezéssel történik meg).



A cikksorozat részei:

    3/1. A sprinttervezés
    3/2. A sprinttervezés
    4. A sprint (jövőben)
    5. Retrospective (jövőben)
    6. Hogyan induljunk? (jövőben)
    7. A Scrum és az agilitás (jövőben)
    8. A Scrum sötét oldala (jövőben)
    9. Scrum szótár (jövőben)
    10. Scrum összefoglalás (jövőben)