Alla som har jobbat i Scrum, och det har väl de flesta av oss vid det här laget, har säkert ställt sig frågan: Vilken uppgift ska jag ta på mig härnäst?

Den mer generella frågan, som den här bloggposten vill ge ett svar på, är: Hur ska uppgifterna i backloggen prioriteras mot varandra?

Det här brukar vara mer konst än vetenskap och man gör det lite på känn; vid behov, när det finns tid över, eller vid särskilda prioriteringsmöten. Aspekter som brukar vägas in är hur lång tid uppgiften tar, hur viktig den är och kanske även dess svårighetsgrad.

För att försöka lösa det här problemet en gång för alla har jag identifiera fem olika kriterier som jag anser bör vägas in i bedömingen. Vidare har jag rangordnat dessa kriterier mot varandra och slutligen har jag satt ihop dem till en formel som tar hänsyn till rangordningen och som ger en totalsumma att prioritera efter, utifrån hur många poäng man satt på varje dimension.

Alltså: Istället för att sätta upp fingret i luften och känna efter hur uppgifterna bör prioriteras, bedömmer man dem enskilt i fem olika dimensioner och räknar sedan fram en inbördes rangordning.

De fem kriterierna är som följer:

  1. Funtamentalitet
    - det första kriteriet har att göra med hur central för systemets ändamål en uppgift är. Jag anser detta vara det viktigaste kriteriet. Ett system bör byggas inifrån ut. Om inte kärnfunktionaliteten fungerar tillfredställande spelar det mindre roll hur bra kringfunktionerna är. Lägger man för stor vikt vid kringfunktioner så kanske man utvecklar fel system och borde istället utveckla ett system där kringfunktionerna är centrala. Alltså; börja med fundamental funktionalitet och gå sedan mot allt mer perifera funktioner när det mer basala finns på plats och fungerar som det ska

  2. Enkelhet
    - För att undvika att bygga på den tekniska skulden så bör man som nummer två värdera hur en uppgift påverkar systemets totala komplexitet. Om det finns uppgifter som minskar den totala komplexiteten eller åtminstone inte ökar den så bör man ta dem före uppgifter som ökar komplexiteten. Jobbar man i den riktningen så skapar man allt hållbarare fundament som kan bära upp en allt större funktionell överbyggnad. Annorlunda uttryckt: De uppgifter som idag adderar mycket komplexitet kan imorgon addera liten eller ingen komplexitet om man först har förstärkt och renodlat fundamenten/koncepten.

  3. Värde
    - Först på tredje plats har jag rankat det som vid första anblicken kan tyckas vara det viktigaste kriteriet, nämligen hur stort värde en uppgift adderar till systemet. Anledningen är att ett IT-system är som ett isberg; den lilla synliga toppen motsvarar funktionalitet som ger ett direkt värde för kunden och allt annat är stödstrukturer som krävs för att bära upp de värdebärande funktionerna. Efter hand som ett system växer sig större och mer komplext minskar den värdebärande funktionalitetens andel av den totala massan. Om man bara satsar på att addera värde så riskerar överbyggnaden att bli större än vad fundamentet kan bära upp och hela systemet kollapsar under sin egen tyngd. Därför bör fundamentalitet och komplexitet värderas över värdeskapande.

  4. Svårighetsgrad
    - svårighetsgrad är i stort sett ekvivalent med risk: Risk att man inte hittar någon som är kompetent nog att utföra uppgiften, risk att oväntade problem uppstår under utvecklingen, risk att funktionen skapar nya buggar, och risk att man har missbedömt någon av de andra kriterierna. Därför bör svårighetsgraden vägas in när man prioriterar uppgifter. Börja med det som är enkelt. Ju längre arbetet framskrider desto mer erfarenhet samlar utvecklarna och ju starkare fundament finns att bygga mer komplicerade funktioner på. Bygger man rätt så tenderar svåra uppgifter som man skjuter på framtiden att te sig allt enklare med tiden och kommer därför prioriteras allt högre, allt annat lika.

  5. Tidsåtgång
    - Sist och faktiskt minst väsentlig är tidsåtgången. I de flesta IT-projekt beror en överhängande del av tidsåtgången på att man får betala för gamla synder, det vill säga handskas med teknisk skuld. Det kan röra sig om så mycket om en faktor tio eller en faktor hundra i tidsskillnad mellan att bygga en funktion på ett starkt och väl underhållet fundament och att bygga den på ett svagt och överkomplext fundament. Därför blir tidsåtgången ofta mer en funktion av hur väl underhållet systemet är än en funktion av hur stor uppgiften är. Icke desto mindre bör naturligtvis tidsåtgången beaktas eftersom effektiviteten i utvecklingen totalt sett är en funktion av värde delat med tid.

Man poängsätter alltså varje uppgift efter var och en av ovan beskrivna dimensioner. Sedan summeras poängen, och uppgifter med lägre poäng prioriteras före uppgifter med högre poäng.

För att väga in rangordningen mellan dimensionerna så har de olika skalor, där de viktigare dimensionerna har fler poäng att fördela än de mindre viktiga. Närmare bestämt har Fundamentalitet sju poäng att fördela, Enkelhet sex poäng och så vidare, ner till Tidsåtgång som har tre poäng. Varför en kortare poängskala ger en mindre total vikt i sammanräkningen behöver kanske motiveras. Man kan tänka så här: Differensen mellan minsta och största poäng är mindre ju kortare skalan är, alltså ger en kortare skala en mindre addering till totalsumman. 

Poängskalorna är som följer:

Fundamentalitet:

1: Fundamental
   - utan vilken systemet inte kan köras

2: Essentiell:
  - utan vilken systemet inte är ändamålsenligt

3: Kärnfunktion
 - utan vilka systemet inte kan anses fullt funktionellt

4: Basal funktion
 - utan vilka systemet inte kan anses komplett

5: Extra funktionalitet
 - som lägger till det som behövs i anslutning till det basala och gör systemet fullödigt

6: Nice to have / bra att ha

 - som ytterligare förbättrar systemet

7: Goldplating / Förgyllning
 - som adderar det lilla extra, t ex snyggare layout, grafiska effekter eller arbetsbesparande extra kommandon.

Enkelhet:

-2: Väsentlig förenkling

-1: Viss förenkling

0: Ingen förändring i komplexitet

1: Viss komplexitetsökning

2: Väsentlig komplexitetsökning

3: Mycket stor komplexitetsökning

Värdeskapande

0: Skapar inget direkt värde för användaren (refaktorering)

-1: Litet värde

-2: Medel värde

-3: Stort värde

-4: Mycket stort värde

Svårighetsgrad:

1: Trivialt

2: Enkelt

3: Medel

4: Svårt

Tidsåtgång:

1: Kort (minuter)

2: Medel (någon eller några timmar)

3: Lång (många timmar eller flera dagar)

Genom lite huvudräkning får man snabbt fram att totalsumman som man prioriterar efter kan variera mellan -3 och +17, alltså en total differens på 20; där Tidsåtgång adderar 2, Svårighetsgrad 3 och så vidare, upp till Fundamentalitet som adderar 6 steg.  

Slutligen:

  • En uppgift som är mycket svår ska inte utföras direkt, istället ska man titta på vilka förändringar i fundament och arkitektur som krävs för att förenkla uppgiften

  • En uppgift som tar lång tid (3 poäng) ska alltid delas upp i mindre uppgifter som värderas var för sig och prioriteras mot övriga uppgifter på nytt

  • Uppgifter kan ha beroenden som dikterar i vilken ordning de måste utföras. I sådana fall är det den högst rankade uppgiftens rangordning som bestämmer när andra uppgifter som den är beroende av ska utföras.

  • En uppgift som har ett positivt värde om man summerar enkelhet och värde (alltså skapar mer komplexitet än värde) bör tas bort från backloggen. En uppgift där enkelhet + värde = 0 bör noga övervägas vilket problem den löser och om problemet kan lösas på ett sätt som samtidigt ökar systemets samlade värde och potential (= enkelhet). Om inte bör en motivering till varför uppgiften är värd att utföras skrivas in på uppgiftskortet. 
Den ovan beskrivna metodiken / algoritmen är förmodligen lite för hardcore för de flesta Scrum/Kanban-projekt, men i stora projekt där prioritering mellan många uppgifter under tajta tidsramar blir ett stort huvudbry för projektledare och scrummästare kanske den kan tjäna som inspiration, eller rent av går att tillämpa rakt av.
Artefakt betyder "konstgjort föremål". De uppstår inte av sig själva eller utifrån naturliga processer. Det finns alltid en intention bakom en artefakt. En artefakt kan inte heller fullständigt förklaras utifrån den miljö och det sammanhang den kommer ifrån. För att fullt ut förstå en artefakt måste man fråga dem vars intention ligger bakom skapandet av den.

Vår civilisation är uppbyggd av artefakter. Utan dem hade vi fortfarande gått runt på savannen och samlat kottar. Artefakter har uppenbarligen sina fördelar: Vi har hus som vi kan vila i när vi har gått på savannen och samlat kottar en hel dag. Vi har prydnadshyllor att lägga kottarna på, och vi har bilar så att vi kan nå längre ut på savannen och hämta de större och finare kottarna som finns längre bort, bara för att ta några exempel. Men i programkod är artefakter av ondo. Perfekt ren kod är fri från artefakter. Perfekt ren kod är självförklarande, eller som Ward Cunningham uttrycker det i Robert C. Martin's bok Clean code: "Du vet att du arbetar med ren kod när varje rutin du läser på det hela taget är vad du förväntar dig".

Kod som är självförklarande, eller "på det hela taget vad du förväntar dig" utifrån sammanhanget och kraven, har inga artefakter. Hade där funnits artefakter så hade det också funnits behov av förklaring. Artefakter föder artefakter, vilket är orsaken till att kod som inte hålls perfekt ren med tiden blir allt mer tungarbetad. En illa döpt variabel är en artefakt, liksom den extra kommentaren som behövs för att förklara den. En överdesignad arkitektur är en artefakt, liksom den extra kod som krävs för att uppfylla den. Kod som innehåller artefakter rostar med tiden, medan ren, naturlig kod håller sig frisk genom att ny kod får spira i gammal kod som multnar bort i ett ständigt kretslopp.

Att känna igen en artefakt är inte det lättaste, vilket förklarar varför även den mest samvetsnoggranne programmeraren har så svårt att hålla sin kod ren. Alla har sina fix och trix, förkärlekar och käpphästar, som kan kännas fullständigt naturliga för en själv men för andra framstår som de artefakter de är. Någon kanske vill ha ett kommentarsblock före varje metod, oavsett om det står något i det eller inte, eller en kommentar om varje in- och utparameter, oavsett om de tillför förklaringsvärde eller inte. Sådant är artefakter. Någon annan kanske inte tycker det är så noga om det finns en eller två eller tre radbrytningar mellan metoder och block, eller om en och annan bortkommenterad kodrad ligger kvar. Men varje onödigt tecken är skräp, a.k.a. rester av en artefakt. Ytterligare någon kan ha en förkärlek för fabriker och gränssnitt. Men om varje klass har sin egen fabrik och sitt eget gränssnitt så är det mycket troligt att några av dessa är artefakter.

Det enda sättet att upptäcka artefakter i sin egen och andras kod är genom kodgranskning. Att granska sin egen kod före varje incheckning och ta bort de artefakter man hittar är nödvändigt, men inte tillräckligt. Vi måste också granska varandras kod. Ju mer olik din och din kollegas kodstil är, desto nyttigare är det att ni granskar varandras kod. Incheckad kod ska se ut som om den hade uppstått som en naturlig följd av de interna och externa krav den har att uppfylla. Incheckad kod ska vara fri från personlig stil, fri från artefakter. En professionell programmerare avhåller sig från att sätta sin personliga prägel på koden. "Don't be clever". "Don't be cute."

För att hålla sin kod fri från artefakter måste du hålla ditt ego utanför arbetet. Det är inte din intelligens som skapar koden. Det är kraven som skapar koden. Du är endast jordmånen som tillåter koden att växa. Du vill att koden ska växa sig så rak och stark som möjligt för att uppnå sin fulla potential. Men försöker du styra den så böjer du den bara. Du kanske är expert på WCF, MVC, SQL, eller någon annan TBA. Bra! Det ger koden en rikare jordmån att växa i; Men låt koden välja var den vill växa utan att försöka påverka den. Lämna alltid ditt ego och dina egna ambitioner utanför processen. Och lyssna på dina kollegor som pekar ut de artefakter som just du är blind för.
 
Tack vare missionärer som Robert C. Martin är vi idag många som är medvetna om värdet av att hålla koden ren och fin. Men frågar man två programmerare så är det troligt att de har olika upfattningar om vad ren kod är, eller vad som är ren kod. Om vi flyttar fokus från kodens renhet till hur vi kan frigöra koden från artefakter så blir problemet mer konkret och därmed lättare att lösa. Artefakterna ger svaret på frågan vad som är ren kod och varför vi behöver kodgranskning vid sidan av testtäckning för att hålla koden ren. Så nästa gång du stöter på en artefakt i din eller någon annans kod, fundera på om den alls behövs, och i så fall, vilken som är den naturliga konstruktionen som den kan ersättas med. Med varje artefakt som koden befrias ifrån blir den lite renare, och om du alltid checkar in koden med åtminstone inte fler artefakter än den hade när du checkade ut den så har du receptet för ren kod och ett lyckat projekt.
Inom långdistanslöpning händer det emellanåt att en löpare går in i väggen. Det kan bero på att man har tömt tanken och fått slut på energi. Men en vanligare orsak är att man har samlat på sig för mycket mjölksyra så att musklerna inte längre kan tillgodogöra sig energin i blodet. Syreskulden har överskridit löparens smärtgräns. Följden blir att löparen måste gå ner i mycket långsamt tempo eller stanna helt, och ägna resten av dagen åt att återhämta sig. Loppet är kört.

Inom mjukvaruindustrin finns ett liknande fenomen. Symptomen är att produktiviteten i ett projekt minskar drastiskt. Nya defekter upptäcks i snabbare takt än de åtgärdas. Moralen hos utvecklingsteamet sjunker i takt med att irritationen hos användarna ökar. Snart börjar de duktigaste och mest erfarna teammedlemmarna lämna projektet och ersättas av inte så duktiga och inte så erfarna utvecklare. Vad som har hänt är att den tekniska skulden har överskridit projektets smärtgräns. Följden blir att nyutvecklingen måste gå ner i mycket långsamt tempo, eller upphöra helt. Snart nog så upphör även finansieringen och projektet måste avbrytas. Uppdraget har misslyckats.

Erfarna löpare vet att tricket att undvika att gå in i väggen, utöver en stadig frukost, är att hålla sig under sitt tröskeltempo, det vill säga det tempo där musklerna förbrukar lika mycket syre som kroppen kan förse dem med. Håller man sig under sin tröskelfart så ökar inte syreskulden i musklerna. En vältränad löpare kan hålla igång på det sättet under flera timmar.

Men ett långlopp kräver mer av en tävlingslöpare än att kunna hålla ett jämt och lagom högt tempo. Man måste kunna hantera långa eller branta backar. Ibland måste man svara när en motståndare gör ett ryck. Eller så hamnar man efter och måste jaga ikapp klungan. Någon gång ser man själv en möjlighet att dra ifrån, kanske just i den där långa uppförsbacken. Då måste man tillåta sig att tillfälligt bygga upp en syreskuld som man sedan får betala av med ränta. Men väntar man för länge med att betala så straffar det sig, både i tid och smärta.

Långdistanslöpning är något som kräver övning. Förutom att den rent fysiska kapaciteten måste tränas upp, så tar det även tid att hitta balansen mellan fart och distans som gör att man håller lagom till mållinjen. Väldigt oerfarna löpare som ska springa sitt första lopp tenderar att rusa i början tills de överhettade, flämtande och med mjölksyrastinna och krampande muskler tvingas stanna.

Att drabbas av mjölksyra och gå in i väggen gör ont, så den oerfarne löparen lär sig snabbt att ta det lugnare. Redan vid det andra loppet tar hon sig sannolikt i mål, och snart kan hon till och med börja njuta av att pressa sin kropp att prestera på toppen av sin förmåga, utan att överskrida den. Hon rusar inte längre i starten utan springer lugnt och avslappnat från första till sista steget, kanske med en spurt den sista biten för att krama ut de sista krafterna.

Inom mjukvaruindustrin ser vi en liknande tendens. Oerfarna team rusar i början, påhejade av projektledare och produktägare med dollartecken för ögonen. Nästan-färdiga funktioner levereras i en rasande takt och läggs i hög ovanpå varandra. Produktägaren och projektledaren skrattar hela vägen till mötena med sina uppdragsgivare där de med Powerpoint-slides och välförberedda demos visar hur fantastiskt bra det går. Defekter avfärdas som barnsjukdommar man måste räkna med, eller ren otur. Finansiärerna är också glada och allt är frid och fröjd.
Tills något händer.

De där defekterna blir fler och svårare att skyla över. Efter hand som systemet börjar användas i skarpt läge så blir felen en källa till oro och problem. Allt mer resurser läggs på att få bort dem. Trots att teamet rusar vidare i samma höga tempo så levererar de färre och färre funktioner. De börjar bli defensiva och komma med invecklade förklaringar till varför det och det kravet inte kan tillgodoses och varför den och den funktionen tar längre tid än väntat att utveckla. Det är tecknen på teknisk skuld vi börjar se. Men till skillnad från syreskulden som ger en omedelbar och distinkt smärta, så ger den tekniska skulden en mer vag och obestämd smärta. Varken projektledare, produktägare eller finansiärer skrattar längre, men var gör det egentligen ont? Kanske behövs fler utvecklare? Kanske behövs bättre utvecklare? Kanske måste de motiveras mer? Eller drivas på hårdare? Kanske bör de jobba annorlunda?

I det här läget är det vanligt att utvecklare byts ut mot nya med snyggare CV’n. Inkörda processer och metoder ändras eller byts ut mot helt nya. Stressen ökar. Rädslan att göra fel ökar. Den som ändå dristar sig att lägga sin hårt pressade tid på att reda ut gamla kodhärvor som hjälpligt fungerar får ofta skulden när nya defekter blir synliga för användarna. Resten av teamet lär sig att undvika de rötangripna delarna för att istället måla över sprickorna och sleva på med ny kod ovanpå den som har börjat flagna. Tiden det tar att utveckla varje ny funktion växer sakta men säkert mot oändligheten. Projektet har inlett sin spiralbana mot de misslyckade projektens svarta hål.

Tyvärr är ovanstående scenario inte särskilt ovanligt. Desto ovanligare är att boven i dramat – den tekniska skulden, faktiskt får skulden för misslyckandet. Det finns ingen kropp som känner koden fräta i sin ådror. Det är svårt att mäta teknisk skuld och det är än svårare att leda orsakssambandet mellan den tekniska skulden och den minskade produktiviteten i bevis. Att uppleva smärtan av den tekniska skulden och sätta den i samband med den låga produktiviteten kräver både erfarenhet och lyhördhet.

De som lär sig känna igen kodsyrasmärtan först är utvecklarna i projektet. De upplever hur de får lägga allt större del av sin tid på att försöka förstå någon annan programmerares invecklade kodhärva och allt mindre tid åt att lösa nya intressanta problem åt produktägaren. Till att börja med kan det vara lätt att skylla problemen på de andra, uppenbart mindre bemedlade, projektdeltagarna som inte kan skriva vettig kod. Tills utvecklaren märker att det allt som oftast är den själv som har bidragit till den obegripliga kodhärvan. Det är nu den viktiga insikten om teknisk skuld börjar ta form.

Så det lite mer erfarna utvecklarteamet har ofta programmerare som förstår att man måste hålla ett lagom högt tempo i ett projekt om det ska vara uthålligt i längden. Och att kodsyran, det vill säga den tekniska skulden, kontinuerligt måste hållas på en kontrollerad nivå genom ständig ansning och anpassning av den befintliga kodbasen. Varianter på Scoutregeln hörs citeras: ”Checka in koden i lite bättre skick än du checkade ut den.” Tyvärr är det inte alltid att de här insikterna når projektledaren eller produktägaren, som ju befinner sig längre från själva roten till problemet. Det kan få till följd att fel teammedlemmar premieras för fel saker. Den som snabbt bygger nya funktioner men lämnar rörig kod efter sig får beröm för sin produktivitet. De som kommer efter och städar upp och kanske samtidigt springer på en mina som leder till en ny synlig defekt får förmaningar av typen: ”Laga inte det som inte är trasigt”.

Om inte utvecklarteamet är starkt nog att stå emot den här negativa feedbackloopen så kan det lätt förfalla till det mindre erfarna teamets arbetssätt: Lappa, laga och bygg på så länge det går (och lämna skeppet innan det märks att det har börjat sjunka). Men är teamet starkt nog så självorganiserar det sig till en effektiv maskin som har pli på de mindre erfarna utvecklarna som vill rusa och levererar det produktägaren behöver i den takt som är optimal, strax under teamets tröskelfart.

En del av utvecklingsteamets ansvar är således, inte bara att stå emot somliga projektledares påtryckningar att göra fel saker, utan även att utbilda projektledaren i teknisk skuld och om teamets tröskelfart. Teamet måste vara för projektet och projektledaren vad musklerna är för kroppen och hjärnan – det organ som sänder smärtsignaler genom hela organisationen när skulden börjar närma sig smärtgränsen och som belönar med endorfiner, beröm och god stämning när den får signaler uppifrån att hålla ett högt men kontrollerat tempo och hålla sin kodbas i trim.

Produktägarens ansvar blir då, snarare än att detaljreglera hur teamet ska lösa dess behov, att sätta upp snitslarna längs banan och tala om var målet ligger så att teamet vet åt vilket håll och hur långt det ska springa. Och projektledarens ansvar blir, snarare än att driva på (det gör teamet så bra själva), att serva med vätskekontroller och allt som teamet behöver längs vägen för att prestera på topp. Allt för ofta ser man dock utvecklarteam som får springa utan snitslar eller mål och utan vätskekontroller, men med tydliga krav på att göra nästa hundring så fort de bara kan, och sen nästa, och nästa. Men så enkelt är det inte att vinna ett långlopp och så enkelt är det inte heller att bygga hållbar mjukvara med kvalité.

Så, det är dags att vi i branchen börjar betrakta oss mer som långdistansare än kortdistansare. Sprintprogrammeraren får kanske spurtpriset men långdistansutvecklaren vinner i det långa loppet.